Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(email-mode): hide email mode #8013

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
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
5 changes: 4 additions & 1 deletion .template-env
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,7 @@ FORMSG_SDK_MODE=
# AZURE_OPENAI_API_KEY=
# AZURE_OPENAI_ENDPOINT=
# AZURE_OPENAI_DEPLOYMENT_NAME=
# AZURE_OPENAI_API_VERSION=
# AZURE_OPENAI_API_VERSION=

## Kill email mode configs, provide a valid storage form id
# KILL_EMAIL_MODE_FEEDBACK_FORMID=
3 changes: 2 additions & 1 deletion __tests__/setup/.test-env
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ POSTMAN_MOP_CAMPAIGN_ID=campaign_tesst
POSTMAN_MOP_CAMPAIGN_API_KEY=key_test_123
POSTMAN_INTERNAL_CAMPAIGN_ID=campaign_tesst
POSTMAN_INTERNAL_CAMPAIGN_API_KEY=key_test_123
POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2
POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2
KILL_EMAIL_MODE_FEEDBACK_FORMID=123123132
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ services:
- POSTMAN_BASE_URL=https://test.postman.gov.sg/api/v2
- DOWNLOAD_FORM_WHITELIST_RATE_LIMIT
- UPLOAD_FORM_WHITELIST_RATE_LIMIT
- KILL_EMAIL_MODE_FEEDBACK_FORMID=67642a79b207c811692cad51

mockpass:
build: https://github.com/opengovsg/mockpass.git#v4.3.1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect } from 'react'

import { FormResponseMode } from '~shared/types'
import { FormResponseMode, PublicFormViewDto } from '~shared/types'

import { useFormTemplate } from '~features/admin-form/common/queries'
import {
Expand All @@ -9,6 +9,7 @@ import {
CreateFormWizardContextReturn,
} from '~features/workspace/components/CreateFormModal/CreateFormWizardContext'
import { useCommonFormWizardProvider } from '~features/workspace/components/CreateFormModal/CreateFormWizardProvider'
import { useEmailModeFeedbackMutation } from '~features/workspace/mutations'

import { useUseTemplateMutations } from '../mutation'

Expand Down Expand Up @@ -41,14 +42,16 @@ export const useUseTemplateWizardContext = (
})
}, [reset, getValues, isTemplateFormLoading, templateFormData?.form.title])

const { handleSubmit } = formMethods
const { handleSubmit, setValue } = formMethods

const {
useEmailModeFormTemplateMutation,
useStorageModeFormTemplateMutation,
useMultirespondentFormTemplateMutation,
} = useUseTemplateMutations()

const { emailModeFeedbackMutation } = useEmailModeFeedbackMutation()

