Skip to content

Commit

Permalink
Merge pull request #4 from openimis/feature/CM-454
Browse files Browse the repository at this point in the history
CM-454: (FE): Develop the summary display of potential duplicates.
  • Loading branch information
jdolkowski authored Jan 17, 2024
2 parents 32b69c1 + 9658f21 commit b53053d
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 2 deletions.
15 changes: 15 additions & 0 deletions src/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {
graphql,
formatQuery,
} from '@openimis/fe-core';
import { ACTION_TYPE } from './reducer';

const DEDUPLICATION_SUMMARY_FULL_PROJECTION = () => [
'rows {count, columnValues}',
];

// eslint-disable-next-line import/prefer-default-export
export function fetchDeduplicationSummary(params) {
const payload = formatQuery('beneficiaryDeduplicationSummary', params, DEDUPLICATION_SUMMARY_FULL_PROJECTION());
return graphql(payload, ACTION_TYPE.GET_DEDUPLICATION_SUMMARY);
}
26 changes: 25 additions & 1 deletion src/components/dialogs/DeduplicationFieldSelectionDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { withTheme, withStyles } from '@material-ui/core/styles';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import DeduplicationFieldPicker from '../pickers/DeduplicationFieldPicker';
import DeduplicationSummaryDialog from './DeduplicationSummaryDialog';

