From 2c89f768b0b9df8ed5ddf2cba8492eef347059e2 Mon Sep 17 00:00:00 2001 From: NyashaMuusha Date: Mon, 12 Aug 2024 13:03:01 +0200 Subject: [PATCH 1/6] added handle add row function --- .../src/pages/settings/common/Common.tsx | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx index 055ad8a30..a1d82b45c 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx @@ -17,8 +17,9 @@ import CancelIcon from '@mui/icons-material/Close' import { EditToolbar } from 'components/shared/EditToolBar' import { processIndex, toSnakeCase, transformFieldName } from 'utils/helpers' import { useConfiguration } from 'hooks/useUIConfiguration' -import { Configuration, LinkMetaData } from 'types/Configuration' +import { Configuration, Field, LinkMetaData } from 'types/Configuration' import { RowData } from '../deterministic/SourceView' +import { Button } from '@mui/material' const CommonSettings = () => { const [rows, setRows] = useState([]) @@ -131,7 +132,34 @@ const CommonSettings = () => { handleUpdateConfiguration(updatedRow, updatedRow.rowIndex) return { ...updatedRow, id } as RowData } - + const handleAddNewRow = () => { + const newRow: Field = { + id: (rows.length + 1).toString(), + fieldName: '', + fieldType: 'String', + linkMetaData: { + comparison: '', + comparisonLevels: [], + m: 0, + u: 0 + } + } + console.log(' i was clicked', newRow) + if (configuration) { + const newConfiguration = { + ...configuration, + demographicFields: [...configuration.demographicFields, newRow] + } + + localStorage.setItem('configuration', JSON.stringify(newConfiguration)) + setConfiguration(newConfiguration) + setRows((prevRows: any) => [...prevRows, newRow]) + } else { + console.error("Configuration is null. Cannot add new row.") + } + + } + const columns: GridColDef[] = [ { field: 'fieldName', @@ -248,6 +276,7 @@ const CommonSettings = () => { width: '100%' }} > + {configuration && ( Date: Wed, 21 Aug 2024 11:38:00 +0200 Subject: [PATCH 2/6] updated common settings --- .../JeMPI_UI/src/pages/settings/Settings.tsx | 7 +- .../src/pages/settings/common/Common.tsx | 100 +++++++++++------- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx index 431e4c1c1..464bc91d2 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx @@ -15,9 +15,11 @@ import { generateId } from 'utils/helpers' import Probabilistic from './probabilistic/Probabilistic' import { useConfig } from 'hooks/useConfig' import { useSnackbar } from 'notistack' +import { useConfiguration } from 'hooks/useUIConfiguration' const Settings = () => { const [value, setValue] = useState(0) + const {configuration} = useConfiguration() const [configurationData, setConfigurationData] = useState(() => { const storedData = localStorage.getItem('configuration') return storedData @@ -34,6 +36,8 @@ const Settings = () => { const { enqueueSnackbar } = useSnackbar() const handleSave = async () => { + console.log(`${configuration?.demographicFields.some(field => field.fieldName.toLowerCase() === 'unknown') , configurationData.demographicFields.some(field => field.fieldName === '')} + }`) setIsSaving(true) const response = await apiClient.saveConfiguration() setIsSaving(false) @@ -74,6 +78,7 @@ const Settings = () => { if (storedData) { setConfigurationData(generateId(JSON.parse(storedData))) } + console.log(configurationData.demographicFields) }, []) return ( @@ -160,7 +165,7 @@ const Settings = () => { variant="contained" color="primary" onClick={handleSave} - disabled={isSaving} + disabled={isSaving || configuration?.demographicFields.some(field => field.fieldName.toLowerCase() === 'unknown_field') || configurationData.demographicFields.some(field => field.fieldName === '')} > {isSaving ? 'Saving...' : 'Save'} diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx index a1d82b45c..babda0f3a 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx @@ -18,13 +18,15 @@ import { EditToolbar } from 'components/shared/EditToolBar' import { processIndex, toSnakeCase, transformFieldName } from 'utils/helpers' import { useConfiguration } from 'hooks/useUIConfiguration' import { Configuration, Field, LinkMetaData } from 'types/Configuration' -import { RowData } from '../deterministic/SourceView' import { Button } from '@mui/material' +import { RowData } from '../deterministic/SourceView' +import { useSnackbar } from 'notistack' const CommonSettings = () => { const [rows, setRows] = useState([]) const { configuration, setConfiguration } = useConfiguration() const [rowModesModel, setRowModesModel] = useState({}) + const { enqueueSnackbar } = useSnackbar() useEffect(() => { if (configuration && configuration.demographicFields) { @@ -122,16 +124,24 @@ const CommonSettings = () => { const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => { setRowModesModel(newRowModesModel) } + - const processRowUpdate = (newRow: GridRowModel) => { - const { id, ...updatedRow } = newRow + const processRowUpdate = (newRow: GridRowModel, oldRow: GridRowModel) => { + const isFieldNameValid = newRow?.fieldName && newRow.fieldName.toLowerCase() !== 'unknown_field'; + + if (!isFieldNameValid) { + enqueueSnackbar('Field name cannot be empty or unknown', { variant: 'error' }); + } + + const { id, ...updatedRow } = newRow; const updatedRows = rows.map((row: { id: any }) => row.id === id ? ({ ...updatedRow, id } as RowData) : row - ) - setRows(updatedRows) - handleUpdateConfiguration(updatedRow, updatedRow.rowIndex) - return { ...updatedRow, id } as RowData - } + ); + + setRows(updatedRows); + handleUpdateConfiguration(updatedRow, updatedRow.rowIndex); + return { ...updatedRow, id } as RowData; + }; const handleAddNewRow = () => { const newRow: Field = { id: (rows.length + 1).toString(), @@ -142,24 +152,28 @@ const CommonSettings = () => { comparisonLevels: [], m: 0, u: 0 - } + }, } - console.log(' i was clicked', newRow) + if (configuration) { const newConfiguration = { ...configuration, demographicFields: [...configuration.demographicFields, newRow] } - + localStorage.setItem('configuration', JSON.stringify(newConfiguration)) setConfiguration(newConfiguration) setRows((prevRows: any) => [...prevRows, newRow]) + setRowModesModel(prevRowModesModel => ({ + ...prevRowModesModel, + + [(newRow.id) as string]: { mode: GridRowModes.Edit, fieldToFocus: 'fieldName' } + })) } else { console.error("Configuration is null. Cannot add new row.") } - } - + const columns: GridColDef[] = [ { field: 'fieldName', @@ -177,7 +191,7 @@ const CommonSettings = () => { width: 180, align: 'center', headerAlign: 'center', - editable: false + editable: true, }, { field: 'indexGoldenRecord', @@ -232,17 +246,19 @@ const CommonSettings = () => { width: 300, cellClassName: 'actions', getActions: ({ id }) => { - const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit + const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; + const row = rows.find((row: any) => row.id === id); + const isFieldNameValid = row?.fieldName && row.fieldName.toLowerCase() !== 'unknown_field'; + if (isInEditMode) { return [ } id="save-button" label="Save" - sx={{ - color: 'white' - }} + sx={{ color: 'white' }} onClick={handleSaveClick(id)} + disabled={!isFieldNameValid} />, } @@ -251,10 +267,11 @@ const CommonSettings = () => { className="textPrimary" onClick={handleCancelClick(id)} color="inherit" + disabled={!isFieldNameValid} /> - ] + ]; } - + return [ } @@ -264,8 +281,9 @@ const CommonSettings = () => { onClick={handleEditClick(id)} color="inherit" /> - ] + ]; } + } ] @@ -276,24 +294,30 @@ const CommonSettings = () => { width: '100%' }} > - + + + + {configuration && ( - row.id} - slots={{ - toolbar: EditToolbar - }} - slotProps={{ - toolbar: { setRows, setRowModesModel } - }} - /> + { + console.error(error); + }} + getRowId={(row) => row.id} + slots={{ + toolbar: EditToolbar + }} + slotProps={{ + toolbar: { setRows, setRowModesModel } + }} + /> )} ) From f6bdac6db5128b436ce7c32cc9b51c6cc1c9ddbd Mon Sep 17 00:00:00 2001 From: NyashaMuusha Date: Wed, 21 Aug 2024 22:30:08 +0200 Subject: [PATCH 3/6] added add field dialog, updated handle add row --- .../JeMPI_UI/src/pages/settings/Settings.tsx | 4 +- .../src/pages/settings/common/Common.tsx | 203 +++++++++--------- .../src/pages/settings/common/FieldDialog.tsx | 61 ++++++ 3 files changed, 168 insertions(+), 100 deletions(-) create mode 100644 JeMPI_Apps/JeMPI_UI/src/pages/settings/common/FieldDialog.tsx diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx index 464bc91d2..c9f9a5970 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx @@ -36,8 +36,6 @@ const Settings = () => { const { enqueueSnackbar } = useSnackbar() const handleSave = async () => { - console.log(`${configuration?.demographicFields.some(field => field.fieldName.toLowerCase() === 'unknown') , configurationData.demographicFields.some(field => field.fieldName === '')} - }`) setIsSaving(true) const response = await apiClient.saveConfiguration() setIsSaving(false) @@ -165,7 +163,7 @@ const Settings = () => { variant="contained" color="primary" onClick={handleSave} - disabled={isSaving || configuration?.demographicFields.some(field => field.fieldName.toLowerCase() === 'unknown_field') || configurationData.demographicFields.some(field => field.fieldName === '')} + disabled={isSaving} > {isSaving ? 'Saving...' : 'Save'} diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx index babda0f3a..2c7ec8008 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx @@ -1,5 +1,5 @@ -import { useEffect, useState } from 'react' -import Box from '@mui/material/Box' +import { useEffect, useState } from 'react'; +import Box from '@mui/material/Box'; import { DataGrid, GridColDef, @@ -10,121 +10,123 @@ import { GridRowModes, GridRowModesModel, GridActionsCellItem -} from '@mui/x-data-grid' -import EditIcon from '@mui/icons-material/Edit' -import SaveIcon from '@mui/icons-material/Save' -import CancelIcon from '@mui/icons-material/Close' -import { EditToolbar } from 'components/shared/EditToolBar' -import { processIndex, toSnakeCase, transformFieldName } from 'utils/helpers' -import { useConfiguration } from 'hooks/useUIConfiguration' -import { Configuration, Field, LinkMetaData } from 'types/Configuration' -import { Button } from '@mui/material' -import { RowData } from '../deterministic/SourceView' -import { useSnackbar } from 'notistack' +} from '@mui/x-data-grid'; +import EditIcon from '@mui/icons-material/Edit'; +import SaveIcon from '@mui/icons-material/Save'; +import CancelIcon from '@mui/icons-material/Close'; +import { EditToolbar } from 'components/shared/EditToolBar'; +import { processIndex, toSnakeCase, transformFieldName } from 'utils/helpers'; +import { useConfiguration } from 'hooks/useUIConfiguration'; +import { Configuration, Field, LinkMetaData } from 'types/Configuration'; +import { IconButton, Tooltip } from '@mui/material'; +import { RowData } from '../deterministic/SourceView'; +import { useSnackbar } from 'notistack'; +import FieldDialog from './FieldDialog'; +import AddIcon from '@mui/icons-material/Add' const CommonSettings = () => { - const [rows, setRows] = useState([]) - const { configuration, setConfiguration } = useConfiguration() - const [rowModesModel, setRowModesModel] = useState({}) - const { enqueueSnackbar } = useSnackbar() + const [rows, setRows] = useState([]); + const { configuration, setConfiguration } = useConfiguration(); + const [rowModesModel, setRowModesModel] = useState({}); + const [openFieldModal, setOpenFieldModal] = useState(false); + const { enqueueSnackbar } = useSnackbar(); useEffect(() => { if (configuration && configuration.demographicFields) { - const rowData = configuration?.demographicFields.map( + const rowData = configuration.demographicFields.map( (row: any, rowIndex: number) => ({ id: rowIndex + 1, ...row, rowIndex }) - ) - setRows(rowData) + ); + setRows(rowData); } - }, [configuration]) + }, [configuration]); const handleEditClick = (id: GridRowId) => () => { - setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }) - } + setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }); + }; const handleSaveClick = (id: GridRowId) => () => { - setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }) - } + setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); + }; const handleUpdateConfiguration = (updatedRow: any, rowIndex: number) => { - if (!configuration) return + if (!configuration) return; const updatedConfiguration = getUpdatedConfiguration( updatedRow, rowIndex, configuration - ) - localStorage.setItem('configuration', JSON.stringify(updatedConfiguration)) - setConfiguration(updatedConfiguration) + ); + localStorage.setItem('configuration', JSON.stringify(updatedConfiguration)); + setConfiguration(updatedConfiguration); setRows((prevRows: any) => prevRows.map((row: any) => row.id === updatedRow.id ? { ...updatedRow } : row ) - ) - } + ); + }; const getUpdatedConfiguration = ( updatedRow: any, rowIndex: number, currentConfiguration: Configuration ): Configuration => { - const newConfiguration = { ...currentConfiguration } - const fieldName = toSnakeCase(updatedRow.fieldName) + const newConfiguration = { ...currentConfiguration }; + const fieldName = toSnakeCase(updatedRow.fieldName); if (!newConfiguration.demographicFields) { - return currentConfiguration + return currentConfiguration; } - const fieldToUpdate = { ...newConfiguration.demographicFields[rowIndex] } + const fieldToUpdate = { ...newConfiguration.demographicFields[rowIndex] }; if (!fieldToUpdate) { - return currentConfiguration + return currentConfiguration; } - fieldToUpdate.fieldName = fieldName + fieldToUpdate.fieldName = fieldName; if (updatedRow?.indexGoldenRecord) { fieldToUpdate.indexGoldenRecord = `@index(${updatedRow.indexGoldenRecord.replace( ' ', '' - )})` + )})`; } if (updatedRow?.m) { fieldToUpdate.linkMetaData = { ...fieldToUpdate.linkMetaData, m: Number(updatedRow.m) - } as LinkMetaData + } as LinkMetaData; } if (updatedRow?.u) { fieldToUpdate.linkMetaData = { ...fieldToUpdate.linkMetaData, u: Number(updatedRow.u) - } as LinkMetaData + } as LinkMetaData; } - newConfiguration.demographicFields[rowIndex] = fieldToUpdate + newConfiguration.demographicFields[rowIndex] = fieldToUpdate; - return newConfiguration - } + return newConfiguration; + }; const handleCancelClick = (id: GridRowId) => () => { setRowModesModel(prevRowModesModel => { - const newRowModesModel = { ...prevRowModesModel } - delete newRowModesModel[id] - return newRowModesModel - }) - } + const newRowModesModel = { ...prevRowModesModel }; + delete newRowModesModel[id]; + return newRowModesModel; + }); + }; const handleRowEditStop: GridEventListener<'rowEditStop'> = ({ reason }) => - reason === GridRowEditStopReasons.rowFocusOut + reason === GridRowEditStopReasons.rowFocusOut; const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => { - setRowModesModel(newRowModesModel) - } - + setRowModesModel(newRowModesModel); + }; const processRowUpdate = (newRow: GridRowModel, oldRow: GridRowModel) => { const isFieldNameValid = newRow?.fieldName && newRow.fieldName.toLowerCase() !== 'unknown_field'; @@ -142,10 +144,11 @@ const CommonSettings = () => { handleUpdateConfiguration(updatedRow, updatedRow.rowIndex); return { ...updatedRow, id } as RowData; }; - const handleAddNewRow = () => { + + const handleAddNewRow = (fieldName: string) => { const newRow: Field = { id: (rows.length + 1).toString(), - fieldName: '', + fieldName, fieldType: 'String', linkMetaData: { comparison: '', @@ -153,26 +156,25 @@ const CommonSettings = () => { m: 0, u: 0 }, - } + }; if (configuration) { const newConfiguration = { ...configuration, demographicFields: [...configuration.demographicFields, newRow] - } + }; - localStorage.setItem('configuration', JSON.stringify(newConfiguration)) - setConfiguration(newConfiguration) - setRows((prevRows: any) => [...prevRows, newRow]) + localStorage.setItem('configuration', JSON.stringify(newConfiguration)); + setConfiguration(newConfiguration); + setRows((prevRows: any) => [...prevRows, newRow]); setRowModesModel(prevRowModesModel => ({ ...prevRowModesModel, - [(newRow.id) as string]: { mode: GridRowModes.Edit, fieldToFocus: 'fieldName' } - })) + })); } else { - console.error("Configuration is null. Cannot add new row.") + console.error("Configuration is null. Cannot add new row."); } - } + }; const columns: GridColDef[] = [ { @@ -202,8 +204,8 @@ const CommonSettings = () => { headerAlign: 'center', editable: true, valueGetter: params => { - const indexGoldenRecord = params.row.indexGoldenRecord - return processIndex(indexGoldenRecord) + const indexGoldenRecord = params.row.indexGoldenRecord; + return processIndex(indexGoldenRecord); } }, { @@ -215,11 +217,11 @@ const CommonSettings = () => { align: 'center', headerAlign: 'center', valueGetter: params => { - const linkMetaData = params.row.linkMetaData + const linkMetaData = params.row.linkMetaData; if (linkMetaData && typeof linkMetaData.m === 'number') { - return linkMetaData.m.toFixed(7) + return linkMetaData.m.toFixed(7); } - return + return; } }, { @@ -231,9 +233,9 @@ const CommonSettings = () => { align: 'center', headerAlign: 'center', valueGetter: params => { - const linkMetaData = params.row.linkMetaData + const linkMetaData = params.row.linkMetaData; if (linkMetaData && typeof linkMetaData.u === 'number') { - return linkMetaData.u.toFixed(7) + return linkMetaData.u.toFixed(7); } } }, @@ -283,9 +285,8 @@ const CommonSettings = () => { /> ]; } - } - ] + ]; return ( { width: '100%' }} > - - + + + setOpenFieldModal(true)}> + + + - + {configuration && ( - { - console.error(error); - }} - getRowId={(row) => row.id} - slots={{ - toolbar: EditToolbar - }} - slotProps={{ - toolbar: { setRows, setRowModesModel } - }} - /> + { + console.error(error); + }} + getRowId={(row) => row.id} + slots={{ + toolbar: EditToolbar + }} + slotProps={{ + toolbar: { setRows, setRowModesModel } + }} + /> )} - ) -} + ); +}; -export default CommonSettings +export default CommonSettings; diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/FieldDialog.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/FieldDialog.tsx new file mode 100644 index 000000000..20064cf9b --- /dev/null +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/FieldDialog.tsx @@ -0,0 +1,61 @@ +import Dialog from '@mui/material/Dialog'; +import DialogTitle from '@mui/material/DialogTitle'; +import DialogContent from '@mui/material/DialogContent'; +import DialogActions from '@mui/material/DialogActions'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import { useState } from 'react'; +import { DialogContentText } from '@mui/material'; + +interface FieldDialogProps { + openFieldModal: boolean; + setOpenFieldModal: React.Dispatch>; + onSave: (fieldName: string) => void; +} + +export default function FieldDialog({ openFieldModal, setOpenFieldModal, onSave }: FieldDialogProps) { + const [fieldName, setFieldName] = useState(''); + + const handleClose = () => { + setOpenFieldModal(false); + }; + + const handleSave = () => { + onSave(fieldName); + handleClose(); + }; + + return ( + + Add Field Name + + + To add a new field to common settings, please enter a field name. + + setFieldName(e.target.value)} + /> + + + + + + + ); +} From 9aa4d2fdb4abf45a8e35b2cb1d02434c2038b997 Mon Sep 17 00:00:00 2001 From: NyashaMuusha Date: Wed, 21 Aug 2024 22:32:18 +0200 Subject: [PATCH 4/6] removed console log statement --- JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx index c9f9a5970..8101a7abc 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx @@ -76,7 +76,6 @@ const Settings = () => { if (storedData) { setConfigurationData(generateId(JSON.parse(storedData))) } - console.log(configurationData.demographicFields) }, []) return ( From cd9339fddf16a406dd9fec4c9c49a1a61f5b202f Mon Sep 17 00:00:00 2001 From: NyashaMuusha Date: Wed, 28 Aug 2024 10:37:05 +0200 Subject: [PATCH 5/6] updated unit tests --- .../src/pages/settings/common/Common.tsx | 2 +- .../src/test/settings/CommonSettings.test.tsx | 28 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx index 2c7ec8008..c342f37e2 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx @@ -29,7 +29,7 @@ const CommonSettings = () => { const { configuration, setConfiguration } = useConfiguration(); const [rowModesModel, setRowModesModel] = useState({}); const [openFieldModal, setOpenFieldModal] = useState(false); - const { enqueueSnackbar } = useSnackbar(); + const { enqueueSnackbar } = useSnackbar() useEffect(() => { if (configuration && configuration.demographicFields) { diff --git a/JeMPI_Apps/JeMPI_UI/src/test/settings/CommonSettings.test.tsx b/JeMPI_Apps/JeMPI_UI/src/test/settings/CommonSettings.test.tsx index 5700c7a4d..da5d5f889 100644 --- a/JeMPI_Apps/JeMPI_UI/src/test/settings/CommonSettings.test.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/test/settings/CommonSettings.test.tsx @@ -5,12 +5,21 @@ import CommonSettings from 'pages/settings/common/Common'; import mockData from 'services/mockData'; import '@testing-library/jest-dom'; import { useConfiguration } from 'hooks/useUIConfiguration'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ConfigProvider } from 'hooks/useConfig'; +import { BrowserRouter } from 'react-router-dom'; jest.mock('hooks/useUIConfiguration', () => ({ useConfiguration: jest.fn(), })); +const queryClient = new QueryClient({ + defaultOptions: { + queries: {} + } +}) + describe('CommonSettings Component', () => { const configData = mockData.configuration.demographicFields.map((row, index) => ({ ...row, @@ -23,12 +32,27 @@ describe('CommonSettings Component', () => { }); }); it('renders without crashing', () => { - render(); + render( + + + + + + ); }); it('handles edit mode', async () => { - render(); + render( + + + + + + + + ) + const editIcon = document.getElementById('edit-button'); const saveButton = document.getElementById('save-button'); const cancelButton = document.getElementById('cancel-button'); From 1ab378049c7450cfa87c6b84979816115c1fbb15 Mon Sep 17 00:00:00 2001 From: Matthew Erispe Date: Tue, 3 Sep 2024 11:08:17 +0200 Subject: [PATCH 6/6] implement error handling for config update --- .../src/pages/settings/common/Common.tsx | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx index 59cbd3099..5a4eb94eb 100644 --- a/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx +++ b/JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx @@ -25,14 +25,14 @@ import FieldDialog from './FieldDialog' import AddIcon from '@mui/icons-material/Add' const CommonSettings = () => { - const [rows, setRows] = useState([]); - const { configuration, setConfiguration } = useConfiguration(); - const [rowModesModel, setRowModesModel] = useState({}); - const [openFieldModal, setOpenFieldModal] = useState(false); + const [rows, setRows] = useState([]) + const { configuration, setConfiguration } = useConfiguration() + const [rowModesModel, setRowModesModel] = useState({}) + const [openFieldModal, setOpenFieldModal] = useState(false) const { enqueueSnackbar } = useSnackbar() useEffect(() => { - if (configuration && configuration.demographicFields) { + if (configuration?.demographicFields) { const rowData = configuration.demographicFields.map( (row: any, rowIndex: number) => ({ id: rowIndex + 1, @@ -41,33 +41,44 @@ const CommonSettings = () => { disable: row.isDisabled }) ); - setRows(rowData); + setRows(rowData) } - }, [configuration]); + }, [configuration]) const handleEditClick = (id: GridRowId) => () => { - setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }); + setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }) }; const handleSaveClick = (id: GridRowId) => () => { - setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); + setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }) }; const handleUpdateConfiguration = (updatedRow: any, rowIndex: number) => { - if (!configuration) return; - const updatedConfiguration = getUpdatedConfiguration( - updatedRow, - rowIndex, - configuration - ); - localStorage.setItem('configuration', JSON.stringify(updatedConfiguration)); - setConfiguration(updatedConfiguration); - setRows((prevRows: any) => - prevRows.map((row: any) => - row.id === updatedRow.id ? { ...updatedRow } : row + if (!configuration) { + console.error("Cannot update configuration. Configuration is null.") + return; + } + + const prevConfiguration = { ...configuration } + try { + const updatedConfiguration = getUpdatedConfiguration( + updatedRow, + rowIndex, + configuration ) - ); - }; + localStorage.setItem('configuration', JSON.stringify(updatedConfiguration)) + setConfiguration(updatedConfiguration) + setRows((prevRows: any) => + prevRows.map((row: any) => + row.id === updatedRow.id ? { ...updatedRow } : row + ) + ) + } catch (error) { + console.error("Error updating configuration:", error); + setConfiguration(prevConfiguration) + enqueueSnackbar("Failed to update configuration. Please try again.", { variant: 'error' }) + } + } const getUpdatedConfiguration = ( updatedRow: any,