const handleCreateStorageModeOrMultirespondentForm = handleSubmit(
({ title, responseMode }) => {
if (!formId) return
Expand Down Expand Up @@ -81,6 +84,33 @@ export const useUseTemplateWizardContext = (
},
)

// TODO: (Kill Email Mode) Remove this route after kill email mode is fully implemented.
// Collect email mode usage feedback before creating the form
const handleEmailFeedbackSubmit = () => {
// explicit set response to email as email feedback "button" interaction
// is not handled handled in FormResponseOptions
setValue('responseMode', FormResponseMode.Email)
setCurrentStep([CreateFormFlowStates.EmailFeedback, 1])
}

// TODO: (Kill Email Mode) Remove this route after kill email mode is fully implemented.
const handleCreateEmailModeForm = (feedbackForm: PublicFormViewDto) =>
handleSubmit((inputs) => {
if (!inputs.reason) {
return new Error('Reason is required')
}
emailModeFeedbackMutation.mutate({
body: { reason: inputs.reason },
feedbackForm,
})
return useEmailModeFormTemplateMutation.mutate({
formIdToDuplicate: formId,
emails: inputs.emails.filter(Boolean),
title: inputs.title,
responseMode: FormResponseMode.Email,
})
})

const handleDetailsSubmit = handleSubmit((inputs) => {
if (!formId) return
if (inputs.responseMode === FormResponseMode.Email) {
Expand All @@ -106,6 +136,8 @@ export const useUseTemplateWizardContext = (
formMethods,
handleDetailsSubmit,
handleCreateStorageModeOrMultirespondentForm,
handleEmailFeedbackSubmit,
handleCreateEmailModeForm,
isSingpass,
modalHeader: 'Duplicate form',
}
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/features/public-form/PublicFormService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ export const getPublicFormView = async (
.then(transformAllIsoStringsToDate)
}

/**
* TODO: (Kill Email Mode) Remove this route after kill email mode is fully implemented.
* Gets the BE defined feedback form for admins to answer why they are using email mode
* @returns Public view of form for admin email feedback form
*/
export const getAdminUseEmailModeFeedbackFormView =
async (): Promise<PublicFormViewDto> => {
return ApiService.get<PublicFormViewDto>(
`${PUBLIC_FORMS_ENDPOINT}/admin-use-email-feedback`,
)
.then(({ data }) => data)
.then(transformAllIsoStringsToDate)
}

/**
* Gets the redirect url for public form login
* @param formId form id of form to log in.
Expand Down
17 changes: 17 additions & 0 deletions frontend/src/features/public-form/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ApiError } from '~typings/core'
import { MONGODB_ID_REGEX } from '~constants/routes'

import {
getAdminUseEmailModeFeedbackFormView,
getMultirespondentSubmissionById,
getPublicFormView,
} from './PublicFormService'
Expand Down Expand Up @@ -62,3 +63,19 @@ export const useEncryptedSubmission = (
},
)
}

/**
* TODO: (Kill Email Mode) Remove this after kill email mode is fully implemented.
* Queries the BE defined feedback form for admins to answer why they are using email mode
* @returns
*/
export const useAdminUseEmailModeFormView = (): UseQueryResult<
PublicFormViewDto,
ApiError
> => {
return useQuery<PublicFormViewDto, ApiError>(
publicFormKeys.id('useAdminUseEmailModeFormView'),
() => getAdminUseEmailModeFeedbackFormView(),
{},
)
}
78 changes: 77 additions & 1 deletion frontend/src/features/workspace/WorkspaceService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { AdminFeedbackDto, AdminFeedbackRating } from '~shared/types'
import {
AdminFeedbackDto,
AdminFeedbackRating,
AdminUseEmailModeFeedbackDto,
BasicField,
ErrorDto,
} from '~shared/types'
import {
AdminDashboardFormMetaDto,
CreateEmailFormBodyDto,
Expand All @@ -7,10 +13,15 @@ import {
DuplicateFormBodyDto,
FormDto,
FormId,
PublicFormViewDto,
} from '~shared/types/form/form'
import { WorkspaceDto } from '~shared/types/workspace'
import { removeAt } from '~shared/utils/immutable-array-fns'

import { ApiService } from '~services/ApiService'
import { CHECKBOX_OTHERS_INPUT_VALUE } from '~templates/Field/Checkbox/constants'

import { PUBLIC_FORMS_ENDPOINT } from '~features/public-form/PublicFormService'

export const ADMIN_FORM_ENDPOINT = '/admin/forms'
const ADMIN_WORKSPACES_ENDPOINT = '/admin/workspaces'
Expand Down Expand Up @@ -112,6 +123,71 @@ export const createMultirespondentModeForm = async (
)
}

const createFeedbackResponses = (
formInputs: AdminUseEmailModeFeedbackDto,
feedbackForm: PublicFormViewDto,
) => {
// const feedbackFormFieldsStructure: [string, number][] = [['reason', 0]]

const { fieldType, title, _id } = feedbackForm.form.form_fields[0]

const reasonCheckboxAnswerArray = formInputs['reason']
let answerArray: string[] = []
if (
reasonCheckboxAnswerArray !== undefined &&
reasonCheckboxAnswerArray.value
) {
const othersIndex = reasonCheckboxAnswerArray.value.findIndex(
(v) => v === CHECKBOX_OTHERS_INPUT_VALUE,
)
// Others is checked, so we need to add the input at othersInput to the answer array
if (othersIndex !== -1) {
answerArray = removeAt(reasonCheckboxAnswerArray.value, othersIndex)
answerArray.push(`Others: ${reasonCheckboxAnswerArray.othersInput}`)
} else {
answerArray = reasonCheckboxAnswerArray.value
}
}

const responses = [
{
_id,
question: title,
answerArray,
fieldType,
},
]
return responses
}

const createAdminEmailModeUseFeedback = (
formInputs: AdminUseEmailModeFeedbackDto,
feedbackForm: PublicFormViewDto,
) => {
const responses = createFeedbackResponses(formInputs, feedbackForm)
// convert content to FormData object
const formData = new FormData()
formData.append('body', JSON.stringify({ responses, version: 2.1 }))

return formData
}

// TODO: (Kill Email Mode) Remove this route after kill email mode is fully implemented.
export const submitUseEmailFormFeedback = async ({
body,
feedbackForm,
}: {
body: AdminUseEmailModeFeedbackDto
feedbackForm: PublicFormViewDto
}): Promise<boolean | ErrorDto> => {
if (!feedbackForm) return new Error('feedback form not provided')
const formData = createAdminEmailModeUseFeedback(body, feedbackForm)
return ApiService.post<boolean>(
`${PUBLIC_FORMS_ENDPOINT}/submissions/storage/email-mode-feedback?captchaResponse=null`,
formData,
).then(({ data }) => data)
}

export const dupeEmailModeForm = async (
formId: string,
body: DuplicateFormBodyDto,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const CreateFormDetailsScreen = (): JSX.Element => {
const {
formMethods,
handleDetailsSubmit,
handleEmailFeedbackSubmit,
isLoading,
isFetching,
modalHeader,
Expand All @@ -65,6 +66,9 @@ export const CreateFormDetailsScreen = (): JSX.Element => {

const titleInputValue = watch('title')
const responseModeValue = watch('responseMode')
const handleEmailButtonPress = () => {
handleEmailFeedbackSubmit()
}

return (
<>
Expand Down Expand Up @@ -98,7 +102,11 @@ export const CreateFormDetailsScreen = (): JSX.Element => {
control={control}
render={({ field }) => (
<WorkspaceRowsProvider>
<FormResponseOptions {...field} isSingpass={isSingpass} />
<FormResponseOptions
{...field}
isSingpass={isSingpass}
handleEmailButtonPress={handleEmailButtonPress}
/>
</WorkspaceRowsProvider>
)}
rules={{ required: 'Please select a form response mode' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '../CreateFormWizardContext'

import { CreateFormDetailsScreen } from './CreateFormDetailsScreen'
import { EmailModeFeedbackAndCreateScreen } from './EmailModeFeedbackAndCreateScreen'
import { SaveSecretKeyScreen } from './SaveSecretKeyScreen'

/**
Expand All @@ -21,6 +22,10 @@ export const CreateFormModalContent = () => {
<CreateFormDetailsScreen />
)}
{currentStep === CreateFormFlowStates.Landing && <SaveSecretKeyScreen />}
{/* TODO: (Kill Email Mode) Remove this route after kill email mode is fully implemented. */}
{currentStep === CreateFormFlowStates.EmailFeedback && (
<EmailModeFeedbackAndCreateScreen />
)}
</XMotionBox>
)
}
Loading
Loading