const styles = (theme) => ({
item: theme.paper.item,
Expand All @@ -27,8 +28,10 @@ function DeduplicationFieldSelectionDialog({

const [selectedValues, setSelectedValues] = useState([]);
const [isOpen, setIsOpen] = useState(false);
const [showSummaryDialog, setShowSummaryDialog] = useState(false);

const handleOpen = () => {
setSelectedValues([]);
setIsOpen(true);
};

Expand All @@ -40,6 +43,15 @@ function DeduplicationFieldSelectionDialog({
setSelectedValues(selectedOptions);
};

const handleOpenNextDialog = () => {
setShowSummaryDialog(true);
handleClose();
};

const handleSummaryDialogClose = () => {
setShowSummaryDialog(false);
};

return (
<>
<Button
Expand Down Expand Up @@ -91,10 +103,11 @@ function DeduplicationFieldSelectionDialog({
<div>
<div style={{ float: 'left' }}>
<Button
onClick={() => []}
onClick={handleOpenNextDialog}
variant="outlined"
autoFocus
style={{ margin: '0 16px' }}
disabled={!selectedValues.length}
>
{formatMessage(intl, 'deduplication', 'deduplicate.button.showDuplicateSummary')}
</Button>
Expand All @@ -116,6 +129,17 @@ function DeduplicationFieldSelectionDialog({
</div>
</DialogActions>
</Dialog>

{showSummaryDialog && (
<DeduplicationSummaryDialog
intl={intl}
benefitPlan={benefitPlan}
handleClose={handleSummaryDialogClose}
showSummaryDialog={showSummaryDialog}
selectedValues={selectedValues}
setSelectedValues={setSelectedValues}
/>
)}
</>
);
}
Expand Down
105 changes: 105 additions & 0 deletions src/components/dialogs/DeduplicationSummaryDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from 'react';
import { injectIntl } from 'react-intl';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import { formatMessage } from '@openimis/fe-core';
import { withTheme, withStyles } from '@material-ui/core/styles';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import DeduplicationSummaryTable from '../tables/DeduplicationSummaryTable';
import { fetchDeduplicationSummary } from '../../actions';

const styles = (theme) => ({
item: theme.paper.item,
});

function DeduplicationSummaryDialog({
intl,
benefitPlan,
handleClose,
showSummaryDialog,
selectedValues,
}) {
if (!benefitPlan) return null;

const columns = selectedValues.map((value) => value.id);
const columnParam = `columns: ${JSON.stringify(columns)}`;

return (
<Dialog
open={showSummaryDialog}
onClose={handleClose}
PaperProps={{
style: {
width: 900,
maxWidth: 900,
},
}}
>
<DialogTitle
style={{
marginTop: '10px',
}}
>
{formatMessage(intl, 'deduplication', 'deduplicate.summary.title')}
</DialogTitle>
<DialogContent>
<DeduplicationSummaryTable
columnParam={columnParam}
benefitPlan={benefitPlan}
fetchDeduplicationSummary={fetchDeduplicationSummary}
/>
</DialogContent>
<DialogActions
style={{
display: 'inline',
paddingLeft: '10px',
marginTop: '25px',
marginBottom: '15px',
}}
>
<div>
<div style={{ float: 'left' }}>
<Button
onClick={() => []}
variant="outlined"
autoFocus
style={{ margin: '0 16px' }}
>
{formatMessage(intl, 'deduplication', 'deduplicate.button.createDeduplicationReviewTask')}
</Button>
</div>
<div style={{
float: 'right',
paddingRight: '16px',
}}
>
<Button
onClick={handleClose}
variant="outlined"
autoFocus
style={{ margin: '0 16px' }}
>
{formatMessage(intl, 'deduplication', 'deduplicate.button.cancel')}
</Button>
</div>
</div>
</DialogActions>
</Dialog>
);
}

const mapStateToProps = (state) => ({
rights: !!state.core && !!state.core.user && !!state.core.user.i_user ? state.core.user.i_user.rights : [],
confirmed: state.core.confirmed,
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
}, dispatch);

export default injectIntl(
withTheme(withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(DeduplicationSummaryDialog))),
);
92 changes: 92 additions & 0 deletions src/components/tables/DeduplicationSummaryTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import {
TableContainer, TableHead, TableBody, Table, TableCell, TableRow, Paper,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';

import { useModulesManager, ProgressOrError, useTranslations } from '@openimis/fe-core';
import { MODULE_NAME } from '../../constants';

const useStyles = makeStyles((theme) => ({
footer: {
marginInline: 16,
marginBlock: 12,
},
headerTitle: theme.table.title,
actionCell: {
width: 60,
},
header: theme.table.header,
}));

const DEDUPLICATION_SUMMARY_HEADERS = [
'deduplication.deduplicationSummaryTable.group',
'deduplication.deduplicationSummaryTable.duplicates',
];

function DeduplicationSummaryTable({
columnParam, benefitPlan, fetchDeduplicationSummary,
}) {
const dispatch = useDispatch();
const modulesManager = useModulesManager();
const classes = useStyles();
const { formatMessage } = useTranslations(MODULE_NAME, modulesManager);
const {
fetchingSummary, summary, errorSummary,
} = useSelector((store) => store.deduplication);

useEffect(() => {
const params = [columnParam, `benefitPlanId: "${benefitPlan.id}"`];
dispatch(fetchDeduplicationSummary(params));
}, []);

function reshapeColumnValues(inputString) {
const columnValues = JSON.parse(inputString);
const formattedValues = Object.entries(columnValues).map(([key, value]) => {
const formattedKey = key.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
const formattedValue = value !== null ? value : 'null';
return `${formattedKey}: ${formattedValue}`;
});
const resultString = formattedValues.join(', ');
return resultString;
}

return (
<TableContainer component={Paper}>
<Table size="small">
<TableHead className={classes.header}>
<TableRow className={classes.headerTitle}>
{DEDUPLICATION_SUMMARY_HEADERS.map((header) => (
<TableCell key={header}>
{' '}
{formatMessage(header)}
{' '}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
<ProgressOrError progress={fetchingSummary} error={errorSummary} />
{summary?.map((result) => (
<TableRow key={result?.uuid}>
<TableCell>
{' '}
{reshapeColumnValues(result.columnValues)}
{' '}
</TableCell>
<TableCell>
{' '}
{result.count}
{' '}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}

export default DeduplicationSummaryTable;
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import messagesEn from './translations/en.json';
import DeduplicationFieldSelectionDialog from './components/dialogs/DeduplicationFieldSelectionDialog';
import reducer from './reducer';

const DEFAULT_CONFIG = {
translations: [{ key: 'en', messages: messagesEn }],
reducers: [{ key: 'deduplication', reducer }],
'deduplication.deduplicationFieldSelectionDialog': [
DeduplicationFieldSelectionDialog,
],
Expand Down
55 changes: 55 additions & 0 deletions src/reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Disabled due to consistency with other modules
/* eslint-disable default-param-last */

import {
formatServerError,
} from '@openimis/fe-core';
import {
ERROR, REQUEST, SUCCESS,
} from './util/action-type';

export const ACTION_TYPE = {
GET_DEDUPLICATION_SUMMARY: 'DEDUPLICATION_GET_DEDUPLICATION_SUMMARY',
};

function reducer(
state = {
submittingMutation: false,
mutation: {},
fetchingSummary: false,
errorSummary: null,
fetchedSummary: false,
summary: [],
},
action,
) {
switch (action.type) {
case REQUEST(ACTION_TYPE.GET_DEDUPLICATION_SUMMARY):
return {
...state,
fetchingSummary: true,
fetchedSummary: false,
summary: null,
};
case SUCCESS(ACTION_TYPE.GET_DEDUPLICATION_SUMMARY):
return {
...state,
fetchingSummary: false,
fetchedSummary: true,
summary: action.payload.data.beneficiaryDeduplicationSummary.rows?.map((row) => ({
...row,
})),
errorSummary: null,
};
case ERROR(ACTION_TYPE.GET_DEDUPLICATION_SUMMARY):
return {
...state,
fetchingSummary: false,
errorSummary: formatServerError(action.payload),
};
default:
return state;
}
}

export default reducer;
6 changes: 5 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
"deduplication.deduplicate.button.cancel": "Cancel",
"deduplication.deduplicate.fields": "Duplicate Detection Field Selection",
"deduplication.deduplicate.fields.placeholder": "Duplicate Detection Field Selection",
"deduplicate.button.showDuplicateSummary": "Show Duplicate Summary"
"deduplication.deduplicate.button.showDuplicateSummary": "Show Duplicate Summary",
"deduplication.deduplicate.summary.title": "Deduplication Summary",
"deduplication.deduplicate.button.createDeduplicationReviewTask": "Create Deduplication Review Tasks",
"deduplication.deduplicationSummaryTable.group": "Group",
"deduplication.deduplicationSummaryTable.duplicates": "Duplicates"
}
5 changes: 5 additions & 0 deletions src/util/action-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const REQUEST = (actionTypeName) => `${actionTypeName}_REQ`;
export const SUCCESS = (actionTypeName) => `${actionTypeName}_RESP`;
export const ERROR = (actionTypeName) => `${actionTypeName}_ERR`;
export const CLEAR = (actionTypeName) => `${actionTypeName}_CLEAR`;
export const VALID = (actionTypeName) => `${actionTypeName}_VALID`;
24 changes: 24 additions & 0 deletions src/util/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const defaultPageStyles = (theme) => ({
page: theme.page,
});

export const defaultFilterStyles = (theme) => ({
form: {
padding: 0,
},
item: {
padding: theme.spacing(1),
},
});

export const defaultHeadPanelStyles = (theme) => ({
tableTitle: theme.table.title,
item: theme.paper.item,
fullHeight: {
height: '100%',
},
});

export const defaultDialogStyles = (theme) => ({
item: theme.paper.item,
});

0 comments on commit b53053d

Please sign in to comment.