Skip to content

Commit 6dbc215

Browse files
authored
feat(protocol-designer): update logic for form error rendering (#16611)
AUTH-989
1 parent e88d6f2 commit 6dbc215

File tree

18 files changed

+362
-23
lines changed

18 files changed

+362
-23
lines changed

protocol-designer/src/molecules/InputStepFormField/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface InputStepFormFieldProps extends FieldProps {
88
padding?: string
99
showTooltip?: boolean
1010
caption?: string
11+
formLevelError?: string | null
1112
}
1213

1314
export function InputStepFormField(
@@ -26,6 +27,7 @@ export function InputStepFormField(
2627
padding = SPACING.spacing16,
2728
tooltipContent,
2829
caption,
30+
formLevelError,
2931
...otherProps
3032
} = props
3133
const { t } = useTranslation('tooltip')
@@ -40,7 +42,7 @@ export function InputStepFormField(
4042
title={title}
4143
caption={caption}
4244
name={name}
43-
error={errorToShow}
45+
error={formLevelError ?? errorToShow}
4446
onBlur={onFieldBlur}
4547
onFocus={onFieldFocus}
4648
onChange={e => {

protocol-designer/src/molecules/ToggleExpandStepFormField/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ interface ToggleExpandStepFormFieldProps extends FieldProps {
2626
offLabel?: string
2727
caption?: string
2828
toggleElement?: 'toggle' | 'checkbox'
29+
formLevelError?: string | null
2930
}
3031
export function ToggleExpandStepFormField(
3132
props: ToggleExpandStepFormFieldProps

protocol-designer/src/molecules/ToggleStepFormField/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ export function ToggleStepFormField(
5252
<Flex
5353
justifyContent={JUSTIFY_SPACE_BETWEEN}
5454
alignItems={ALIGN_CENTER}
55-
{...targetProps}
5655
>
5756
<StyledText desktopStyle="bodyDefaultRegular">{title}</StyledText>
5857
<Flex alignItems={ALIGN_CENTER} gridGap={SPACING.spacing4}>
58+
{tooltipContent != null ? (
59+
<Tooltip tooltipProps={tooltipProps}>{tooltipContent}</Tooltip>
60+
) : null}
5961
<StyledText
6062
desktopStyle="bodyDefaultRegular"
6163
color={COLORS.grey60}
64+
{...targetProps}
6265
>
6366
{isSelected ? onLabel : offLabel}
6467
</StyledText>
@@ -76,9 +79,6 @@ export function ToggleStepFormField(
7679
</Flex>
7780
</Flex>
7881
</ListItem>
79-
{tooltipContent != null ? (
80-
<Tooltip tooltipProps={tooltipProps}>{tooltipContent}</Tooltip>
81-
) : null}
8282
</>
8383
)
8484
}

protocol-designer/src/organisms/Alerts/FormAlerts.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,16 @@ function FormAlertsComponent(props: FormAlertsProps): JSX.Element | null {
121121
</Flex>
122122
)
123123
const formErrors = [
124-
...visibleFormErrors.map(error => ({
125-
title: error.title,
126-
description: error.body || null,
127-
})),
124+
...visibleFormErrors.reduce((acc, error) => {
125+
return error.showAtForm ?? true
126+
? {
127+
...acc,
128+
title: error.title,
129+
description: error.body || null,
130+
showAtForm: error.showAtForm ?? true,
131+
}
132+
: acc
133+
}, []),
128134
...visibleDynamicFieldFormErrors.map(error => ({
129135
title: error.title,
130136
description: error.body || null,

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
254254
focusHandlers,
255255
toolboxStep,
256256
visibleFormErrors,
257+
showFormErrors: showFormErrorsAndWarnings,
258+
focusedField,
259+
setShowFormErrorsAndWarnings,
257260
}}
258261
/>
259262
</Toolbox>

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/HeaterShakerTools/index.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@ import {
1616
ToggleExpandStepFormField,
1717
ToggleStepFormField,
1818
} from '../../../../../../molecules'
19+
import { getFormErrorsMappedToField, getFormLevelError } from '../../utils'
1920
import type { StepFormProps } from '../../types'
2021

2122
export function HeaterShakerTools(props: StepFormProps): JSX.Element {
22-
const { propsForFields, formData } = props
23+
const {
24+
propsForFields,
25+
formData,
26+
showFormErrors = false,
27+
focusedField = null,
28+
visibleFormErrors,
29+
} = props
2330
const { t } = useTranslation(['application', 'form', 'protocol_steps'])
2431
const moduleLabwareOptions = useSelector(getHeaterShakerLabwareOptions)
2532

@@ -29,6 +36,8 @@ export function HeaterShakerTools(props: StepFormProps): JSX.Element {
2936
}
3037
}, [])
3138

39+
const mappedErrorsToField = getFormErrorsMappedToField(visibleFormErrors)
40+
3241
return (
3342
<Flex flexDirection={DIRECTION_COLUMN}>
3443
{moduleLabwareOptions.length > 1 ? (
@@ -82,6 +91,12 @@ export function HeaterShakerTools(props: StepFormProps): JSX.Element {
8291
offLabel={t(
8392
'form:step_edit_form.field.heaterShaker.temperature.toggleOff'
8493
)}
94+
formLevelError={getFormLevelError(
95+
showFormErrors,
96+
'targetHeaterShakerTemperature',
97+
mappedErrorsToField,
98+
focusedField
99+
)}
85100
/>
86101
<ToggleExpandStepFormField
87102
{...propsForFields.targetSpeed}
@@ -95,6 +110,12 @@ export function HeaterShakerTools(props: StepFormProps): JSX.Element {
95110
offLabel={t(
96111
'form:step_edit_form.field.heaterShaker.shaker.toggleOff'
97112
)}
113+
formLevelError={getFormLevelError(
114+
showFormErrors,
115+
'targetSpeed',
116+
mappedErrorsToField,
117+
focusedField
118+
)}
98119
/>
99120
<ToggleStepFormField
100121
isDisabled={propsForFields.latchOpen.disabled}
@@ -121,6 +142,12 @@ export function HeaterShakerTools(props: StepFormProps): JSX.Element {
121142
isSelected={formData.heaterShakerSetTimer === true}
122143
units={t('application:units.time')}
123144
toggleElement="checkbox"
145+
formLevelError={getFormLevelError(
146+
showFormErrors,
147+
'heaterShakerTimer',
148+
mappedErrorsToField,
149+
focusedField
150+
)}
124151
/>
125152
</Flex>
126153
</Flex>

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/PauseTools/index.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@ import {
2828
import { InputStepFormField } from '../../../../../../molecules'
2929
import { getInitialDeckSetup } from '../../../../../../step-forms/selectors'
3030
import { selectors as uiModuleSelectors } from '../../../../../../ui/modules'
31+
import { getFormErrorsMappedToField, getFormLevelError } from '../../utils'
3132

3233
import type { ChangeEvent } from 'react'
3334
import type { StepFormProps } from '../../types'
3435

3536
export function PauseTools(props: StepFormProps): JSX.Element {
36-
const { propsForFields } = props
37+
const {
38+
propsForFields,
39+
visibleFormErrors,
40+
focusedField,
41+
showFormErrors,
42+
setShowFormErrorsAndWarnings,
43+
} = props
3744

3845
const tempModuleLabwareOptions = useSelector(
3946
uiModuleSelectors.getTemperatureLabwareOptions
@@ -75,6 +82,8 @@ export function PauseTools(props: StepFormProps): JSX.Element {
7582

7683
const { pauseAction } = props.formData
7784

85+
const mappedErrorsToField = getFormErrorsMappedToField(visibleFormErrors)
86+
7887
return (
7988
<>
8089
<Flex flexDirection={DIRECTION_COLUMN}>
@@ -88,6 +97,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
8897
<RadioButton
8998
onChange={(e: ChangeEvent<any>) => {
9099
propsForFields.pauseAction.updateValue(e.currentTarget.value)
100+
setShowFormErrorsAndWarnings?.(false)
91101
}}
92102
buttonLabel={t(
93103
'form:step_edit_form.field.pauseAction.options.untilResume'
@@ -101,6 +111,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
101111
<RadioButton
102112
onChange={(e: ChangeEvent<any>) => {
103113
propsForFields.pauseAction.updateValue(e.currentTarget.value)
114+
setShowFormErrorsAndWarnings?.(false)
104115
}}
105116
buttonLabel={t(
106117
'form:step_edit_form.field.pauseAction.options.untilTime'
@@ -112,6 +123,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
112123
<RadioButton
113124
onChange={(e: ChangeEvent<any>) => {
114125
propsForFields.pauseAction.updateValue(e.currentTarget.value)
126+
setShowFormErrorsAndWarnings?.(false)
115127
}}
116128
buttonLabel={t(
117129
'form:step_edit_form.field.pauseAction.options.untilTemperature'
@@ -146,6 +158,12 @@ export function PauseTools(props: StepFormProps): JSX.Element {
146158
units={t('application:units.time_hms')}
147159
padding="0"
148160
showTooltip={false}
161+
formLevelError={getFormLevelError(
162+
showFormErrors,
163+
'pauseTime',
164+
mappedErrorsToField,
165+
focusedField
166+
)}
149167
/>
150168
</Flex>
151169
</Flex>
@@ -184,6 +202,12 @@ export function PauseTools(props: StepFormProps): JSX.Element {
184202
errorToShow={propsForFields.pauseTemperature.errorToShow}
185203
padding="0"
186204
showTooltip={false}
205+
formLevelError={getFormLevelError(
206+
showFormErrors,
207+
'pauseTemperature',
208+
mappedErrorsToField,
209+
focusedField
210+
)}
187211
/>
188212
</Flex>
189213
</>

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/ProfileSettings.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,27 @@ import {
66
StyledText,
77
} from '@opentrons/components'
88
import { InputStepFormField } from '../../../../../../molecules'
9+
import { getFormErrorsMappedToField, getFormLevelError } from '../../utils'
910

11+
import type { StepFormErrors } from '../../../../../../steplist'
1012
import type { FieldPropsByName } from '../../types'
1113

1214
interface ProfileSettingsProps {
1315
propsForFields: FieldPropsByName
16+
showFormErrors: boolean
17+
visibleFormErrors: StepFormErrors
18+
focusedField?: string | null
1419
}
1520
export function ProfileSettings(props: ProfileSettingsProps): JSX.Element {
16-
const { propsForFields } = props
21+
const {
22+
propsForFields,
23+
showFormErrors,
24+
visibleFormErrors,
25+
focusedField,
26+
} = props
27+
28+
const mappedErrorsToField = getFormErrorsMappedToField(visibleFormErrors)
29+
1730
const { i18n, t } = useTranslation(['application', 'form'])
1831
return (
1932
<Flex
@@ -30,6 +43,12 @@ export function ProfileSettings(props: ProfileSettingsProps): JSX.Element {
3043
units={t('units.microliter')}
3144
padding="0"
3245
showTooltip={false}
46+
formLevelError={getFormLevelError(
47+
showFormErrors,
48+
'profileVolume',
49+
mappedErrorsToField,
50+
focusedField
51+
)}
3352
/>
3453
<InputStepFormField
3554
{...propsForFields.profileTargetLidTemp}
@@ -40,6 +59,12 @@ export function ProfileSettings(props: ProfileSettingsProps): JSX.Element {
4059
units={t('units.degrees')}
4160
padding="0"
4261
showTooltip={false}
62+
formLevelError={getFormLevelError(
63+
showFormErrors,
64+
'profileTargetLidTemp',
65+
mappedErrorsToField,
66+
focusedField
67+
)}
4368
/>
4469
</Flex>
4570
)

protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/ThermocyclerState.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,36 @@ import {
1010
ToggleExpandStepFormField,
1111
ToggleStepFormField,
1212
} from '../../../../../../molecules'
13+
import { getFormErrorsMappedToField, getFormLevelError } from '../../utils'
1314

1415
import type { FormData } from '../../../../../../form-types'
16+
import type { StepFormErrors } from '../../../../../../steplist'
1517
import type { FieldPropsByName } from '../../types'
1618

1719
interface ThermocyclerStateProps {
1820
title: string
1921
formData: FormData
2022
propsForFields: FieldPropsByName
2123
isHold?: boolean
24+
visibleFormErrors: StepFormErrors
25+
showFormErrors?: boolean
26+
focusedField?: string | null
2227
}
2328

2429
export function ThermocyclerState(props: ThermocyclerStateProps): JSX.Element {
25-
const { title, propsForFields, formData, isHold = false } = props
30+
const {
31+
title,
32+
propsForFields,
33+
formData,
34+
isHold = false,
35+
visibleFormErrors,
36+
showFormErrors = true,
37+
focusedField,
38+
} = props
2639
const { i18n, t } = useTranslation(['application', 'form'])
2740

41+
const mappedErrorsToField = getFormErrorsMappedToField(visibleFormErrors)
42+
2843
const {
2944
blockFieldActive,
3045
lidFieldActive,
@@ -68,6 +83,12 @@ export function ThermocyclerState(props: ThermocyclerStateProps): JSX.Element {
6883
isSelected={formData[blockFieldActive] === true}
6984
onLabel={t('form:step_edit_form.field.heaterShaker.shaker.toggleOn')}
7085
offLabel={t('form:step_edit_form.field.heaterShaker.shaker.toggleOff')}
86+
formLevelError={getFormLevelError(
87+
showFormErrors,
88+
blockTempField,
89+
mappedErrorsToField,
90+
focusedField
91+
)}
7192
/>
7293
<ToggleExpandStepFormField
7394
{...propsForFields[lidTempField]}
@@ -81,6 +102,12 @@ export function ThermocyclerState(props: ThermocyclerStateProps): JSX.Element {
81102
offLabel={t(
82103
'form:step_edit_form.field.thermocyclerState.lid.toggleOff'
83104
)}
105+
formLevelError={getFormLevelError(
106+
showFormErrors,
107+
lidTempField,
108+
mappedErrorsToField,
109+
focusedField
110+
)}
84111
/>
85112
<ToggleStepFormField
86113
isDisabled={propsForFields[lidPositionField].disabled}

0 commit comments

Comments
 (0)