From d79eff07a23e2e950dbf33bd9bb151e8e629e730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9line=20S=C3=A8be?= <87119259+CelineSebe@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:14:58 +0100 Subject: [PATCH] [frontend] use context to prefill the dynamic entity mapping column (#7400) Co-authored-by: Landry Trebon --- .../data/csvMapper/CsvMapperContext.tsx | 27 ++++++++++ .../data/csvMapper/CsvMapperForm.tsx | 5 +- .../CsvMapperConditionalEntityMapping.tsx | 51 ++++++++++++------- 3 files changed, 63 insertions(+), 20 deletions(-) create mode 100644 opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperContext.tsx diff --git a/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperContext.tsx b/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperContext.tsx new file mode 100644 index 000000000000..e75923488248 --- /dev/null +++ b/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperContext.tsx @@ -0,0 +1,27 @@ +import React, { createContext, ReactNode, useContext, useState } from 'react'; + +interface CsvMapperContextProps { + dynamicMappingColumn: string | null; + setDynamicMappingColumn: (index: string) => void; +} + +interface CsvMapperProviderProps { + children: ReactNode; +} + +const CsvMapperContext = createContext(undefined); +export const CsvMapperProvider: React.FC = ({ children }) => { + const [dynamicMappingColumn, setDynamicMappingColumn] = useState(null); + return ( + + {children} + + ); +}; +export const useCsvMapperContext = () => { + const context = useContext(CsvMapperContext); + if (!context) { + throw new Error('useCsvMapperContext must be used within a CsvMapperProvider'); + } + return context; +}; diff --git a/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperForm.tsx b/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperForm.tsx index 0adb957ab35b..8aaeffe3329a 100644 --- a/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperForm.tsx +++ b/opencti-platform/opencti-front/src/private/components/data/csvMapper/CsvMapperForm.tsx @@ -14,6 +14,7 @@ import { CsvMapperFormData } from '@components/data/csvMapper/CsvMapper'; import classNames from 'classnames'; import FormControlLabel from '@mui/material/FormControlLabel'; import { formDataToCsvMapper } from '@components/data/csvMapper/CsvMapperUtils'; +import { CsvMapperProvider } from '@components/data/csvMapper/CsvMapperContext'; import type { Theme } from '../../../../components/Theme'; import { useFormatter } from '../../../../components/i18n'; import TextField from '../../../../components/TextField'; @@ -160,7 +161,7 @@ const CsvMapperForm: FunctionComponent = ({ csvMapper, onSub setHasError(Object.values(errors).filter((v) => v).length > 0); }; return ( - <> + enableReinitialize initialValues={csvMapper} @@ -351,7 +352,7 @@ const CsvMapperForm: FunctionComponent = ({ csvMapper, onSub ); }} - + ); }; diff --git a/opencti-platform/opencti-front/src/private/components/data/csvMapper/representations/CsvMapperConditionalEntityMapping.tsx b/opencti-platform/opencti-front/src/private/components/data/csvMapper/representations/CsvMapperConditionalEntityMapping.tsx index 4f14242fb2c3..279995737e1f 100644 --- a/opencti-platform/opencti-front/src/private/components/data/csvMapper/representations/CsvMapperConditionalEntityMapping.tsx +++ b/opencti-platform/opencti-front/src/private/components/data/csvMapper/representations/CsvMapperConditionalEntityMapping.tsx @@ -6,42 +6,64 @@ import { CsvMapperColumnBasedFormData, CsvMapperRepresentationFormData } from '@ import Tooltip from '@mui/material/Tooltip'; import { InformationOutline } from 'mdi-material-ui'; import { alphabet } from '@components/data/csvMapper/representations/attributes/AttributeUtils'; +import { useCsvMapperContext } from '@components/data/csvMapper/CsvMapperContext'; +import { useTheme } from '@mui/styles'; +import { Option } from '@components/common/form/ReferenceField'; import { useFormatter } from '../../../../../components/i18n'; import TextField from '../../../../../components/TextField'; import SwitchField from '../../../../../components/fields/SwitchField'; +import type { Theme } from '../../../../../components/Theme'; interface CsvMapperConditionalEntityMappingProps extends FieldProps { representation: CsvMapperRepresentationFormData; representationName: string; } + const CsvMapperConditionalEntityMapping: FunctionComponent< CsvMapperConditionalEntityMappingProps > = ({ form, representationName, representation }) => { + const theme = useTheme(); const { t_i18n } = useFormatter(); + const { dynamicMappingColumn, setDynamicMappingColumn } = useCsvMapperContext(); + const columnOptions = alphabet(26); - const operatorOptions = [ - { label: t_i18n('Equal'), value: ('eq') }, + const operatorOptions: Option[] = [ + { label: t_i18n('Equal'), value: 'eq' }, { label: t_i18n('Not equal'), value: 'not_eq' }]; const { setFieldValue } = form; + const columnBased = representation.column_based; const handleColumnSelect = async (column: string | null) => { await setFieldValue(`${representationName}.column_based.column_reference`, column); + if (column) { + setDynamicMappingColumn(column); + } }; - const handleOperatorSelect = async (operator: { label: string, value: string } | null) => { + const handleOperatorSelect = async (operator: Option | null) => { await setFieldValue(`${representationName}.column_based.operator`, operator?.value); }; + const onToggleDynamicMapping = async (val: string) => { + if (val === 'false') { + await setFieldValue(`${representationName}.column_based.column_reference`, null); + await setFieldValue(`${representationName}.column_based.operator`, null); + } else { + await setFieldValue(`${representationName}.column_based.column_reference`, dynamicMappingColumn ?? null); + await setFieldValue(`${representationName}.column_based.operator`, 'eq'); + } + }; + return (
onToggleDynamicMapping(val)} label={t_i18n('Entity dynamic mapping')} /> handleColumnSelect(val)} sx={{ width: '100%' }} renderInput={(params) => ( @@ -100,20 +119,16 @@ CsvMapperConditionalEntityMappingProps /> )} /> - + selectOnFocus openOnFocus + autoComplete autoSelect={false} autoHighlight options={operatorOptions} disabled={!columnBased?.enabled} - value={ - columnBased?.enabled - ? (operatorOptions.find((opt) => (opt.value === columnBased?.operator)) ?? undefined) - : null - } + value={operatorOptions.find((opt) => opt.value === columnBased?.operator) ?? null} onChange={(_, val) => handleOperatorSelect(val)} - defaultValue={operatorOptions.find((opt) => opt.value === 'eq')} sx={{ width: '100%' }} renderInput={(params) => (