diff --git a/CHANGELOG.md b/CHANGELOG.md index c4fee55818..eba55d67cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [7.26.1](https://github.com/opengovsg/formsg/compare/v7.26.0...v7.26.1) (2026-06-09) + + +### Bug Fixes + +* add replyTo and X-Formsg-Submission-ID headers to MRF outcome emails (#9570) ([#9570](https://github.com/opengovsg/formsg/commit/b7e9c320686c326dc9c6518da4b3a97875cdc980)) + + +### Miscellaneous + +* Merge pull request #9568 from opengovsg/chore/revert-number-field-buttons-removal ([#9568](https://github.com/opengovsg/formsg/commit/d1698445285a9b0be20d5ecf02d955cbb2500081)) + ## [7.26.0](https://github.com/opengovsg/formsg/compare/v7.25.0...v7.26.0) (2026-06-08) diff --git a/apps/backend/package.json b/apps/backend/package.json index 8151795363..b0fa627d90 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -1,6 +1,6 @@ { "name": "formsg-backend", - "version": "7.26.0", + "version": "7.26.1", "private": true, "homepage": ".", "scripts": { diff --git a/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts b/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts index 3ebe7551dd..a79ed4e9b7 100644 --- a/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts +++ b/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts @@ -68,6 +68,7 @@ import { reportSubmissionResponseTime } from '../submissions.statsd-client' import { MultirespondentSubmissionContent } from './multirespondent-submission.types' import { + extractEmailAnswersFromResponses, extractRespondentCopyEmailDatas, formatSubmittedStepTimestamp, getEmailFromResponses, @@ -524,13 +525,17 @@ const sendMrfOutcomeEmails = ({ if (isApproval) { return MailService.sendMrfApprovalEmail({ emails: destinationEmails, - formId: form._id, + formId: String(form._id), formTitle: form.title, responseId: submissionId, + submissionId, timestamp: latestSubmissionTimestamp, isRejected, formQuestionAnswers, attachments: emailAttachments, + replyTo: + extractEmailAnswersFromResponses(responses).join(', ') || + undefined, }).orElse((error) => { logger.error({ message: 'Failed to send approval email', @@ -547,12 +552,15 @@ const sendMrfOutcomeEmails = ({ return MailService.sendMrfWorkflowCompletionEmail({ emails: destinationEmails, - formId: form._id, + formId: String(form._id), formTitle: form.title, responseId: submissionId, + submissionId, timestamp: latestSubmissionTimestamp, formQuestionAnswers, attachments: emailAttachments, + replyTo: + extractEmailAnswersFromResponses(responses).join(', ') || undefined, }).orElse((error) => { logger.error({ message: 'Failed to send workflow completion email', diff --git a/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.utils.ts b/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.utils.ts index 670ce3b9be..191fbb95d3 100644 --- a/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.utils.ts +++ b/apps/backend/src/app/modules/submission/multirespondent-submission/multirespondent-submission.utils.ts @@ -109,6 +109,23 @@ export const getEmailFromResponses = ( return field.answer.value } +export const extractEmailAnswersFromResponses = ( + responses: FieldResponsesV3, +): string[] => { + if (!responses) return [] + return Object.values(responses) + .filter( + ( + response, + ): response is Extract< + FieldResponseV3, + { fieldType: BasicField.Email } + > => response.fieldType === BasicField.Email, + ) + .map((response) => response.answer.value) + .filter(Boolean) +} + const getConditionalFieldEmailRecipient = ( form_fields: FormFieldSchema[] | FormFieldDto[], fieldId: string, diff --git a/apps/backend/src/app/services/mail/mail.service.ts b/apps/backend/src/app/services/mail/mail.service.ts index 5d9ba2dcb3..fffbb263d8 100644 --- a/apps/backend/src/app/services/mail/mail.service.ts +++ b/apps/backend/src/app/services/mail/mail.service.ts @@ -1186,17 +1186,21 @@ export class MailService { formId, formTitle, responseId, + submissionId, timestamp, formQuestionAnswers, attachments, + replyTo, }: { emails: string[] formId: string formTitle: string responseId: string + submissionId?: string timestamp: string formQuestionAnswers: QuestionAnswer[] attachments?: Mail.Attachment[] + replyTo?: string }): ResultAsync => { const emailTemplateData: EmailData = { formTitle, @@ -1213,6 +1217,8 @@ export class MailService { attachments, emailType: EmailType.WorkflowCompletion, actionName: 'sendMrfWorkflowCompletionEmail', + submissionId, + replyTo, }) } @@ -1221,19 +1227,23 @@ export class MailService { formId, formTitle, responseId, + submissionId, timestamp, isRejected, formQuestionAnswers, attachments, + replyTo, }: { emails: string[] formId: string formTitle: string responseId: string + submissionId?: string timestamp: string isRejected: boolean formQuestionAnswers: QuestionAnswer[] attachments?: Mail.Attachment[] + replyTo?: string }): ResultAsync => { const outcome = isRejected ? WorkflowOutcome.NOT_APPROVED @@ -1255,6 +1265,8 @@ export class MailService { attachments, emailType: EmailType.WorkflowApproval, actionName: 'sendMrfApprovalEmail', + submissionId, + replyTo, }) } diff --git a/apps/frontend/package.json b/apps/frontend/package.json index ddd9a21162..eca79c9e4b 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "formsg-frontend", - "version": "7.26.0", + "version": "7.26.1", "private": true, "homepage": ".", "type": "module", diff --git a/apps/frontend/src/templates/Field/Number/NumberField.test.tsx b/apps/frontend/src/templates/Field/Number/NumberField.test.tsx index 299dc210c5..75d928661a 100644 --- a/apps/frontend/src/templates/Field/Number/NumberField.test.tsx +++ b/apps/frontend/src/templates/Field/Number/NumberField.test.tsx @@ -13,16 +13,6 @@ import * as stories from './NumberField.stories' const { ValidationRequired, ValidationOptional } = composeStories(stories) describe('validation required', () => { - it('does not render stepper buttons', () => { - render() - expect( - screen.queryByRole('button', { name: /increment/i, hidden: true }), - ).toBeNull() - expect( - screen.queryByRole('button', { name: /decrement/i, hidden: true }), - ).toBeNull() - }) - it('renders error when field is not filled before submitting', async () => { // Arrange const user = userEvent.setup() diff --git a/apps/frontend/src/templates/Field/Number/NumberField.tsx b/apps/frontend/src/templates/Field/Number/NumberField.tsx index 468952714e..eaa776a0c4 100644 --- a/apps/frontend/src/templates/Field/Number/NumberField.tsx +++ b/apps/frontend/src/templates/Field/Number/NumberField.tsx @@ -34,7 +34,6 @@ export const NumberField = ({ defaultValue="" render={({ field: { value, onChange, ...rest } }) => ( ", "main": "dist/index.js", diff --git a/services/virus-scanner-guardduty/package.json b/services/virus-scanner-guardduty/package.json index 36d0816be5..df8f3c40ac 100644 --- a/services/virus-scanner-guardduty/package.json +++ b/services/virus-scanner-guardduty/package.json @@ -1,6 +1,6 @@ { "name": "formsg-virus-scanner-guardduty", - "version": "7.26.0", + "version": "7.26.1", "private": true, "description": "", "scripts": {