Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cu 86bz9pz5f save common fields to local storage #263

7 changes: 3 additions & 4 deletions JeMPI_Apps/JeMPI_UI/src/pages/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ const Settings = () => {
return () => {
window.removeEventListener('storage', handleStorageChange);
};
}, [configurationData]);
}, []);

useEffect(() => {
const storedData = localStorage.getItem('configuration');
if (storedData) {
setConfigurationData(generateId(JSON.parse(storedData)));
}
}, [configurationData]);
}, []);

return (
<Grid container spacing={4}>
Expand Down Expand Up @@ -88,7 +88,7 @@ const Settings = () => {
<Typography variant="h5" sx={{ py: 3 }}>
Setup common properties
</Typography>
<CommonSettings demographicData={configurationData.demographicFields} />
<CommonSettings />
</CustomTabPanel>
<CustomTabPanel value={value} index={1}>
<Typography variant="h5" sx={{ py: 3 }}>
Expand All @@ -111,7 +111,6 @@ const Settings = () => {
Setup properties for Golden record lists
</Typography>
<GoldenRecordLists
goldenRecordList={configurationData?.additionalNodes || []}
/>
</CustomTabPanel>
<CustomTabPanel value={value} index={4}>
Expand Down
44 changes: 21 additions & 23 deletions JeMPI_Apps/JeMPI_UI/src/pages/settings/blocking/BlockingContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,30 @@ const BlockingContent = ({
transformRulesToRowData({ probabilistic: initialRules })
)
}
}, [configuration, linkingRules])
}, [configuration])

const handleUpdateConfiguration = useCallback(
(newRules: Rule[], ruleType: 'matchNotification' | 'link') => {
setConfiguration(prevConfig => {
if (!prevConfig) return prevConfig

const updatedConfig: Configuration = {
...prevConfig,
rules: {
...prevConfig.rules,
[ruleType]: {
...prevConfig.rules[ruleType],
probabilistic: newRules
}
const handleUpdateConfiguration = (newRules: Rule[], ruleType: 'matchNotification' | 'link') => {
setConfiguration(prevConfig => {
if (!prevConfig) return prevConfig;

const updatedConfig: Configuration = {
...prevConfig,
rules: {
...prevConfig.rules,
[ruleType]: {
...prevConfig.rules[ruleType],
probabilistic: newRules
}
}

localStorage.setItem('configuration', JSON.stringify(updatedConfig))
return updatedConfig
})

setProbabilisticRows(transformRulesToRowData({ probabilistic: newRules }))
},
[setConfiguration]
)
};

localStorage.setItem('configuration', JSON.stringify(updatedConfig));
return updatedConfig;
});

setProbabilisticRows(transformRulesToRowData({ probabilistic: newRules }));
};
MatthewErispe marked this conversation as resolved.
Show resolved Hide resolved


const handleAddRule = useCallback(
(ruleType: 'matchNotification' | 'link') => {
Expand Down
148 changes: 106 additions & 42 deletions JeMPI_Apps/JeMPI_UI/src/pages/settings/common/Common.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useCallback, useEffect, useState } from 'react'
import Box from '@mui/material/Box'
import {
DataGrid,
Expand All @@ -13,66 +14,130 @@ import {
import EditIcon from '@mui/icons-material/Edit'
import SaveIcon from '@mui/icons-material/Save'
import CancelIcon from '@mui/icons-material/Close'
import { useEffect, useState } from 'react'
import { EditToolbar } from 'components/shared/EditToolBar'
import { processIndex, transformFieldName } from 'utils/helpers'
import { useConfiguration } from 'hooks/useUIConfiguration'
import { Configuration, LinkMetaData } from 'types/Configuration'
import { RowData } from '../deterministic/SourceView'

const CommonSettings = ({ demographicData }: { demographicData: any }) => {
const [rows, setRows] = useState(demographicData)
const toSnakeCase = (str: string) => {
return str
.trim()
.replace(/\s+/g, '_')
.replace(/([a-z])([A-Z])/g, '$1_$2')
.toLowerCase()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor toSnakeCase function to handle additional cases.

The function currently handles spaces and camelCase to snake_case conversion. Consider adding support for other cases such as kebab-case and removing special characters that are not typically used in identifiers.

-  .replace(/\s+/g, '_')
-  .replace(/([a-z])([A-Z])/g, '$1_$2')
+  .replace(/[\s-]+/g, '_')
+  .replace(/([^\w]|_)+/g, '')
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const toSnakeCase = (str: string) => {
return str
.trim()
.replace(/\s+/g, '_')
.replace(/([a-z])([A-Z])/g, '$1_$2')
.toLowerCase()
}
const toSnakeCase = (str: string) => {
return str
.trim()
.replace(/[\s-]+/g, '_')
.replace(/([^\w]|_)+/g, '')
.toLowerCase()
}


const CommonSettings = () => {
const [rows, setRows] = useState<any>([])
const { configuration, setConfiguration } = useConfiguration()
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({})

useEffect(() => {
const rowsWithIds = demographicData.map((row: any, index: number) => ({
...row,
id: index.toString()
}))
setRows(rowsWithIds)
}, [demographicData])
if(configuration && configuration.demographicFields){
const rowData = configuration?.demographicFields.map((row: any, rowIndex: number) => ({
id: rowIndex + 1,
...row,
rowIndex
}))
setRows(rowData)
}

}, [configuration])

const handleEditClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } })
}

const handleSaveClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } })
const updatedRow = rows.find((row: { id: GridRowId }) => row.id === id)
if (updatedRow) {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }) }
}

