Skip to content

Commit

Permalink
Merge pull request #201 from Elastic-Suite/fix-1282746-GridTextInputA…
Browse files Browse the repository at this point in the history
…reVeryBuggyAndSlowInGrid

fix(#1282746): [Grid] Add error validation in grid
  • Loading branch information
matthias-goupil authored Jun 26, 2024
2 parents 69bf638 + 2aace64 commit a63e496
Show file tree
Hide file tree
Showing 24 changed files with 256 additions and 61 deletions.
1 change: 1 addition & 0 deletions packages/components/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"formError.synonymTermsSizeInvalid": "Please provide at least two values in all \"synonyms\" fields.",
"formError.synonymTermsDuplicate": "There are duplicates among the \"synonyms\", please remove them.",
"formError.expansionTermsDuplicate": "There are duplicates among the \"expansion terms\", please remove them.",
"formError.prompt": "The prompt must contain a single occurrence of \"%s\".",
"field.productImage": "Product image",
"default.undefined": "empty",
"log.out": "Log out",
Expand Down
1 change: 1 addition & 0 deletions packages/components/public/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"formError.synonymTermsDuplicate": "Il y a des doublons parmi les \"synonymes\", veuillez les retirer.",
"formError.expansionTermsDuplicate": "Il y a des doublons parmi les \"termes étendus\", veuillez les retirer.",
"field.productImage": "Image produit",
"formError.prompt": "Le prompt doit contenir une seule occurrence de \"%s\".",
"default.undefined": "vide",
"log.out": "Déconnexion",
"entity": "Entité",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,19 @@ describe('RangeError', () => {
)
expect(screen.getByText('formError.erreur')).toBeInTheDocument()
})

