Skip to content

Commit

Permalink
CM-421: added possibility to add new group, fixing move to other grou…
Browse files Browse the repository at this point in the history
…p picker (#83)
  • Loading branch information
sniedzielski authored May 29, 2024
1 parent 2c4554e commit 676f3f9
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 32 deletions.
26 changes: 25 additions & 1 deletion src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import { ACTION_TYPE } from './reducer';
import {
CLEAR, ERROR, REQUEST, SET, SUCCESS,
} from './util/action-type';
import {ACCEPT, APPROVED, FAILED, REJECT} from "./constants";
import {
ACCEPT, APPROVED, FAILED, REJECT,
} from './constants';

const WORKFLOWS_FULL_PROJECTION = () => [
'name',
Expand Down Expand Up @@ -245,6 +247,13 @@ function formatGroupGQL(group, groupIndividualId = null) {
${groupIndividualId ? `groupIndividualId: "${groupIndividualId}"` : ''}`;
}

function formatCreateGroupGQL(group) {
return `
${group?.code ? `code: "${group.code}"` : ''}
${'individualsData: []'}
`;
}

function formatIndividualGQL(individual) {
return `
${individual?.id ? `id: "${individual.id}"` : ''}
Expand Down Expand Up @@ -370,6 +379,21 @@ export function updateGroup(group, clientMutationLabel) {
);
}

export function createGroup(group, clientMutationLabel) {
const mutation = formatMutation('createGroup', formatCreateGroupGQL(group), clientMutationLabel);
const requestedDateTime = new Date();
return graphql(
mutation.payload,
[REQUEST(ACTION_TYPE.MUTATION), SUCCESS(ACTION_TYPE.CREATE_GROUP), ERROR(ACTION_TYPE.MUTATION)],
{
actionType: ACTION_TYPE.CREATE_GROUP,
clientMutationId: mutation.clientMutationId,
clientMutationLabel,
requestedDateTime,
},
);
}

export function fetchPendingGroupUploads(variables) {
return graphqlWithVariables(
`
Expand Down
4 changes: 2 additions & 2 deletions src/components/GroupHeadPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const styles = (theme) => ({
class GroupHeadPanel extends FormPanel {
render() {
const {
edited, classes, mandatoryFieldsEmpty,
edited, classes, mandatoryFieldsEmpty, readOnly,
} = this.props;
const group = { ...edited };
return (
Expand Down Expand Up @@ -55,7 +55,7 @@ class GroupHeadPanel extends FormPanel {
<Grid container className={classes.item}>
<Grid item xs={3} className={classes.item}>
<TextInput
readOnly
readOnly={readOnly}
module="individual"
label="group.code"
onChange={(v) => this.updateAttribute('code', v)}
Expand Down
2 changes: 2 additions & 0 deletions src/components/GroupTabPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ function GroupTabPanel({
groupIndividualIds,
groupId,
}) {
if (!groupId) return null;

const [activeTab, setActiveTab] = useState(individual ? BENEFIT_PLANS_LIST_TAB_VALUE : INDIVIDUALS_LIST_TAB_VALUE);

const isSelected = (tab) => tab === activeTab;
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const BENEFIT_PLAN_TABS_LABEL_CONTRIBUTION_KEY = 'individual.BenefitPlans
export const BENEFIT_PLAN_TABS_PANEL_CONTRIBUTION_KEY = 'individual.BenefitPlansListTabPanel';
export const TASK_CONTRIBUTION_KEY = 'tasksManagement.tasks';
export const BENEFITS_CONTRIBUTION_KEY = 'payroll.benefitConsumptionPayrollSearcher';
export const GROUP_ROUTE_GROUP = 'individual.route.group';

export const BENEFICIARY_STATUS = {
POTENTIAL: 'POTENTIAL',
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ import IndividualPicker from './pickers/IndividualPicker';
import {
GroupUploadConfirmationPanel,
GroupUploadResolutionItemFormatters,
GroupUploadResolutionTaskTableHeaders
} from "./components/tasks/GroupImportTasks";
GroupUploadResolutionTaskTableHeaders,
} from './components/tasks/GroupImportTasks';
import EnrollmentGroupPage from './pages/EnrollmentGroupPage';
import GroupMenu from './components/dialogs/GroupMenu';

Expand Down
43 changes: 28 additions & 15 deletions src/pages/GroupPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import DeleteIcon from '@material-ui/icons/Delete';
import { RIGHT_GROUP_CREATE, RIGHT_GROUP_SEARCH } from '../constants';
import {
fetchGroup, deleteGroup, updateGroup, clearGroup, createGroupAndMoveIndividual,
createGroup,
} from '../actions';
import GroupHeadPanel from '../components/GroupHeadPanel';
import { ACTION_TYPE } from '../reducer';
Expand All @@ -37,6 +38,7 @@ function GroupPage({
group,
fetchGroup,
deleteGroup,
createGroup,
updateGroup,
coreConfirm,
clearConfirm,
Expand Down Expand Up @@ -108,18 +110,25 @@ function GroupPage({

const handleSave = () => {
setReadOnly(true);
if (editedGroup?.id) {
updateGroup(
editedGroup,
formatMessageWithValues(intl, 'individual', 'group.update.mutationLabel', {
id: group?.id,
}),
);
} else if (editedGroupIndividual?.id) {
createGroupAndMoveIndividual(
if (groupUuid) {
if (editedGroup?.id) {
updateGroup(
editedGroup,
formatMessageWithValues(intl, 'individual', 'group.update.mutationLabel', {
id: group?.id,
}),
);
} else if (editedGroupIndividual?.id) {
createGroupAndMoveIndividual(
editedGroup,
editedGroupIndividual.id,
formatMessageWithValues(intl, 'individual', 'group.createGroupAndMoveIndividual.mutationLabel'),
);
}
} else {
createGroup(
editedGroup,
editedGroupIndividual.id,
formatMessageWithValues(intl, 'individual', 'group.createGroupAndMoveIndividual.mutationLabel'),
formatMessageWithValues(intl, 'socialProtection', 'group.create.mutationLabel', titleParams(editedGroup)),
);
}
};
Expand All @@ -141,7 +150,10 @@ function GroupPage({
);
};

const canAdd = () => rights.includes(RIGHT_GROUP_CREATE) && editedGroupIndividual && !readOnly;
const canAdd = () => {
if (groupUuid) return rights.includes(RIGHT_GROUP_CREATE) && editedGroupIndividual && !readOnly;
return rights.includes(RIGHT_GROUP_CREATE) && !!editedGroup?.code;
};

const actions = [
!!group && {
Expand All @@ -165,8 +177,8 @@ function GroupPage({
onEditedChanged={setEditedGroup}
back={back}
mandatoryFieldsEmpty={isMandatoryFieldsEmpty}
canSave={canSave}
save={groupUuid ? handleSave : null}
canSave={groupUuid ? canSave : canAdd}
save={handleSave}
HeadPanel={GroupHeadPanel}
Panels={[GroupTabPanel]}
rights={rights}
Expand All @@ -176,7 +188,7 @@ function GroupPage({
add={canAdd() ? handleSave : null}
setEditedGroupIndividual={setEditedGroupIndividual}
editedGroupIndividual={editedGroupIndividual}
readOnly={readOnly}
readOnly={!!groupUuid}
groupIndividualIds={groupIndividualIds}
groupId={groupUuid}
/>
Expand All @@ -201,6 +213,7 @@ const mapStateToProps = (state, props) => ({
const mapDispatchToProps = (dispatch) => bindActionCreators({
fetchGroup,
deleteGroup,
createGroup,
updateGroup,
clearGroup,
createGroupAndMoveIndividual,
Expand Down
27 changes: 24 additions & 3 deletions src/pages/GroupsPage.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React from 'react';
import { Helmet, withModulesManager, formatMessage } from '@openimis/fe-core';
import {
Helmet, withModulesManager, withTooltip, formatMessage, historyPush,
} from '@openimis/fe-core';
import { injectIntl } from 'react-intl';
import { withTheme, withStyles } from '@material-ui/core/styles';
import { connect } from 'react-redux';
import { RIGHT_GROUP_SEARCH } from '../constants';
import { Fab } from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import { GROUP_ROUTE_GROUP, RIGHT_GROUP_CREATE, RIGHT_GROUP_SEARCH } from '../constants';
import GroupSearcher from '../components/GroupSearcher';

const styles = (theme) => ({
Expand All @@ -12,13 +16,30 @@ const styles = (theme) => ({
});

function GroupsPage(props) {
const { intl, classes, rights } = props;
const {
intl, classes, modulesManager, history, rights,
} = props;

const onAdd = () => historyPush(
modulesManager,
history,
GROUP_ROUTE_GROUP,
);

return (
rights.includes(RIGHT_GROUP_SEARCH) && (
<div className={classes.page}>
<Helmet title={formatMessage(intl, 'individual', 'groups.pageTitle')} />
<GroupSearcher rights={rights} isModalEnrollment={false} />
{rights.includes(RIGHT_GROUP_CREATE)
&& withTooltip(
<div className={classes.fab}>
<Fab color="primary" onClick={onAdd}>
<AddIcon />
</Fab>
</div>,
formatMessage(intl, 'individual', 'createButton.tooltip'),
)}
</div>
)
);
Expand Down
1 change: 0 additions & 1 deletion src/pickers/GroupIndividualRecipientTypePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ function GroupIndividualRecipientTypePicker(props) {
const {
required, readOnly, onChange, value, nullLabel, withLabel,
} = props;
console.log(value)
return (
<ConstantBasedPicker
module="individual"
Expand Down
20 changes: 13 additions & 7 deletions src/pickers/GroupPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ function GroupPicker(props) {
const errorGroups = useSelector((state) => state.individual.errorGroups);
const groups = useSelector((state) => state.individual.groups);
const [group, setGroup] = useState(null);
// eslint-disable-next-line no-unused-vars
const [currentString, setCurrentString] = useState('');
const [filters, setFilters] = useState(['isDeleted: false']);

useEffect(() => {
if (!fetchingGroups && !fetchedGroups) {
dispatch(fetchGroups({}));
}
}, []);
dispatch(fetchGroups(filters));
}, [filters]);

const groupLabel = (option) => option.id;
const groupLabel = (option) => option.code;

const getGroupsWithoutCurrentGroup = (options) => options.filter(
(option) => option?.id !== groupIndividual?.group?.id,
(option) => option?.code !== groupIndividual?.group?.code,
);

const handleChange = (group) => {
Expand All @@ -48,11 +49,16 @@ function GroupPicker(props) {
withPlaceholder={withPlaceholder}
options={getGroupsWithoutCurrentGroup(groups)}
isLoading={fetchingGroups}
setCurrentString={setCurrentString}
isFetched={fetchedGroups}
value={group}
getOptionLabel={groupLabel}
onChange={handleChange}
onInputChange={() => null}
onInputChange={
(search) => {
if (search !== undefined) setFilters([`code_Icontains: "${search}"`, 'isDeleted: false']);
}
}
/>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/pickers/IndividualPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TextField, Tooltip } from '@material-ui/core';
import {
Autocomplete, useModulesManager,
useTranslations, useGraphqlQuery,
decodeId
decodeId,
} from '@openimis/fe-core';
import { INDIVIDUALS_QUANTITY_LIMIT } from '../constants';

Expand Down
3 changes: 3 additions & 0 deletions src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const ACTION_TYPE = {
UPDATE_INDIVIDUAL: 'INDIVIDUAL_UPDATE_INDIVIDUAL',
UPDATE_GROUP_INDIVIDUAL: 'GROUP_INDIVIDUAL_UPDATE_GROUP_INDIVIDUAL',
UPDATE_GROUP: 'GROUP_UPDATE_GROUP',
CREATE_GROUP: 'CREATE_GROUP',
CREATE_GROUP_AND_MOVE_INDIVIDUAL: 'CREATE_GROUP_AND_MOVE_INDIVIDUAL',
GROUP_EXPORT: 'GROUP_EXPORT',
INDIVIDUAL_EXPORT: 'INDIVIDUAL_EXPORT',
Expand Down Expand Up @@ -654,6 +655,8 @@ function reducer(
return dispatchMutationResp(state, 'deleteGroup', action);
case SUCCESS(ACTION_TYPE.UPDATE_GROUP):
return dispatchMutationResp(state, 'updateGroup', action);
case SUCCESS(ACTION_TYPE.CREATE_GROUP):
return dispatchMutationResp(state, 'createGroup', action);
case SUCCESS(ACTION_TYPE.CREATE_GROUP_AND_MOVE_INDIVIDUAL):
return dispatchMutationResp(state, 'createGroupAndMoveIndividual', action);
case SUCCESS(ACTION_TYPE.RESOLVE_TASK):
Expand Down
3 changes: 3 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@
"id": "ID",
"head": "Head",
"code": "Code",
"create": {
"mutationLabel": "Created Group {id}"
},
"noHeadSpecified": "head not specified",
"individual.firstName": "Individual First Name",
"individual.lastName": "Individual Last Name",
Expand Down

0 comments on commit 676f3f9

Please sign in to comment.