Skip to content
Merged
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [v6.271.0](https://github.com/opengovsg/FormSG/compare/v6.270.0...v6.271.0)

- feat: respondent copy v3 (phase 1) [`#8854`](https://github.com/opengovsg/FormSG/pull/8854)
- fix: remove noisy chromatic diffs due to dynamic dates and form link [`#8903`](https://github.com/opengovsg/FormSG/pull/8903)
- build: release al2 6.270.0 back to develop [`#8904`](https://github.com/opengovsg/FormSG/pull/8904)
- build: release v6.270.0 [`#8902`](https://github.com/opengovsg/FormSG/pull/8902)

#### [v6.270.0](https://github.com/opengovsg/FormSG/compare/v6.269.0...v6.270.0)

> 14 November 2025

- feat: remove un-neeeded dd tracing and browser installation in the setup [`#8901`](https://github.com/opengovsg/FormSG/pull/8901)
- feat: remove signature beta label [`#8898`](https://github.com/opengovsg/FormSG/pull/8898)
- feat: enable save draft instrumentation basic again [`#8899`](https://github.com/opengovsg/FormSG/pull/8899)
- fix(copy): fixed copy for toast message on form open [`#8900`](https://github.com/opengovsg/FormSG/pull/8900)
- build: merge v6.269.0 back to develop [`#8897`](https://github.com/opengovsg/FormSG/pull/8897)
- build: release v6.269.0 [`#8896`](https://github.com/opengovsg/FormSG/pull/8896)
- chore: bump version to v6.270.0 [`f2df60b`](https://github.com/opengovsg/FormSG/commit/f2df60b99a67cc54c8abaeb8c824a339a85934aa)

#### [v6.269.0](https://github.com/opengovsg/FormSG/compare/v6.268.1...v6.269.0)

Expand Down
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "form-frontend",
"version": "6.270.0",
"version": "6.271.0",
"homepage": ".",
"type": "module",
"private": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ export const EditEmail = ({ field }: EditEmailProps): JSX.Element => {
form?.responseMode === FormResponseMode.Email || isPaymentDisabledForm

const pdfResponseToggleDescription = isPdfResponseEnabled
? undefined
? t(
'features.adminForm.sidebar.fields.email.emailConfirmation.includeResponseDescription',
)
: t(
'features.adminForm.sidebar.fields.email.emailConfirmation.includePdfResponseWarning',
)
Expand Down Expand Up @@ -185,52 +187,6 @@ export const EditEmail = ({ field }: EditEmailProps): JSX.Element => {
)}
/>
</FormControl>
<FormControl isReadOnly={isLoading}>
<Toggle
{...register('isVerifiable')}
label={t(
'features.adminForm.sidebar.fields.email.otpVerification.title',
)}
description={t(
'features.adminForm.sidebar.fields.email.otpVerification.description',
)}
/>
</FormControl>
<Box>
<FormControl isReadOnly={isLoading}>
<Toggle
{...allowedEmailDomainsRegister}
ref={mergedAllowedEmailDomainsRef}
label={t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.title',
)}
/>
</FormControl>
{watchedHasAllowedEmailDomains && (
<FormControl
isReadOnly={isLoading}
isRequired
isInvalid={!!errors.allowedEmailDomains}
mt="1.5rem"
>
<FormLabel>
{t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.inputLabel',
)}
</FormLabel>
<Textarea
autoFocus
{...register('allowedEmailDomains', emailDomainsValidation)}
placeholder={t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.placeholder',
)}
/>
<FormErrorMessage>
{errors?.allowedEmailDomains?.message}
</FormErrorMessage>
</FormControl>
)}
</Box>
<Box>
<FormControl
isReadOnly={isLoading}
Expand All @@ -248,13 +204,25 @@ export const EditEmail = ({ field }: EditEmailProps): JSX.Element => {
</FormControl>
{watchedHasAutoReply && (
<>
<FormControl isReadOnly={isLoading} mt="1.5rem">
<Toggle
{...register('autoReplyOptions.includeFormSummary')}
label={t(
'features.adminForm.sidebar.fields.email.emailConfirmation.includeResponse',
)}
description={pdfResponseToggleDescription}
isDisabled={!isPdfResponseEnabled}
/>
</FormControl>
<FormControl isRequired isReadOnly={isLoading} mt="1.5rem">
<FormLabel>Subject</FormLabel>
<Input
autoFocus
placeholder={t(
'features.adminForm.sidebar.fields.email.emailConfirmation.subject.placeholder',
{ formTitle: form?.title },
)}
_placeholder={{ color: 'secondary.700' }}
{...register('autoReplyOptions.autoReplySubject')}
/>
</FormControl>
Expand All @@ -265,9 +233,8 @@ export const EditEmail = ({ field }: EditEmailProps): JSX.Element => {
)}
</FormLabel>
<Input
placeholder={t(
'features.adminForm.sidebar.fields.email.emailConfirmation.senderName.placeholder',
)}
placeholder={form?.admin.agency.fullName}
_placeholder={{ color: 'secondary.700' }}
{...register('autoReplyOptions.autoReplySender')}
/>
</FormControl>
Expand All @@ -280,23 +247,66 @@ export const EditEmail = ({ field }: EditEmailProps): JSX.Element => {
<Textarea
placeholder={t(
'features.adminForm.sidebar.fields.email.emailConfirmation.content.placeholder',
{ agencyName: form?.admin.agency.fullName },
)}
sx={{
'::placeholder': {
color: 'secondary.700',
opacity: 1,
},
}}
{...register('autoReplyOptions.autoReplyMessage')}
/>
</FormControl>
<FormControl isReadOnly={isLoading} mt="1.5rem">
<Toggle
{...register('autoReplyOptions.includeFormSummary')}
label={t(
'features.adminForm.sidebar.fields.email.emailConfirmation.includePdfResponse',
)}
description={pdfResponseToggleDescription}
isDisabled={!isPdfResponseEnabled}
/>
</FormControl>
</>
)}
</Box>
<FormControl isReadOnly={isLoading}>
<Toggle
{...register('isVerifiable')}
label={t(
'features.adminForm.sidebar.fields.email.otpVerification.title',
)}
description={t(
'features.adminForm.sidebar.fields.email.otpVerification.description',
)}
/>
</FormControl>
<Box>
<FormControl isReadOnly={isLoading}>
<Toggle
{...allowedEmailDomainsRegister}
ref={mergedAllowedEmailDomainsRef}
label={t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.title',
)}
/>
</FormControl>
{watchedHasAllowedEmailDomains && (
<FormControl
isReadOnly={isLoading}
isRequired
isInvalid={!!errors.allowedEmailDomains}
mt="1.5rem"
>
<FormLabel>
{t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.inputLabel',
)}
</FormLabel>
<Textarea
autoFocus
{...register('allowedEmailDomains', emailDomainsValidation)}
placeholder={t(
'features.adminForm.sidebar.fields.email.restrictEmailDomains.placeholder',
)}
/>
<FormErrorMessage>
{errors?.allowedEmailDomains?.message}
</FormErrorMessage>
</FormControl>
)}
</Box>
<FormFieldDrawerActions
isLoading={isLoading}
buttonText={buttonText}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ const PrintableResponseRows = ({
)
}

const isTest = import.meta.env.STORYBOOK_NODE_ENV === 'test'
const MOCK_CONSTANT_FORM_LINK = 'https://form.gov.sg/64e2f7ae841cbe0012e785e7'

export const PrintableResponse = ({
formTitle,
formId,
Expand Down Expand Up @@ -210,9 +213,11 @@ export const PrintableResponse = ({
color="white"
textDecor="underline"
textDecorationColor="white"
data-chromatic="ignore"
>
{window.location.origin}/{formId}
{/* RATIONALE: Prevent noisy diffs from being detected during storybook snapshot comparisons due to dynamic form link. */}
{isTest
? MOCK_CONSTANT_FORM_LINK
: `${window.location.origin}/${formId}`}
</Text>
</Box>
<Box mx="5%" my="30px">
Expand Down
20 changes: 14 additions & 6 deletions frontend/src/features/public-form/PublicFormProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ interface PublicFormProviderProps {
isPublicFormPage?: boolean
}

const DATE_TIME_FORMAT_STRING = 'do MMM yyyy, h:mm:ss a'
const MOCK_CONSTANT_LAST_SAVED_DATETIME = '2025-11-14T12:00:00.000Z'

export function useCommonFormProvider(formId: string) {
// For mobile section sidebar
const {
Expand Down Expand Up @@ -1388,6 +1391,16 @@ export const PublicFormProvider = ({
return <NotFoundErrorPage />
}

// RATIONALE: Prevent noisy diffs from being detected during storybook snapshot comparisons due to dynamic date time.
const draftLastSavedDateTime =
draftSubmission?.lastUpdated && isTest
? MOCK_CONSTANT_LAST_SAVED_DATETIME
: draftSubmission?.lastUpdated

const draftLastSavedDateTimeString = draftLastSavedDateTime
? format(new Date(draftLastSavedDateTime), DATE_TIME_FORMAT_STRING)
: undefined

return (
<PublicFormContext.Provider
value={{
Expand All @@ -1412,12 +1425,7 @@ export const PublicFormProvider = ({
previousAttachments,
setPreviousSubmission,
isSaveDraftEnabled,
draftLastSavedDateTimeString: draftSubmission?.lastUpdated
? format(
new Date(draftSubmission.lastUpdated),
'do MMM yyyy, h:mm:ss a',
)
: undefined,
draftLastSavedDateTimeString,
onSaveDraft,
defaultFormValues,
augmentedFormFields,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,22 @@ export const enSG: Fields = {
description: 'Customise an email acknowledgement to respondents',
subject: {
title: 'Subject',
placeholder: 'Default email subject',
placeholder: 'Thank you for submitting {formTitle}',
},
senderName: {
title: 'Sender name',
placeholder: 'Default sender name is your agency name',
},
content: {
title: 'Content',
placeholder: 'Default email body',
placeholder:
'To whom it may concern,\n\nThank you for submitting this form.\n\nRegards,\n{agencyName}',
},
includePdfResponse: 'Include PDF response',
includeResponse: 'Include a copy of their responses',
includePdfResponseWarning:
'PDF responses are not available for payment forms.',
includeResponseDescription:
'Responses are included in the email and as a PDF attachment',
},
},
mobileNo: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ export interface Fields {
title: string
placeholder: string
}
includePdfResponse: string
includeResponse: string
includePdfResponseWarning: string
includeResponseDescription: string
}
}
mobileNo: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const enSG: Fields = {
domainDisallowed:
'The entered email does not belong to an allowed email domain',
},
respondentCopyHelperText:
'A copy of your responses will be sent to this email address',
},
verification: {
button: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface Fields {
validation: {
domainDisallowed: string
}
respondentCopyHelperText: string
}
attachment: {
disabled: string
Expand Down
Loading
Loading