it('should display a replacement error message with replacementErrorsMessages prop when the field has an error', () => {
renderWithProviders(
<DoubleDatePickerError
label="Label"
required
showError
value={{ toDate: null, fromDate: null }}
replacementErrorsMessages={{
valueMissing: 'customError',
}}
/>
)
expect(screen.getByText('formError.customError')).toBeInTheDocument()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ export function doubleDateValidator(
function DoubleDatePickerError(
props: IDoubleDatePickerErrorProps
): JSX.Element {
const { onChange, showError, additionalValidator, ...inputProps } = props
const {
onChange,
showError,
additionalValidator,
replacementErrorsMessages,
...inputProps
} = props

const validator = useCallback<IValidator>(
(value: IDoubleDatePickerValues, event) => {
Expand All @@ -66,7 +72,8 @@ function DoubleDatePickerError(
inputProps.value,
showError,
validator,
inputProps.disabled
inputProps.disabled,
replacementErrorsMessages
)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,19 @@ describe('DropDownError', () => {
)
expect(screen.getByText('formError.erreur')).toBeInTheDocument()
})

it('should display a replacement error message with replacementErrorsMessages prop when the field has an error', () => {
renderWithProviders(
<DropDownError
options={options}
required
showError
additionalValidator={(): string => 'erreur'}
replacementErrorsMessages={{
erreur: 'customError',
}}
/>
)
expect(screen.getByText('formError.customError')).toBeInTheDocument()
})
})
11 changes: 9 additions & 2 deletions packages/components/src/components/atoms/form/DropDownError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import Dropdown, { IDropDownProps } from './DropDown'
interface IDropDownErrorProps<T> extends IFieldErrorProps, IDropDownProps<T> {}

function DropdownError<T>(props: IDropDownErrorProps<T>): JSX.Element {
const { onChange, showError, additionalValidator, ...inputProps } = props
const {
onChange,
showError,
additionalValidator,
replacementErrorsMessages,
...inputProps
} = props

const validator = useCallback<IValidator>(
(value, event) => {
Expand All @@ -30,7 +36,8 @@ function DropdownError<T>(props: IDropDownErrorProps<T>): JSX.Element {
inputProps.value,
showError,
validator,
inputProps.disabled
inputProps.disabled,
replacementErrorsMessages
)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,21 @@ describe('InputTextError', () => {
)
expect(screen.getByText('formError.erreur')).toBeInTheDocument()
})

it('should display a replacement error message with replacementErrorsMessages prop when the field has an error', () => {
renderWithProviders(
<InputTextError
id="input-text"
label="Label"
placeholder="Name"
required
value=""
showError
replacementErrorsMessages={{
valueMissing: 'customError',
}}
/>
)
expect(screen.getByText('formError.customError')).toBeInTheDocument()
})
})
11 changes: 9 additions & 2 deletions packages/components/src/components/atoms/form/InputTextError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import InputText, { IInputTextProps } from './InputText'
interface IInputTextErrorProps extends IFieldErrorProps, IInputTextProps {}

function InputTextError(props: IInputTextErrorProps): JSX.Element {
const { onChange, showError, additionalValidator, ...inputProps } = props
const {
onChange,
showError,
additionalValidator,
replacementErrorsMessages,
...inputProps
} = props
const validator = useCallback<IValidator>(
(value, event) => {
if (additionalValidator) return additionalValidator(value, event)
Expand All @@ -21,7 +27,8 @@ function InputTextError(props: IInputTextErrorProps): JSX.Element {
inputProps.value,
showError,
validator,
inputProps.disabled
inputProps.disabled,
replacementErrorsMessages
)

return (
Expand Down
20 changes: 17 additions & 3 deletions packages/components/src/components/atoms/form/RangeError.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,25 @@ describe('RangeError', () => {
showError
required
value={[1, null]}
additionalValidator={(): string => {
return 'erreur'
}}
additionalValidator={(): string => 'erreur'}
/>
)
expect(screen.getByText('formError.erreur')).toBeInTheDocument()
})

it('should display a replacement error message with replacementErrorsMessages prop when the field has an error', () => {
renderWithProviders(
<RangeError
label="Label"
showError
required
value={[1, null]}
additionalValidator={(): string => 'erreur'}
replacementErrorsMessages={{
erreur: 'customError',
}}
/>
)
expect(screen.getByText('formError.customError')).toBeInTheDocument()
})
})
11 changes: 9 additions & 2 deletions packages/components/src/components/atoms/form/RangeError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import Range, { IRangeProps } from './Range'
interface IRangeErrorProps extends IFieldErrorProps, IRangeProps {}

function RangeError(props: IRangeErrorProps): JSX.Element {
const { onChange, showError, additionalValidator, ...inputProps } = props
const {
onChange,
showError,
additionalValidator,
replacementErrorsMessages,
...inputProps
} = props

const validator = useCallback<IValidator>(
(value: [number | string | null, number | string | null], event) => {
Expand All @@ -28,7 +34,8 @@ function RangeError(props: IRangeErrorProps): JSX.Element {
inputProps.value,
showError,
validator,
inputProps.disabled
inputProps.disabled,
replacementErrorsMessages
)

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const StickyActions = styled(Box)(({ theme }) => ({
backgroundColor: theme.palette.colors.white,
minHeight: '64px',
width: '100%',
margin: '32px 16px 16px 16px',
margin: '0px 16px 16px 16px',
border: 'solid',
borderColor: theme.palette.colors.neutral[300],
borderWidth: '1px',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ exports[`StickyBar should match snapshot 1`] = `
style="left: 0px;"
>
<div
class="MuiBox-root css-1dpte2y"
class="MuiBox-root css-1ed5lla"
>
<div>
Hello Sticky
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {
Dispatch,
FunctionComponent,
SetStateAction,
SyntheticEvent,
useEffect,
useMemo,
useState,
Expand Down Expand Up @@ -216,12 +217,18 @@ function ResourceTable(props: IResourceTable): JSX.Element {
function handleRowChange(
id: string | number,
name: string,
value: boolean | number | string
value: boolean | number | string,
event: SyntheticEvent,
showError: boolean
): void {
const validity = (event.target as HTMLInputElement)?.checkValidity()
if (update) {
update(id, { [name]: value })
update(id, { [name]: value }, !showError || validity)
} else if (replace) {
replace({ id, [name]: value } as unknown as ISourceField)
replace(
{ id, [name]: value } as unknown as ISourceField,
!showError || validity
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function EditableDropDownGuesser(props: IProps): JSX.Element {
helperText,
helperIcon,
showError,
replacementErrorsMessages,
} = props

const { t } = useTranslation('common')
Expand Down Expand Up @@ -94,6 +95,7 @@ function EditableDropDownGuesser(props: IProps): JSX.Element {
}
objectKeyValue={field?.gally?.options?.objectKeyValue}
sx={{ minWidth: '230.667px' }}
replacementErrorsMessages={replacementErrorsMessages}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element {
placeholder,
error,
helperText,
replacementErrorsMessages,
} = props

const { t } = useTranslation('common')
Expand Down Expand Up @@ -120,6 +121,7 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element {
type={input === DataContentType.NUMBER ? 'number' : 'text'}
value={value as string | number | null}
placeholder={placeholder}
replacementErrorsMessages={replacementErrorsMessages}
/>
)
}
Expand All @@ -141,6 +143,7 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element {
showError={showError}
suffix={suffix}
value={value as (string | number | null)[]}
replacementErrorsMessages={replacementErrorsMessages}
/>
)
}
Expand Down Expand Up @@ -267,6 +270,7 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element {
multiple={Boolean(value instanceof Array)}
error={error}
helperText={helperText}
replacementErrorsMessages={replacementErrorsMessages}
/>
)
}
Expand Down Expand Up @@ -295,6 +299,7 @@ function EditableFieldGuesser(props: IFieldGuesserProps): JSX.Element {
placeholder={placeholder}
error={error}
showError={showError}
replacementErrorsMessages={replacementErrorsMessages}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ interface IProps<T extends IHydraMember> {
id: string | number,
name: string,
value: boolean | number | string,
event: SyntheticEvent
event: SyntheticEvent,
showError?: boolean
) => void
resource: IResource
rowsPerPage?: number
Expand Down Expand Up @@ -128,6 +129,15 @@ function TableGuesser<T extends IHydraMember>(props: IProps<T>): JSX.Element {
}
}

function handleRowUpdate(
id: string | number,
name: string,
value: boolean | number | string,
event: SyntheticEvent
): void {
const field = tableHeaders.find((field) => field.name === name)
onRowUpdate(id, name, value, event, field?.showError)
}
return (
<>
<PagerTable
Expand All @@ -138,7 +148,7 @@ function TableGuesser<T extends IHydraMember>(props: IProps<T>): JSX.Element {
massiveSelectionState={massiveSelectionState}
massiveSelectionIndeterminate={massiveSelectionIndeterminate}
onPageChange={onPageChange}
onRowUpdate={onRowUpdate}
onRowUpdate={handleRowUpdate}
onSelection={handleSelection}
ref={tableRef}
rowsPerPage={rowsPerPage ?? defaultPageSize}
Expand Down
Loading

0 comments on commit a63e496

Please sign in to comment.