Skip to content

Commit e01bf1c

Browse files
committed
feat: [PROD-14182] add dialog to update ETL parameters
1 parent 96a9c2f commit e01bf1c

File tree

10 files changed

+306
-42
lines changed

10 files changed

+306
-42
lines changed

public/locales/en/translation.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,21 @@
170170
"confirmButton": "Delete",
171171
"impactedScenariosWarning": "Users won’t be able to launch scenarios using this dataset, but previously existing results will still be available."
172172
},
173+
"update": {
174+
"title": "Update dataset",
175+
"subTitle": "Update your data source's information",
176+
"source": "Source:",
177+
"button": "Update"
178+
},
173179
"cancel": "Cancel"
174180
},
175181
"overview": {
176182
"actions": {
177183
"deleteButtonTooltip": "Delete",
178184
"shareButtonTooltip": "Share",
179185
"refreshButtonTooltip": "Refresh",
180-
"createSubdatasetButtonTooltip": "Create sub-dataset"
186+
"createSubdatasetButtonTooltip": "Create sub-dataset",
187+
"editParametersButtonTooltip": "Edit parameters of the dataset"
181188
},
182189
"attributesLabel": "Attributes:",
183190
"categoryTypes": {

public/locales/fr/translation.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,21 @@
170170
"confirmButton": "Supprimer",
171171
"impactedScenariosWarning": "Les scénarios utilisant ce dataset ne pourront pas être relancés, mais les résultats déjà disponibles resteront visibles."
172172
},
173+
"update": {
174+
"title": "Mettre à jour les paramètres du dataset",
175+
"subTitle": "Mettre à jour la source du dataset",
176+
"source": "Source : ",
177+
"button": "Sauvegarder"
178+
},
173179
"cancel": "Annuler"
174180
},
175181
"overview": {
176182
"actions": {
177183
"deleteButtonTooltip": "Supprimer",
178184
"shareButtonTooltip": "Partager",
179185
"refreshButtonTooltip": "Mettre à jour",
180-
"createSubdatasetButtonTooltip": "Créer un sous-dataset"
186+
"createSubdatasetButtonTooltip": "Créer un sous-dataset",
187+
"editParametersButtonTooltip": "Modifier les paramètres du dataset"
181188
},
182189
"attributesLabel": "Attributs:",
183190
"categoryTypes": {

src/views/DatasetManager/components/CreateDatasetButton/components/DatasetCreationParameters/DatasetCreationParameters.js

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,30 @@ import PropTypes from 'prop-types';
77
import { Grid, Typography } from '@mui/material';
88
import rfdc from 'rfdc';
99
import { UploadFile, BasicEnumInput } from '@cosmotech/ui';
10-
import {
11-
GenericEnumInput,
12-
GenericMultiSelect,
13-
GenericTextInput,
14-
GenericDateInput,
15-
} from '../../../../../../components/ScenarioParameters/components/ScenarioParametersInputs';
10+
import { GenericEnumInput, GenericMultiSelect, GenericTextInput, GenericDateInput } from '../../../../../../components';
1611
import { ConfigUtils, SolutionsUtils, TranslationUtils } from '../../../../../../utils';
1712
import { FileManagementUtils } from '../../../../../../utils/FileManagementUtils';
1813
import { useDatasetCreationParameters } from './DatasetCreationParametersHook';
1914

2015
const clone = rfdc();
2116

22-
export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDataset }) => {
17+
export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDataset, selectedRunner }) => {
2318
const { t } = useTranslation();
2419
const { resetField } = useFormContext();
2520
const { datasourceParameterHelpers, getDataSourceTypeEnumValues, getUploadFileLabels, getDefaultFileTypeFilter } =
2621
useDatasetCreationParameters();
2722

2823
const isSubDatasetCreationWizard = useMemo(() => parentDataset != null, [parentDataset]);
29-
const [dataSourceType, setDataSourceType] = useState(null);
24+
const isDatasetParametersEditionDialog = selectedRunner && Object.keys(selectedRunner).length > 0;
25+
const [dataSourceType, setDataSourceType] = useState(selectedRunner?.runTemplateId ?? null);
3026
const dataSourceTypeEnumValues = useMemo(
3127
() => getDataSourceTypeEnumValues(dataSourceRunTemplates),
3228
[getDataSourceTypeEnumValues, dataSourceRunTemplates]
3329
);
3430
const defaultDataSourceTypeKey = useMemo(() => dataSourceTypeEnumValues?.[0]?.key ?? '', [dataSourceTypeEnumValues]);
31+
const selectedRunnerDataSourceLabel = useMemo(() => {
32+
return dataSourceTypeEnumValues?.find((rt) => rt.key === dataSourceType)?.value || dataSourceType;
33+
}, [dataSourceTypeEnumValues, dataSourceType]);
3534

3635
useEffect(() => {
3736
if (dataSourceType == null) setDataSourceType(defaultDataSourceTypeKey);
@@ -52,7 +51,6 @@ export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDatase
5251
const escapedSourceType = SolutionsUtils.escapeRunTemplateId(dataSourceType);
5352
const fieldPath = `${escapedSourceType}.${parameterId}`;
5453
const inputType = parameter.varType;
55-
5654
let defaultValue;
5755
if (inputType === 'string') defaultValue = parameter?.defaultValue ?? '';
5856
else if (inputType === 'enum') {
@@ -152,14 +150,14 @@ export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDatase
152150
const runTemplate = dataSourceRunTemplates[dataSourceType];
153151
return runTemplate?.parameters?.map((parameter) => forgeParameterInput(parameter));
154152
}, [
155-
t,
156-
getUploadFileLabels,
157-
getDefaultFileTypeFilter,
158153
dataSourceRunTemplates,
159154
dataSourceType,
160-
parentDataset?.id,
161155
datasourceParameterHelpers,
156+
parentDataset?.id,
162157
resetField,
158+
getUploadFileLabels,
159+
t,
160+
getDefaultFileTypeFilter,
163161
]);
164162

165163
const labels = useMemo(() => {
@@ -183,36 +181,46 @@ export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDatase
183181
};
184182
}, [t, isSubDatasetCreationWizard]);
185183

184+
const sourceTypeComponent = isDatasetParametersEditionDialog ? (
185+
<Typography data-cy="selected-runner-source-type">
186+
{labels.sourceSelectLabel + ': ' + selectedRunnerDataSourceLabel}
187+
</Typography>
188+
) : (
189+
<Controller
190+
name="sourceType"
191+
key="sourceType"
192+
defaultValue={dataSourceType ?? defaultDataSourceTypeKey}
193+
shouldUnregister={true}
194+
render={({ field }) => {
195+
const { value, onChange } = field;
196+
const setDatasetSource = (newValue) => {
197+
onChange(newValue);
198+
setDataSourceType(newValue);
199+
};
200+
201+
return (
202+
<BasicEnumInput
203+
id="new-dataset-sourceType"
204+
label={labels.sourceSelectLabel}
205+
size="medium"
206+
value={value ?? defaultDataSourceTypeKey}
207+
changeEnumField={setDatasetSource}
208+
enumValues={dataSourceTypeEnumValues}
209+
/>
210+
);
211+
}}
212+
/>
213+
);
214+
186215
return (
187216
<>
188-
<Grid item xs={12}>
189-
{<Typography sx={{ py: 2 }}>{labels.subtitle}</Typography>}
190-
</Grid>
217+
{!isDatasetParametersEditionDialog && (
218+
<Grid item xs={12}>
219+
{<Typography sx={{ py: 2 }}>{labels.subtitle}</Typography>}
220+
</Grid>
221+
)}
191222
<Grid item xs={7}>
192-
<Controller
193-
name="sourceType"
194-
key="sourceType"
195-
defaultValue={dataSourceType ?? defaultDataSourceTypeKey}
196-
shouldUnregister={true}
197-
render={({ field }) => {
198-
const { value, onChange } = field;
199-
const setDatasetSource = (newValue) => {
200-
onChange(newValue);
201-
setDataSourceType(newValue);
202-
};
203-
204-
return (
205-
<BasicEnumInput
206-
id="new-dataset-sourceType"
207-
label={labels.sourceSelectLabel}
208-
size="medium"
209-
value={value ?? defaultDataSourceTypeKey}
210-
changeEnumField={setDatasetSource}
211-
enumValues={dataSourceTypeEnumValues}
212-
/>
213-
);
214-
}}
215-
/>
223+
{sourceTypeComponent}
216224
</Grid>
217225
<Grid item container xs={12} sx={{ px: 2, pt: 3 }}>
218226
{sourceParameters}
@@ -224,4 +232,8 @@ export const DatasetCreationParameters = ({ dataSourceRunTemplates, parentDatase
224232
DatasetCreationParameters.propTypes = {
225233
dataSourceRunTemplates: PropTypes.object.isRequired,
226234
parentDataset: PropTypes.object,
235+
selectedRunner: PropTypes.object,
236+
};
237+
DatasetCreationParameters.defaultProps = {
238+
selectedRunner: {},
227239
};

src/views/DatasetManager/components/DatasetOverview/components/DatasetActions/DatasetActions.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import ButtonGroup from '@mui/material/ButtonGroup';
44
import ShareDatasetButton from '../../../../../../components/ShareDatasetButton/ShareDatasetButton';
55
import { CreateSubDatasetButton } from '../../../CreateDatasetButton';
66
import { DeleteDatasetButton } from '../../../DeleteDatasetButton';
7+
import { UpdateDatasetButton } from '../../../UpdateDatasetButton';
78
import { RefreshDatasetButton } from '../RefreshDatasetButton';
89

910
export default function DatasetActions({ dataset }) {
1011
if (dataset == null) return null;
1112
return (
1213
<ButtonGroup>
1314
<RefreshDatasetButton dataset={dataset} />
15+
{dataset?.sourceType === 'ETL' && <UpdateDatasetButton dataset={dataset} />}
1416
<CreateSubDatasetButton parentDataset={dataset} />
1517
<ShareDatasetButton dataset={dataset} />
1618
<DeleteDatasetButton dataset={dataset} location="dataset-actions-" />
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Cosmo Tech.
2+
// Licensed under the MIT license.
3+
import { React, useCallback, useState } from 'react';
4+
import { useTranslation } from 'react-i18next';
5+
import PropTypes from 'prop-types';
6+
import EditIcon from '@mui/icons-material/Edit';
7+
import { IconButton } from '@mui/material';
8+
import { FadingTooltip, PermissionsGate } from '@cosmotech/ui';
9+
import { INGESTION_STATUS } from '../../../../services/config/ApiConstants';
10+
import { ACL_PERMISSIONS } from '../../../../services/config/accessControl';
11+
import { useGetETLRunners } from '../../../../state/hooks/RunnerHooks';
12+
import { UpdateDatasetDialog } from './components';
13+
14+
export const UpdateDatasetButton = ({ dataset }) => {
15+
const { t } = useTranslation();
16+
const runners = useGetETLRunners();
17+
const selectedRunner = runners.find((runner) => runner.id === dataset.source.name);
18+
19+
const isDisabled =
20+
dataset?.ingestionStatus === INGESTION_STATUS.PENDING || Object.keys(selectedRunner ?? {})?.length === 0;
21+
const [isUpdateDatasetDialogOpen, setIsUpdateDatasetDialogOpen] = useState(false);
22+
const closeDialog = useCallback(() => setIsUpdateDatasetDialogOpen(false), []);
23+
const userPermissionsOnDataset = dataset?.security?.currentUserPermissions ?? [];
24+
25+
return (
26+
<>
27+
<PermissionsGate
28+
userPermissions={userPermissionsOnDataset}
29+
necessaryPermissions={[ACL_PERMISSIONS.DATASET.WRITE]}
30+
>
31+
<FadingTooltip
32+
title={t(
33+
'commoncomponents.datasetmanager.overview.actions.editParametersButtonTooltip',
34+
'Edit parameters of the dataset'
35+
)}
36+
disableInteractive={true}
37+
>
38+
<IconButton
39+
data-cy="edit-dataset-parameters-button"
40+
onClick={() => setIsUpdateDatasetDialogOpen(true)}
41+
disabled={isDisabled}
42+
>
43+
<EditIcon color={isDisabled ? 'disabled' : 'primary'} />
44+
</IconButton>
45+
</FadingTooltip>
46+
</PermissionsGate>
47+
<UpdateDatasetDialog
48+
open={isUpdateDatasetDialogOpen}
49+
dataset={dataset}
50+
selectedRunner={selectedRunner}
51+
closeDialog={closeDialog}
52+
/>
53+
</>
54+
);
55+
};
56+
UpdateDatasetButton.propTypes = {
57+
dataset: PropTypes.object.isRequired,
58+
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Cosmo Tech.
2+
// Licensed under the MIT license.
3+
import { React, useCallback, useEffect } from 'react';
4+
import { FormProvider, useForm } from 'react-hook-form';
5+
import { useTranslation } from 'react-i18next';
6+
import PropTypes from 'prop-types';
7+
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from '@mui/material';
8+
import { SolutionsUtils } from '../../../../../utils';
9+
import { DatasetCreationParameters } from '../../CreateDatasetButton/components/DatasetCreationParameters';
10+
import { useUpdateDatasetDialog } from './UpdateDatasetDialogHook';
11+
12+
export const UpdateDatasetDialog = ({ open, dataset, closeDialog, selectedRunner }) => {
13+
const { t } = useTranslation();
14+
const { dataSourceRunTemplates, updateRunner, solutionData, parentDataset, formattedParametersValues } =
15+
useUpdateDatasetDialog(dataset, selectedRunner);
16+
17+
const methods = useForm({
18+
mode: 'onChange',
19+
});
20+
const { isDirty, errors } = methods.formState;
21+
const isValid = Object.keys(errors ?? {}).length === 0;
22+
useEffect(() => {
23+
if (open) {
24+
const escapedSourceType = SolutionsUtils.escapeRunTemplateId(selectedRunner?.runTemplateId);
25+
methods.reset({ [escapedSourceType]: formattedParametersValues });
26+
}
27+
}, [open, methods, selectedRunner?.runTemplateId, formattedParametersValues]);
28+
29+
const updateRunnerAndCloseDialog = useCallback(() => {
30+
const values = methods.getValues();
31+
const escapedSourceType = SolutionsUtils.escapeRunTemplateId(selectedRunner?.runTemplateId);
32+
const parametersValues = SolutionsUtils.forgeRunnerParameters(solutionData, values[escapedSourceType]);
33+
const runnerPatch = { runTemplateId: selectedRunner?.runTemplateId, parametersValues };
34+
updateRunner(selectedRunner.id, dataset.id, runnerPatch);
35+
closeDialog();
36+
}, [closeDialog, dataset.id, methods, selectedRunner?.id, selectedRunner?.runTemplateId, solutionData, updateRunner]);
37+
38+
return (
39+
<FormProvider {...methods} key={`form-update-dataset-${dataset.id}`}>
40+
<Dialog data-cy="update-dataset-parameters-dialog" open={open} fullWidth>
41+
<DialogTitle>{t('commoncomponents.datasetmanager.dialogs.update.title', 'Update dataset')}</DialogTitle>
42+
<DialogContent>
43+
<Typography sx={{ pb: 1 }}>
44+
{t('commoncomponents.datasetmanager.dialogs.update.subTitle', "Update your data source's information")}
45+
</Typography>
46+
<DatasetCreationParameters
47+
dataSourceRunTemplates={dataSourceRunTemplates}
48+
parentDataset={parentDataset}
49+
selectedRunner={selectedRunner}
50+
/>
51+
</DialogContent>
52+
<DialogActions>
53+
<Button data-cy="close-update-dataset-parameters-dialog-button" onClick={closeDialog}>
54+
{t('commoncomponents.datasetmanager.dialogs.cancel', 'Cancel')}
55+
</Button>
56+
<Button
57+
data-cy="update-dataset-parameters-button"
58+
variant="contained"
59+
disabled={!isDirty || !isValid}
60+
onClick={updateRunnerAndCloseDialog}
61+
>
62+
{t('commoncomponents.datasetmanager.dialogs.update.button', 'Update')}
63+
</Button>
64+
</DialogActions>
65+
</Dialog>
66+
</FormProvider>
67+
);
68+
};
69+
UpdateDatasetDialog.propTypes = {
70+
open: PropTypes.bool.isRequired,
71+
closeDialog: PropTypes.func.isRequired,
72+
dataset: PropTypes.object.isRequired,
73+
selectedRunner: PropTypes.object.isRequired,
74+
};

0 commit comments

Comments
 (0)