ENG-3180: Migrate messaging template forms to Ant Design#7939
ENG-3180: Migrate messaging template forms to Ant Design#7939gilluminate wants to merge 3 commits intomainfrom
Conversation
Replace Formik + Chakra-backed inputs (CustomTextInput, CustomTextArea,
CustomSwitch) with antd Form + Form.Item + native antd inputs across
the messaging-templates feature. Submit button derives disabled state
from form.isFieldsTouched() + form.getFieldsError() inside a
shouldUpdate render-prop, with no extra useState/useEffect. The form
re-mounts via a content-hashed key prop so antd's "touched" state
resets after a successful save without a setFieldsValue dance.
AddMessagingTemplateModal switches to the standard modal body pattern
(footer={null} with buttons inside the body) and Typography.Paragraph,
and the template-type-selector test id moves directly onto the Select.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
There was a problem hiding this comment.
Code Review: Migrate messaging template forms to Ant Design
Overall, this is a well-structured migration. The shouldUpdate render-prop for disabled Save state, the controlled PropertiesList adapter (value/onChange), and the use of Form.Item with nested field names are all the right antd patterns. The removal of Chakra and Formik dependencies is clean.
Must Fix
1. router.push() in Cancel button (PropertySpecificMessagingTemplateForm.tsx:77)
The Cancel button uses router.push() in an onClick handler. This should be a <NextLink href={...} passHref> wrapping the <Button> instead, which gives correct <a> semantics, right-click / open-in-new-tab support, and Next.js prefetching. The handleCancel function and useRouter import can then be dropped.
2. isFieldsTouched() may not detect property-only edits (PropertySpecificMessagingTemplateForm.tsx:158)
PropertiesList drives the properties field via onChange?.(newValues) through ScrollableList. If antd doesn't mark that field as "touched" through the Form.Item value-control bridge, a user who only adds/removes a property (without touching subject or body) will find Save permanently disabled. This is a potential user-facing bug. Fix by explicitly calling form.setFields([{ name: 'properties', touched: true }]) in PropertiesList's onChange, or by using a useState dirty flag.
Suggestions
3. formKey includes mutable template content (PropertySpecificMessagingTemplateForm.tsx:91)
Including content.subject and content.body in the form's key means any background re-fetch returning data that differs from the user's in-progress edits will silently discard those edits (a React key change causes a full unmount). Scope the key to template.id (or template.id + template.type) only, and use form.setFieldsValue in the parent page's save-success callback instead.
4. resetFields() + setFieldsValue() ordering (EmailTemplatesForm.tsx:56-57)
The sequence is correct, but the dependency between the two calls is non-obvious to the next reader. A comment explaining the intent (or collapsing to just setFieldsValue(values)) would improve maintainability.
5. destroyOnHidden prop name (AddMessagingTemplateModal.tsx:37)
Verify that the fidesui Modal wrapper forwards destroyOnHidden. In some antd versions this prop is named destroyOnClose. If it isn't forwarded, the selectedTemplateId state won't reset between modal openings.
🔬 Codegraph: connected (46727 nodes)
💡 Write /code-review in a comment to re-run this review.
|
Re: review item #5 ( |
- Swap Cancel Button for NextLink wrapper for proper link semantics - Scope formKey to template.id || template.type so background refetches don't discard in-progress edits - Reset touched state via onFinish wrapper on successful save; handleSubmit now returns Promise<boolean> so the form can tell success from failure - Expand inline comment explaining why EmailTemplatesForm needs both resetFields() and setFieldsValue() after a successful save
Ticket ENG-3180
Description Of Changes
Part of the ENG-3165 epic to eliminate Chakra form components across admin-ui. The messaging template forms in
clients/admin-ui/src/features/messaging-templates/previously used Formik + Chakra-backed wrappers (CustomTextInput,CustomTextArea,CustomSwitch). They now use antdForm+Form.Item+ native antd inputs, matching the pattern established byOrganizationForm,SharedMonitorConfigForm, andDeleteUserModal.API contracts and submit payload shapes are unchanged so the backend is unaffected and existing Cypress coverage stays valid. The Save button derives its disabled state directly from
form.isFieldsTouched()+form.getFieldsError()inside ashouldUpdaterender-prop — no extrauseState/useEffectfor dirty tracking. The form re-mounts via a content-hashedkeyprop so antd's "touched" state resets after a successful save without asetFieldsValuedance.AddMessagingTemplateModalwas also tidied up: it now uses the standard modal body pattern (footer={null}with action buttons inside the body),Typography.Paragraphinstead of bespoke Tailwind, and thetemplate-type-selectortest id sits directly on the<Select>.Code Changes
PropertySpecificMessagingTemplateForm.tsx— Formik → antdForm. ReplacedCustomTextInput/CustomTextArea/CustomSwitchwithInput/Input.TextArea/Switch. WrappedScrollableListin a controlledPropertiesListadapter that bridges antd'svalue/onChangeto ScrollableList'svalues/setValues. ReplacedFormSectionwith antdCard. Submit-button disabled state derives from form built-ins inside ashouldUpdaterender-prop. Form re-mounts via a content-hashkeyto reset touched state after save.EmailTemplatesForm.tsx— Formik → antdFormwith nestednamearrays.form.resetFields()+form.setFieldsValue(values)re-baselines after a successful save. SameshouldUpdatesubmit pattern.FormSectionreplaced with antdCard.AddMessagingTemplateModal.tsx— droppedChakraBox/ChakraTextaliases. Moved action buttons out of thefooterprop into the standard bodyFlex. Switched description copy toTypography.Paragraph. Removed the wrapper<div>aroundSelectand moveddata-testid="template-type-selector"directly onto theSelect. Fixed a pre-existing invalidgap="medium"→gap="small"on antdFlex.pages/notifications/templates/add-template.tsxand[id].tsx— destructureisLoadingoff the create/put mutation and pass asisSavingprop to the form (the form no longer owns the submitting state).cypress/e2e/messaging.cy.ts— updated the template-type-selector assertion to call.antSelect(...)directly on the testid'd Select element instead of.find(".ant-select").antSelect(...).Steps to Confirm
cd clients/admin-ui && npm run dev, log in withroot_user/Testpassword1!ruleserrors display under each field.npx cypress run --spec cypress/e2e/messaging.cy.tsfromclients/admin-ui— should pass.Pre-Merge Checklist
CHANGELOG.mdupdatedmaindowngrade()migration is correct and works