Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/7939-messaging-templates-antd-form.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type: Changed
description: Migrated messaging template forms to Ant Design Form
pr: 7939
labels: []
6 changes: 3 additions & 3 deletions clients/admin-ui/cypress/e2e/messaging.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ describe("Messaging", () => {

cy.getByTestId("add-message-btn").click();

cy.getByTestId("template-type-selector")
.find(".ant-select")
.antSelect("Access request completed");
cy.getByTestId("template-type-selector").antSelect(
"Access request completed",
);

cy.getByTestId("confirm-btn").click();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
Button,
ChakraBox as Box,
ChakraText as Text,
Flex,
Modal,
Select,
} from "fidesui";
import { Button, Flex, Modal, Select, Typography } from "fidesui";
import { useState } from "react";

import { MODAL_SIZE } from "~/features/common/modals/modal-sizes";
Expand Down Expand Up @@ -45,47 +38,35 @@ const AddMessagingTemplateModal = ({
width={MODAL_SIZE.md}
data-testid="add-messaging-template-modal"
title="Select message template"
footer={
<Flex className="w-full" gap="medium">
<Button onClick={onClose} data-testid="cancel-btn" className="grow">
Cancel
</Button>
<Button
onClick={() => onAccept(selectedTemplateId!)}
type="primary"
data-testid="confirm-btn"
disabled={!selectedTemplateId}
className="grow"
>
Next
</Button>
</Flex>
}
footer={null}
>
<Text
color="gray.700"
fontWeight="medium"
fontSize="sm"
marginBottom={3}
marginTop={1}
>
<Typography.Paragraph>
Add a new email message by selecting a template below and clicking
accept.
</Text>
<Text color="gray.700" fontSize="sm" fontWeight="medium" marginBottom={2}>
Choose template:
</Text>

<Box data-testid="template-type-selector">
<Select<string>
options={options}
onChange={(value) => {
setSelectedTemplateType(value);
}}
className="w-full"
aria-label="Select a template"
/>
</Box>
</Typography.Paragraph>
<Select<string>
data-testid="template-type-selector"
options={options}
onChange={(value) => {
setSelectedTemplateType(value);
}}
className="w-full"
placeholder="Choose template"
aria-label="Select a template"
/>
<Flex justify="flex-end" className="mt-4" gap="small">
<Button onClick={onClose} data-testid="cancel-btn">
Cancel
</Button>
<Button
onClick={() => onAccept(selectedTemplateId!)}
type="primary"
data-testid="confirm-btn"
disabled={!selectedTemplateId}
>
Next
</Button>
</Flex>
</Modal>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { SerializedError } from "@reduxjs/toolkit";
import { FetchBaseQueryError } from "@reduxjs/toolkit/query";
import {
Button,
ChakraBox as Box,
ChakraFlex as Flex,
useMessage,
} from "fidesui";
import { Form, Formik, FormikHelpers } from "formik";
import { Button, Card, Flex, Form, Input, useMessage } from "fidesui";

import FormSection from "~/features/common/form/FormSection";
import { CustomTextArea, CustomTextInput } from "~/features/common/form/inputs";
import { getErrorMessage, isErrorResult } from "~/features/common/helpers";

import {
Expand All @@ -36,11 +28,17 @@ const EmailTemplatesForm = ({ emailTemplates }: EmailTemplatesFormProps) => {
const [updateMessagingTemplates, { isLoading }] =
useUpdateMessagingTemplatesMutation();
const message = useMessage();
const [form] = Form.useForm<EmailTemplatesFormValues>();

const initialValues = emailTemplates.reduce(
(acc, template) => ({
...acc,
[template.type]: { label: template.label, content: template.content },
}),
{} as EmailTemplatesFormValues,
);

const handleSubmit = async (
values: EmailTemplatesFormValues,
formikHelpers: FormikHelpers<EmailTemplatesFormValues>,
) => {
const handleSubmit = async (values: EmailTemplatesFormValues) => {
const handleResult = (
result:
| { data: object }
Expand All @@ -54,7 +52,12 @@ const EmailTemplatesForm = ({ emailTemplates }: EmailTemplatesFormProps) => {
message.error(errorMsg);
} else {
message.success("Email templates saved.");
formikHelpers.resetForm({ values });
// Re-baseline the form: resetFields() clears antd's touched flags (but
// reverts to the original initialValues), then setFieldsValue re-applies
// the just-saved data on top. Together they make the saved values the
// new baseline so Save becomes disabled until the next edit.
form.resetFields();
form.setFieldsValue(values);
Comment thread
gilluminate marked this conversation as resolved.
}
};

Expand All @@ -70,52 +73,54 @@ const EmailTemplatesForm = ({ emailTemplates }: EmailTemplatesFormProps) => {
handleResult(result);
};

const initialValues = emailTemplates.reduce(
(acc, template) => ({
...acc,
[template.type]: { label: template.label, content: template.content },
}),
{} as EmailTemplatesFormValues,
);

return (
<Formik
enableReinitialize
<Form
form={form}
layout="vertical"
initialValues={initialValues}
onSubmit={handleSubmit}
onFinish={handleSubmit}
className="py-3"
>
{() => (
<Form
style={{
paddingTop: "12px",
paddingBottom: "12px",
}}
>
{Object.entries(initialValues).map(([key, value]) => (
<Box key={key} py={3}>
<FormSection title={value.label}>
<CustomTextInput
label="Message subject"
name={`${key}.content.subject`}
variant="stacked"
/>
<CustomTextArea
label="Message body"
name={`${key}.content.body`}
variant="stacked"
resize
/>
</FormSection>
</Box>
))}
<Flex justifyContent="right" width="100%" paddingTop={2}>
<Button htmlType="submit" type="primary" loading={isLoading}>
{Object.entries(initialValues).map(([key, value]) => (
<Card key={key} title={value.label} className="my-3">
<Form.Item
name={[key, "content", "subject"]}
label="Message subject"
rules={[{ required: true, message: "Subject is required" }]}
>
<Input data-testid={`input-${key}.content.subject`} />
</Form.Item>
<Form.Item
name={[key, "content", "body"]}
label="Message body"
rules={[{ required: true, message: "Body is required" }]}
>
<Input.TextArea
autoSize={{ minRows: 3 }}
data-testid={`input-${key}.content.body`}
/>
</Form.Item>
</Card>
))}
<Flex justify="flex-end" className="w-full pt-2">
<Form.Item shouldUpdate noStyle>
{() => (
<Button
htmlType="submit"
type="primary"
disabled={
!form.isFieldsTouched() ||
form.getFieldsError().some(({ errors }) => errors.length > 0)
}
Comment thread
gilluminate marked this conversation as resolved.
loading={isLoading}
data-testid="submit-btn"
>
Save
</Button>
</Flex>
</Form>
)}
</Formik>
)}
</Form.Item>
</Flex>
</Form>
);
};

Expand Down
Loading
Loading