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

Custom and dynamic columns in spreadsheet #2272

Merged
merged 13 commits into from
Oct 2, 2024
84 changes: 79 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"eventemitter3": "^5.0.1",
"localized-countries": "^2.0.0",
"lucene-escape-query": "^1.0.1",
"mathjs": "^13.1.1",
"mjolnir.js": "^2.7.1",
"mui-nested-menu": "^3.3.0",
"notistack": "^3.0.1",
Expand Down
4 changes: 4 additions & 0 deletions src/components/app-wrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ import errors_locale_en from '../translations/dynamic/errors-locale-en';
import errors_locale_fr from '../translations/dynamic/errors-locale-fr';
import events_locale_fr from '../translations/dynamic/events-locale-fr';
import events_locale_en from '../translations/dynamic/events-locale-en';
import spreadsheet_locale_fr from '../translations/spreadsheet-fr';
import spreadsheet_locale_en from '../translations/spreadsheet-en';
import { store } from '../redux/store';
import CssBaseline from '@mui/material/CssBaseline';
import {
Expand Down Expand Up @@ -267,6 +269,7 @@ const messages = {
...table_locale_en,
...errors_locale_en,
...events_locale_en,
...spreadsheet_locale_en,
...messages_plugins.en, // keep it at the end to allow translation overwriting
},
fr: {
Expand Down Expand Up @@ -295,6 +298,7 @@ const messages = {
...table_locale_fr,
...errors_locale_fr,
...events_locale_fr,
...spreadsheet_locale_fr,
...messages_plugins.fr, // keep it at the end to allow translation overwriting
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/custom-aggrid/custom-aggrid-header.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export enum FILTER_NUMBER_COMPARATORS {
GREATER_THAN = 'greaterThan',
}

type FilterParams = {
export type FilterParams = {
filterDataType?: string;
isDuration?: boolean;
filterComparators?: string[];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright © 2024, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { Badge, Button } from '@mui/material';
import { Calculate as CalculateIcon } from '@mui/icons-material';
import { useSelector } from 'react-redux';
import { TABLES_NAMES } from '../utils/config-tables';
import { AppState } from '../../../redux/reducer';
import { useStateBoolean, useStateNumber } from '@gridsuite/commons-ui';
import CustomColumnDialog from './custom-columns-dialog';

export type CustomColumnsConfigProps = {
indexTab: number;
};

export default function CustomColumnsConfig({ indexTab }: Readonly<CustomColumnsConfigProps>) {
const numberColumns = useStateNumber(0);
const dialogOpen = useStateBoolean(false);
const customColumnsDefinitions = useSelector(
(state: AppState) => state.allCustomColumnsDefinitions[TABLES_NAMES[indexTab]]
);

useEffect(() => {
numberColumns.setValue(customColumnsDefinitions.columns.length);
}, [customColumnsDefinitions.columns.length, numberColumns]);

return (
<>
<Button color="inherit" onClick={dialogOpen.setTrue}>
<FormattedMessage id="spreadsheet/custom_column/main_button" />
<Badge
color="secondary"
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
badgeContent={numberColumns.value}
>
<CalculateIcon />
</Badge>
</Button>
<CustomColumnDialog
indexTab={indexTab}
open={dialogOpen}
customColumnsDefinitions={customColumnsDefinitions.columns}
/>
</>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const numberColumns = useStateNumber(0);
const dialogOpen = useStateBoolean(false);
const customColumnsDefinitions = useSelector(
(state: AppState) => state.allCustomColumnsDefinitions[TABLES_NAMES[indexTab]]
);
useEffect(() => {
numberColumns.setValue(customColumnsDefinitions.columns.length);
}, [customColumnsDefinitions.columns.length, numberColumns]);
return (
<>
<Button color="inherit" onClick={dialogOpen.setTrue}>
<FormattedMessage id="spreadsheet/custom_column/main_button" />
<Badge
color="secondary"
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
badgeContent={numberColumns.value}
>
<CalculateIcon />
</Badge>
</Button>
<CustomColumnDialog
indexTab={indexTab}
open={dialogOpen}
customColumnsDefinitions={customColumnsDefinitions.columns}
/>
</>
const dialogOpen = useStateBoolean(false);
const customColumnsDefinitions = useSelector(
(state: AppState) => state.allCustomColumnsDefinitions[TABLES_NAMES[indexTab]].columns
);
return (
<>
<Button color="inherit" onClick={dialogOpen.setTrue}>
<FormattedMessage id="spreadsheet/custom_column/main_button" />
<Badge
color="secondary"
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
badgeContent={customColumnsDefinitions.length}
>
<CalculateIcon />
</Badge>
</Button>
<CustomColumnDialog
indexTab={indexTab}
open={dialogOpen}
customColumnsDefinitions={customColumnsDefinitions}
/>
</>

This can still be simplified

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

);
}
107 changes: 107 additions & 0 deletions src/components/spreadsheet/custom-columns/custom-columns-dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright © 2024, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { useCallback, useEffect } from 'react';
import { useIntl } from 'react-intl';
import { Box, Dialog, DialogActions, DialogContent, DialogTitle, Grid, SxProps, Theme } from '@mui/material';
import { CancelButton, CustomFormProvider, SubmitButton, UseStateBooleanReturn } from '@gridsuite/commons-ui';
import { useForm } from 'react-hook-form';
import {
CustomColumnForm,
customColumnFormSchema,
initialCustomColumnForm,
TAB_CUSTOM_COLUMN,
} from './custom-columns-form';

import { yupResolver } from '@hookform/resolvers/yup';
import CustomColumnTable from './custom-columns-table';
import { setCustomColumDefinitions } from 'redux/actions';
import { TABLES_NAMES } from '../utils/config-tables';
import { useDispatch } from 'react-redux';
import { AppDispatch } from 'redux/store';
import { ColumnWithFormula } from 'types/custom-columns.types';

export type CustomColumnDialogProps = {
open: UseStateBooleanReturn;
indexTab: number;
customColumnsDefinitions: ColumnWithFormula[];
};

const styles = {
dialogContent: {
width: '50%',
height: '60%',
maxWidth: 'none',
margin: 'auto',
},
actionButtons: { display: 'flex', gap: 2, justifyContent: 'end' },
} as const satisfies Record<string, SxProps<Theme>>;

export default function CustomColumnDialog({
open,
indexTab,
customColumnsDefinitions,
}: Readonly<CustomColumnDialogProps>) {
const formMethods = useForm({
defaultValues: initialCustomColumnForm,
resolver: yupResolver(customColumnFormSchema),
});

const { handleSubmit, reset } = formMethods;
const dispatch = useDispatch<AppDispatch>();

const intl = useIntl();

const onSubmit = useCallback(
(newParams: CustomColumnForm) => {
dispatch(setCustomColumDefinitions(TABLES_NAMES[indexTab], newParams[TAB_CUSTOM_COLUMN]));
reset(initialCustomColumnForm);
open.setFalse();
},

[dispatch, indexTab, open, reset]
);

useEffect(() => {
if (open.value && customColumnsDefinitions.length !== 0) {
reset({
[TAB_CUSTOM_COLUMN]: customColumnsDefinitions,
});
} else {
reset(initialCustomColumnForm);
}
}, [customColumnsDefinitions, indexTab, open.value, reset]);

return (
<CustomFormProvider validationSchema={customColumnFormSchema} {...formMethods}>
<Dialog
id="custom-column-dialog-edit"
open={open.value}
onClose={open.setFalse}
aria-labelledby="custom-column-dialog-edit-title"
PaperProps={{ sx: styles.dialogContent }}
>
<DialogTitle id="custom-column-dialog-edit-title">
{intl.formatMessage({ id: 'spreadsheet/custom_column/main_button' })}
</DialogTitle>
<DialogContent dividers>
<CustomColumnTable />
</DialogContent>
<DialogActions>
<Grid container spacing={0.5}>
<Grid item xs>
<Box sx={styles.actionButtons}>
<CancelButton onClick={open.setFalse} />
<SubmitButton onClick={handleSubmit(onSubmit)} variant="outlined" />
</Box>
</Grid>
</Grid>
</DialogActions>
</Dialog>
</CustomFormProvider>
);
}
Loading
Loading