const handleDeleteClick = (id: any) => () => {
setRows(rows?.filter((row: { id: any }) => row.id !== id))
}

const handleCancelClick = (id: GridRowId) => () => {
setRowModesModel({
...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true }
const handleUpdateConfiguration = (updatedRow: any, rowIndex: number) => {
setConfiguration(previousConfiguration => {
if (!previousConfiguration) return previousConfiguration
const updatedConfiguration = getUpdatedConfiguration(
updatedRow,
rowIndex,
previousConfiguration
)
localStorage.setItem(
'configuration',
JSON.stringify(updatedConfiguration)
)
setConfiguration(updatedConfiguration)
return updatedConfiguration
})
}

const editedRow = rows.find((row: { id: GridRowId }) => row.id === id)
if (editedRow!.isNew) {
setRows(rows.filter((row: { id: GridRowId }) => row.id !== id))
const getUpdatedConfiguration = (
updatedRow: any,
rowIndex: number,
currentConfiguration: Configuration
): Configuration => {
const fieldName = toSnakeCase(updatedRow.fieldName);
if (!currentConfiguration.demographicFields) {
console.error('demographicFields is undefined');
return currentConfiguration;
}

const fieldToUpdate = currentConfiguration.demographicFields[rowIndex];

if (!fieldToUpdate) {
console.error(`No field found at row index ${rowIndex}`);
return currentConfiguration;
}

fieldToUpdate.fieldName = fieldName;

if (updatedRow?.indexGoldenRecord) {
fieldToUpdate.indexGoldenRecord = `@index(${updatedRow.indexGoldenRecord})`;
}

if (updatedRow?.m) {
fieldToUpdate.linkMetaData = {
...fieldToUpdate.linkMetaData,
m: Number(updatedRow.m)
} as LinkMetaData;
}

if (updatedRow?.u) {
fieldToUpdate.linkMetaData = {
...fieldToUpdate.linkMetaData,
u: Number(updatedRow.u)
} as LinkMetaData;
}

currentConfiguration.demographicFields[rowIndex] = fieldToUpdate;

return currentConfiguration;
}


const processRowUpdate = (newRow: GridRowModel) => {
const { isNew, ...updatedRow } = newRow
setRows(
rows.map((row: { id: any }) => (row.id === newRow.id ? updatedRow : row))
)
return updatedRow
const handleCancelClick = (id: GridRowId) => () => {
setRowModesModel(prevRowModesModel => {
const newRowModesModel = { ...prevRowModesModel }
delete newRowModesModel[id]
return newRowModesModel
})
}

const handleRowEditStop: GridEventListener<'rowEditStop'> = ({ reason }) =>
reason === GridRowEditStopReasons.rowFocusOut

Comment on lines +109 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent handling of rowFocusOut reason.

The handleRowEditStop function checks if the reason is GridRowEditStopReasons.rowFocusOut but does not set event.defaultMuiPrevented = true. Ensure consistency across the codebase by updating the implementation.

-  const handleRowEditStop: GridEventListener<'rowEditStop'> = ({ reason }) =>
-    reason === GridRowEditStopReasons.rowFocusOut
+  const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
+    if (params.reason === GridRowEditStopReasons.rowFocusOut) {
+      event.defaultMuiPrevented = true;
+    }
+  }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleRowEditStop: GridEventListener<'rowEditStop'> = ({ reason }) =>
reason === GridRowEditStopReasons.rowFocusOut
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
event.defaultMuiPrevented = true;
}
}

const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => {
setRowModesModel(newRowModesModel)
}

const handleRowEditStop: GridEventListener<'rowEditStop'> = (
params,
event
) => {
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
event.defaultMuiPrevented = true
}
}
const processRowUpdate = (newRow: GridRowModel) => {
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;
};

const columns: GridColDef[] = [
{
Expand All @@ -93,7 +158,6 @@ const CommonSettings = ({ demographicData }: { demographicData: any }) => {
headerAlign: 'center',
editable: false
},

{
field: 'indexGoldenRecord',
headerName: 'Index',
Expand All @@ -117,10 +181,10 @@ const CommonSettings = ({ demographicData }: { demographicData: any }) => {
headerAlign: 'center',
valueGetter: params => {
const linkMetaData = params.row.linkMetaData
if (linkMetaData) {
if (linkMetaData && typeof linkMetaData.m === 'number') {
return linkMetaData.m.toFixed(1)
}
return ''
return
}
},
{
Expand All @@ -133,10 +197,9 @@ const CommonSettings = ({ demographicData }: { demographicData: any }) => {
headerAlign: 'center',
valueGetter: params => {
const linkMetaData = params.row.linkMetaData
if (linkMetaData) {
if (linkMetaData && typeof linkMetaData.u === 'number') {
return linkMetaData.u.toFixed(2)
}
return ''
}
},
{
Expand Down Expand Up @@ -192,15 +255,16 @@ const CommonSettings = ({ demographicData }: { demographicData: any }) => {
width: '100%'
}}
>
{demographicData && (
{configuration && (
<DataGrid
rows={rows}
columns={columns}
editMode="row"
rowModesModel={rowModesModel}
onRowModesModelChange={handleRowModesModelChange}
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
onRowEditStop={handleRowEditStop}
getRowId={row => row.id}
slots={{
toolbar: EditToolbar
}}
Expand Down
Loading