From 75b2228bf9b1c3af5ccc95f1ef8fa4f8461d3533 Mon Sep 17 00:00:00 2001 From: Matthias GOUPIL Date: Tue, 10 Dec 2024 14:37:32 +0100 Subject: [PATCH 1/2] feat(1314737): [Boost] Add Proportional Attribute Component to the FieldGuesser --- .../components/public/locales/en/boost.json | 6 +- .../components/public/locales/fr/boost.json | 6 +- .../src/components/atoms/form/RadioGroup.tsx | 4 +- .../atoms/form/RadioGroupWithoutError.tsx | 22 ++++- .../__snapshots__/RadioGroup.test.tsx.snap | 4 +- .../RadioGroupWithoutError.test.tsx.snap | 16 +++- .../ProportionalToAttributes.stories.tsx | 52 ++++++++++++ .../ProportionalToAttributes.tsx | 85 +++++++++++++++++++ .../ProportionalToAttributesManager.tsx | 65 ++++++++++++++ .../FieldGuesser/EditableFieldGuesser.tsx | 16 +++- .../stateful/FieldGuesser/MultipleInput.tsx | 4 +- packages/shared/src/services/hydra.ts | 7 ++ packages/shared/src/types/customTables.ts | 1 + 13 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.stories.tsx create mode 100644 packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.tsx create mode 100644 packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributesManager.tsx diff --git a/packages/components/public/locales/en/boost.json b/packages/components/public/locales/en/boost.json index e326489c..120ee128 100644 --- a/packages/components/public/locales/en/boost.json +++ b/packages/components/public/locales/en/boost.json @@ -22,5 +22,9 @@ "boost_zero": "boost", "boost_one": "boost", "boost_other": "boosts", - "preview": "Preview" + "preview": "Preview", + "boostConfig.sourceField": "Source field", + "boostConfig.sourceField.placeholder": "Select a source field", + "boostConfig.boostImpact": "Boost impact", + "boostConfig.scaleFactor": "Scale factor" } diff --git a/packages/components/public/locales/fr/boost.json b/packages/components/public/locales/fr/boost.json index 7f97c01c..ab4f8210 100644 --- a/packages/components/public/locales/fr/boost.json +++ b/packages/components/public/locales/fr/boost.json @@ -22,5 +22,9 @@ "boost_zero": "boost", "boost_one": "boost", "boost_other": "boosts", - "preview": "Prévisualiser" + "preview": "Prévisualiser", + "boostConfig.sourceField": "Source field", + "boostConfig.sourceField.placeholder": "Sélectionnez un source field", + "boostConfig.boostImpact": "Impacte du Boost", + "boostConfig.scaleFactor": "Facteur d'échelle" } diff --git a/packages/components/src/components/atoms/form/RadioGroup.tsx b/packages/components/src/components/atoms/form/RadioGroup.tsx index d7c511e5..59ad9807 100644 --- a/packages/components/src/components/atoms/form/RadioGroup.tsx +++ b/packages/components/src/components/atoms/form/RadioGroup.tsx @@ -12,9 +12,7 @@ import RadioGroupWithoutError, { } from './RadioGroupWithoutError' import InputTextWithoutError from './InputTextWithoutError' -interface IRadioGroupErrorProps extends IFieldErrorProps, IRadioGroupProps { - required?: boolean -} +interface IRadioGroupErrorProps extends IFieldErrorProps, IRadioGroupProps {} function RadioGroup(props: IRadioGroupErrorProps): JSX.Element { const { diff --git a/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx b/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx index 77c7343b..b3143e94 100644 --- a/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx +++ b/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx @@ -1,13 +1,16 @@ import React, { ReactNode, SyntheticEvent } from 'react' import { + FormControl, FormControlLabel, FormHelperText, + InputLabel, Radio, RadioGroupProps, RadioGroup as RadioGrp, } from '@mui/material' import { IOption, IOptions } from '@elastic-suite/gally-admin-shared' import IonIcon from '../IonIcon/IonIcon' +import InfoTooltip from '../../atoms/form/InfoTooltip' export interface IRadioGroupProps extends Omit { options: IOptions @@ -15,6 +18,9 @@ export interface IRadioGroupProps extends Omit { error?: boolean helperText?: ReactNode helperIcon?: string + label?: string + infoTooltip?: string + required?: boolean } function RadioGroupWithoutError(props: IRadioGroupProps): JSX.Element { @@ -24,12 +30,24 @@ function RadioGroupWithoutError(props: IRadioGroupProps): JSX.Element { helperIcon, options, onChange, + infoTooltip, + label, ...radioGroupProps } = props const foundNameDefaultValue = options.find((element) => element.default) return ( -
+ + {Boolean(label || infoTooltip) && ( + + {label} + {infoTooltip ? : null} + + )} { @@ -62,7 +80,7 @@ function RadioGroupWithoutError(props: IRadioGroupProps): JSX.Element { {helperText} )} -
+ ) } diff --git a/packages/components/src/components/atoms/form/__snapshots__/RadioGroup.test.tsx.snap b/packages/components/src/components/atoms/form/__snapshots__/RadioGroup.test.tsx.snap index 0b20fa5f..2bf3b00a 100644 --- a/packages/components/src/components/atoms/form/__snapshots__/RadioGroup.test.tsx.snap +++ b/packages/components/src/components/atoms/form/__snapshots__/RadioGroup.test.tsx.snap @@ -2,7 +2,9 @@ exports[`RadioGroup sould match snapshot 1`] = `
-
+
-
+
-
+
-
+
-
+
+ +const Template: ComponentStory = ( + args +) => { + const [value, setValue] = useState({ + sourceField: undefined, + boostImpact: undefined, + scaleFactor: 0, + }) + return ( + setValue(value)} + /> + ) +} + +export const ProportionalToAttributes = Template.bind({}) + +ProportionalToAttributes.args = { + boostImpactOptions: [ + { + label: 'Low', + value: 'Low', + }, + { + label: 'Medium', + value: 'Medium', + }, + { + label: 'High', + value: 'High', + }, + ], + sourceFields: [ + { + label: 'test', + value: 'test', + }, + ], +} diff --git a/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.tsx b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.tsx new file mode 100644 index 00000000..7912d32e --- /dev/null +++ b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.tsx @@ -0,0 +1,85 @@ +import React from 'react' +import RadioGroup from '../../atoms/form/RadioGroup' +import InputText from '../../atoms/form/InputText' +import DropDown from '../../atoms/form/DropDown' +import { styled } from '@mui/material' +import { IOptions } from '@elastic-suite/gally-admin-shared' +import { useTranslation } from 'next-i18next' + +const Container = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(1), +})) + +export interface IProportionalToAttributesValue { + sourceField?: string + boostImpact?: string + scaleFactor: number +} +export interface IProportionalToAttributesProps { + sourceFields: IOptions + boostImpactOptions: IOptions + value: IProportionalToAttributesValue + showError?: boolean + onChange: (value: IProportionalToAttributesValue) => void +} + +function ProportionalToAttributes({ + value, + sourceFields, + boostImpactOptions, + showError, + onChange, +}: IProportionalToAttributesProps): JSX.Element { + const { sourceField, boostImpact, scaleFactor } = value + const { t } = useTranslation('boost') + + function handleChange( + name: keyof IProportionalToAttributesProps['value'], + newValue: string | number + ): void { + onChange({ + ...value, + [name]: newValue, + }) + } + + return ( + + handleChange('sourceField', value)} + required + showError={showError} + sx={{ minWidth: '230px' }} + placeholder={t('boostConfig.sourceField.placeholder')} + /> + + handleChange('boostImpact', value)} + label={t('boostConfig.boostImpact')} + required + showError={showError} + /> + + handleChange('scaleFactor', value)} + showError={showError} + /> + + ) +} + +export default ProportionalToAttributes diff --git a/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributesManager.tsx b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributesManager.tsx new file mode 100644 index 00000000..67b065b2 --- /dev/null +++ b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributesManager.tsx @@ -0,0 +1,65 @@ +import React, { useMemo } from 'react' +import { useApiList, useResource } from '../../../hooks' +import ProportionalToAttributes, { + IProportionalToAttributesProps, +} from './ProportionalToAttributes' +import { IOption } from '@elastic-suite/gally-admin-shared' + +function ProportionalToAttributesManager( + props: Omit< + IProportionalToAttributesProps, + 'sourceFields' | 'boostImpactOptions' + > +): JSX.Element { + const rowsPerPage = 200 + const sourceFieldFixedFilters = useMemo( + () => ({ + 'metadata.entity': 'product', + }), + [] + ) + + const boostImpactOptionResource = useResource('BoostImpactOption') + const boostAttributeValueFieldOptionsResource = useResource( + 'BoostAttributeValueFieldOption' + ) + + const [boostImpactOptionsResponse] = useApiList>( + boostImpactOptionResource, + false, + rowsPerPage, + undefined, + undefined, + false, + true + ) + + const [boostAttributeValueFieldOptionsResponse] = useApiList>( + boostAttributeValueFieldOptionsResource, + false, + rowsPerPage, + sourceFieldFixedFilters, + undefined, + false, + true + ) + + if ( + !boostImpactOptionsResponse?.data || + !boostAttributeValueFieldOptionsResponse?.data + ) { + return null + } + + return ( + + ) +} + +export default ProportionalToAttributesManager diff --git a/packages/components/src/components/stateful/FieldGuesser/EditableFieldGuesser.tsx b/packages/components/src/components/stateful/FieldGuesser/EditableFieldGuesser.tsx index 6d964b5c..2047ee8f 100644 --- a/packages/components/src/components/stateful/FieldGuesser/EditableFieldGuesser.tsx +++ b/packages/components/src/components/stateful/FieldGuesser/EditableFieldGuesser.tsx @@ -28,7 +28,8 @@ import RulesManager from '../RulesManager/RulesManager' import Slider from '../../atoms/form/Slider' import Synonym from '../../atoms/form/Synonym' import Expansion from '../../atoms/form/Expansion' - +import { IProportionalToAttributesValue } from '../../molecules/ProportionalToAttributes/ProportionalToAttributes' +import ProportionalToAttributesManager from '../../molecules/ProportionalToAttributes/ProportionalToAttributesManager' function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element { const { diffValue, @@ -74,7 +75,8 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element { | IRequestType | IRuleCombination | ISynonyms - | IExpansions, + | IExpansions + | IProportionalToAttributesValue, event?: SyntheticEvent ): void { if (onChange) { @@ -337,6 +339,16 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element { ) } + case DataContentType.PROPARTIONALTOATTRIBUTE: { + return ( + + ) + } + default: { return } diff --git a/packages/components/src/components/stateful/FieldGuesser/MultipleInput.tsx b/packages/components/src/components/stateful/FieldGuesser/MultipleInput.tsx index 87703f30..ad1defd9 100644 --- a/packages/components/src/components/stateful/FieldGuesser/MultipleInput.tsx +++ b/packages/components/src/components/stateful/FieldGuesser/MultipleInput.tsx @@ -33,8 +33,8 @@ function MultipleInput(props: IProps): JSX.Element { {fields.map((field) => { const value = otherProps.value ? JSON.parse(otherProps.value as string)?.[field.jsonKeyValue] ?? - valueInitializer(field.input) - : valueInitializer(field.input) + valueInitializer(field.input, field.input) + : valueInitializer(field.input, field.input) function handleChange( _name: string, diff --git a/packages/shared/src/services/hydra.ts b/packages/shared/src/services/hydra.ts index b4f0b92f..38ba3d10 100644 --- a/packages/shared/src/services/hydra.ts +++ b/packages/shared/src/services/hydra.ts @@ -239,6 +239,13 @@ export function inputInitializer(input: string): unknown { toDate: null, } + case 'proportionalToAttribute': + return { + sourceField: undefined, + boostImpact: undefined, + scaleFactor: 0, + } + default: return '' } diff --git a/packages/shared/src/types/customTables.ts b/packages/shared/src/types/customTables.ts index 2de310fe..a0137238 100644 --- a/packages/shared/src/types/customTables.ts +++ b/packages/shared/src/types/customTables.ts @@ -31,6 +31,7 @@ export enum DataContentType { PRODUCTINFO = 'productInfo', BOOSTPREVIEW = 'boostPreview', POSITIONEFFECT = 'positionEffect', + PROPARTIONALTOATTRIBUTE = 'proportionalToAttribute', } export interface ITableHeader extends IFieldConfig { From 58c07711c3889fe121aa45f822bc13694399b3be Mon Sep 17 00:00:00 2001 From: Botis Date: Fri, 24 Jan 2025 14:34:18 +0100 Subject: [PATCH 2/2] fix(#1314737): draft --- .../atoms/form/RadioGroupWithoutError.tsx | 1 + .../ProportionalToAttributes.stories.tsx | 6 ++-- .../ProportionalToAttributes.tsx | 29 ++++++++++++------- packages/shared/src/services/hydra.ts | 6 ++-- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx b/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx index b3143e94..bad525a0 100644 --- a/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx +++ b/packages/components/src/components/atoms/form/RadioGroupWithoutError.tsx @@ -53,6 +53,7 @@ function RadioGroupWithoutError(props: IRadioGroupProps): JSX.Element { onChange={(event, value): void => { onChange(value, event) }} + //todo : la default value ne fonctionne pas et lors de la dernière demo on avait note des contraintes + un label pour le scale factor defaultValue={ radioGroupProps.defaultChecked ? foundNameDefaultValue?.value : null } diff --git a/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.stories.tsx b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.stories.tsx index 6517306c..18a41baa 100644 --- a/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.stories.tsx +++ b/packages/components/src/components/molecules/ProportionalToAttributes/ProportionalToAttributes.stories.tsx @@ -13,9 +13,9 @@ const Template: ComponentStory = ( args ) => { const [value, setValue] = useState({ - sourceField: undefined, - boostImpact: undefined, - scaleFactor: 0, + source_field_code: undefined, + boost_impact: undefined, + scale_factor: 1, }) return ( ({ })) export interface IProportionalToAttributesValue { - sourceField?: string - boostImpact?: string - scaleFactor: number + source_field_code?: string + boost_impact?: string + scale_factor: number } + export interface IProportionalToAttributesProps { sourceFields: IOptions boostImpactOptions: IOptions @@ -32,11 +33,15 @@ function ProportionalToAttributes({ showError, onChange, }: IProportionalToAttributesProps): JSX.Element { - const { sourceField, boostImpact, scaleFactor } = value + const { + source_field_code: sourceFieldCode, + boost_impact: boostImpact, + scale_factor: scaleFactor, + } = value const { t } = useTranslation('boost') function handleChange( - name: keyof IProportionalToAttributesProps['value'], + name: keyof IProportionalToAttributesValue, newValue: string | number ): void { onChange({ @@ -50,8 +55,10 @@ function ProportionalToAttributes({ handleChange('sourceField', value)} + value={sourceFieldCode} + onChange={(value: string): void => + handleChange('source_field_code', value) + } required showError={showError} sx={{ minWidth: '230px' }} @@ -60,8 +67,10 @@ function ProportionalToAttributes({ handleChange('boostImpact', value)} + value={boostImpact} + onChange={(value: string): void => handleChange('boost_impact', value)} label={t('boostConfig.boostImpact')} required showError={showError} @@ -72,10 +81,10 @@ function ProportionalToAttributes({ label={t('boostConfig.scaleFactor')} required inputProps={{ - min: 0, + min: 1, }} value={scaleFactor} - onChange={(value: number): void => handleChange('scaleFactor', value)} + onChange={(value: number): void => handleChange('scale_factor', value)} showError={showError} /> diff --git a/packages/shared/src/services/hydra.ts b/packages/shared/src/services/hydra.ts index 38ba3d10..36d124ad 100644 --- a/packages/shared/src/services/hydra.ts +++ b/packages/shared/src/services/hydra.ts @@ -241,9 +241,9 @@ export function inputInitializer(input: string): unknown { case 'proportionalToAttribute': return { - sourceField: undefined, - boostImpact: undefined, - scaleFactor: 0, + source_field_code: undefined, + boost_impact: undefined, + scale_factor: 1, } default: