Skip to content

Commit

Permalink
Merge pull request #6298 from opengovsg/release_v6.49.0
Browse files Browse the repository at this point in the history
build: release v6.49.0
  • Loading branch information
wanlingt authored May 11, 2023
2 parents dc0b538 + e0b174b commit 9e2c872
Show file tree
Hide file tree
Showing 37 changed files with 502 additions and 40 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@ 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.49.0](https://github.com/opengovsg/FormSG/compare/v6.48.0...v6.49.0)

- feat: control feature flags through DB [`#6286`](https://github.com/opengovsg/FormSG/pull/6286)
- build: merge release v6.48.0 to develop [`#6295`](https://github.com/opengovsg/FormSG/pull/6295)
- feat: control payment methods through stripe dashboard [`#6272`](https://github.com/opengovsg/FormSG/pull/6272)
- feat: add business field mutation to form-level [`#6236`](https://github.com/opengovsg/FormSG/pull/6236)
- build: release v6.48.0 [`#6291`](https://github.com/opengovsg/FormSG/pull/6291)

#### [v6.48.0](https://github.com/opengovsg/FormSG/compare/v6.47.0...v6.48.0)

> 9 May 2023

- feat: update sms copy to remove link (policy) [`#6289`](https://github.com/opengovsg/FormSG/pull/6289)
- chore(deps-dev): bump @typescript-eslint/parser from 5.59.2 to 5.59.5 in /shared [`#6287`](https://github.com/opengovsg/FormSG/pull/6287)
- build: merge release v6.47.0 to develop [`#6281`](https://github.com/opengovsg/FormSG/pull/6281)
- fix: add missing env var in docker_compose.yml [`#6284`](https://github.com/opengovsg/FormSG/pull/6284)
- build: release v6.47.0 [`#6279`](https://github.com/opengovsg/FormSG/pull/6279)
- chore: bump version to v6.47.0 [`002b8b6`](https://github.com/opengovsg/FormSG/commit/002b8b6b66c6cc199921311a2ea1800644bcc332)
- chore: bump version to v6.48.0 [`074746f`](https://github.com/opengovsg/FormSG/commit/074746f55303ab1ac2fb7e398b04bf91451fa9a0)

#### [v6.47.0](https://github.com/opengovsg/FormSG/compare/v6.46.0...v6.47.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.48.0",
"version": "6.49.0",
"homepage": ".",
"private": true,
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import {
Text,
} from '@chakra-ui/react'

import { featureFlags } from '~shared/constants'

import { Tab } from '~components/Tabs'

import { useCreatePageSidebar } from '~features/admin-form/create/common/CreatePageSidebarContext'
import { useFeatureFlags } from '~features/feature-flags/queries'
import { useUser } from '~features/user/queries'

import { useCreateTabForm } from '../../../builder-and-design/useCreateTabForm'
Expand All @@ -28,7 +31,11 @@ export const FieldListDrawer = (): JSX.Element => {
const { isLoading } = useCreateTabForm()

const { user } = useUser()
const displayPayments = user?.betaFlags?.payment
const { data: flags } = useFeatureFlags()

const displayPayments =
user?.betaFlags?.payment || flags?.has(featureFlags.payment)

return (
<Tabs
pos="relative"
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/features/admin-form/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import {
Tabs,
} from '@chakra-ui/react'

import { featureFlags } from '~shared/constants'

import { ADMINFORM_RESULTS_SUBROUTE, ADMINFORM_ROUTE } from '~constants/routes'
import { useDraggable } from '~hooks/useDraggable'

import { useFeatureFlags } from '~features/feature-flags/queries'
import { useUser } from '~features/user/queries'

import { useAdminFormCollaborators } from '../common/queries'
Expand All @@ -28,6 +31,7 @@ import { SettingsWebhooksPage } from './SettingsWebhooksPage'
export const SettingsPage = (): JSX.Element => {
const { formId } = useParams()
const { user } = useUser()
const { data: flags } = useFeatureFlags()

if (!formId) throw new Error('No formId provided')

Expand All @@ -43,6 +47,9 @@ export const SettingsPage = (): JSX.Element => {

const { ref, onMouseDown } = useDraggable<HTMLDivElement>()

const displayPayments =
user?.betaFlags?.payment || flags?.has(featureFlags.payment)

return (
<Box overflow="auto" flex={1}>
<Tabs
Expand Down Expand Up @@ -84,7 +91,7 @@ export const SettingsPage = (): JSX.Element => {
<SettingsTab label="Singpass" icon={BiKey} />
<SettingsTab label="Twilio credentials" icon={BiMessage} />
<SettingsTab label="Webhooks" icon={BiCodeBlock} />
{user?.betaFlags?.payment && (
{displayPayments && (
<SettingsTab label="Payments" icon={BiDollar} />
)}
</TabList>
Expand All @@ -106,7 +113,7 @@ export const SettingsPage = (): JSX.Element => {
<TabPanel>
<SettingsWebhooksPage />
</TabPanel>
{user?.betaFlags?.payment && (
{displayPayments && (
<TabPanel>
<SettingsPaymentsPage />
</TabPanel>
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/features/admin-form/settings/SettingsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
EmailFormSettings,
FormSettings,
SettingsUpdateDto,
StorageFormSettings,
} from '~shared/types/form/form'

import { ApiService } from '~services/ApiService'
Expand All @@ -16,6 +17,11 @@ type UpdateEmailFormFn<T extends keyof EmailFormSettings> = (
settingsToUpdate: EmailFormSettings[T],
) => Promise<FormSettings>

type UpdateStorageFormFn<T extends keyof StorageFormSettings> = (
formId: string,
settingsToUpdate: StorageFormSettings[T],
) => Promise<FormSettings>

type UpdateFormFn<T extends keyof FormSettings> = (
formId: string,
settingsToUpdate: FormSettings[T],
Expand Down Expand Up @@ -106,6 +112,13 @@ export const updateFormWebhookRetries = async (
})
}

export const updateBusinessInfo: UpdateStorageFormFn<'business'> = async (
formId,
newBusinessField: StorageFormSettings['business'],
) => {
return updateFormSettings(formId, { business: newBusinessField })
}

/**
* Internal function that calls the PATCH API.
* @param formId the id of the form to update
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import {
ChangeEventHandler,
KeyboardEventHandler,
useCallback,
useRef,
useState,
} from 'react'
import { FormControl } from '@chakra-ui/react'

import {
AgencyBase,
FormResponseMode,
StorageFormSettings,
} from '~shared/types'

import FormLabel from '~components/FormControl/FormLabel'
import Input from '~components/Input'

import { useAdminForm } from '~features/admin-form/common/queries'

import { useMutateFormSettings } from '../../mutations'
import { useAdminFormSettings } from '../../queries'

interface BusinessFieldInputProps {
initialValue: string
handleMutation: (newAddress: string) => void
placeholder: string
}
const BusinessFieldInput = ({
initialValue,
handleMutation,
placeholder,
}: BusinessFieldInputProps): JSX.Element => {
const [value, setValue] = useState(initialValue)

const inputRef = useRef<HTMLInputElement>(null)

const handleValueChange: ChangeEventHandler<HTMLInputElement> = useCallback(
(e) => {
setValue(e.target.value)
},
[],
)

const handleBlur = useCallback(() => {
if (value === initialValue) return
const trimmedValue = value.trim()
handleMutation(trimmedValue)
setValue(trimmedValue)
}, [handleMutation, value, initialValue])

const handleKeydown: KeyboardEventHandler<HTMLInputElement> = useCallback(
(e) => {
if (e.key === 'Enter') {
e.preventDefault()
inputRef.current?.blur()
}
},
[],
)

return (
<Input
ref={inputRef}
value={value}
onChange={handleValueChange}
onKeyDown={handleKeydown}
onBlur={handleBlur}
placeholder={placeholder}
_placeholder={{ opacity: 1 }}
/>
)
}

const BusinessInfoBlock = ({
settings,
agencyDefaults,
}: {
settings: StorageFormSettings
agencyDefaults: AgencyBase['business']
}) => {
const { mutateFormBusiness } = useMutateFormSettings()
const handleAddressMutation = (newAddress: string) => {
mutateFormBusiness.mutate({ address: newAddress })
}
const handleGstRegNoMutation = (newGstRegNo: string) => {
mutateFormBusiness.mutate({ gstRegNo: newGstRegNo })
}
return (
<>
<FormControl mb="2.5rem" isReadOnly={mutateFormBusiness.isLoading}>
<FormLabel
description="Leave empty to use your agency defaults."
isRequired
>
GST Registration Number
</FormLabel>
<BusinessFieldInput
placeholder={agencyDefaults?.gstRegNo || ''}
initialValue={settings.business?.gstRegNo || ''}
handleMutation={handleGstRegNoMutation}
/>
</FormControl>
<FormControl mb="2.5rem" isReadOnly={mutateFormBusiness.isLoading}>
<FormLabel
description="Leave empty to use your agency defaults."
isRequired
>
Business Address
</FormLabel>
<BusinessFieldInput
placeholder={agencyDefaults?.address || ''}
initialValue={settings.business?.address || ''}
handleMutation={handleAddressMutation}
/>
</FormControl>
</>
)
}

export const BusinessInfoSection = () => {
const { data: settings, isLoading } = useAdminFormSettings()
const { data: adminSettings } = useAdminForm()

if (
isLoading ||
!settings ||
settings.responseMode !== FormResponseMode.Encrypt ||
!adminSettings
) {
return <></>
}

return (
<BusinessInfoBlock
settings={settings}
agencyDefaults={adminSettings.admin.agency.business}
/>
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Flex, FormControl, Icon, Skeleton, Text } from '@chakra-ui/react'
import {
Divider,
Flex,
FormControl,
Icon,
Skeleton,
Text,
} from '@chakra-ui/react'

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

Expand All @@ -8,6 +15,7 @@ import Input from '~components/Input'

import { useAdminFormPayments, useAdminFormSettings } from '../../queries'

import { BusinessInfoSection } from './BusinessInfoSection'
import { StripeConnectButton } from './StripeConnectButton'

const PaymentsAccountValidation = () => {
Expand Down Expand Up @@ -128,6 +136,8 @@ export const PaymentSettingsSection = (): JSX.Element => {
<>
<PaymentsSectionText />
<StripeConnectButton />
<Divider my="2.5rem" />
<BusinessInfoSection />
</>
)
}
17 changes: 17 additions & 0 deletions frontend/src/features/admin-form/settings/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
FormResponseMode,
FormSettings,
FormStatus,
StorageFormSettings,
} from '~shared/types/form/form'
import { TwilioCredentials } from '~shared/types/twilio'

Expand All @@ -25,6 +26,7 @@ import {
createStripeAccount,
deleteTwilioCredentials,
unlinkStripeAccount,
updateBusinessInfo,
updateFormAuthType,
updateFormCaptcha,
updateFormEmails,
Expand Down Expand Up @@ -287,6 +289,20 @@ export const useMutateFormSettings = () => {
},
)

const mutateFormBusiness = useMutation(
(businessInfo: StorageFormSettings['business']) =>
updateBusinessInfo(formId, businessInfo),
{
onSuccess: (newData) => {
handleSuccess({
newData,
toastDescription: `Business information has been updated.`,
})
},
onError: handleError,
},
)

return {
mutateWebhookRetries,
mutateFormWebhookUrl,
Expand All @@ -298,6 +314,7 @@ export const useMutateFormSettings = () => {
mutateFormTitle,
mutateFormAuthType,
mutateFormEsrvcId,
mutateFormBusiness,
}
}

Expand Down
13 changes: 13 additions & 0 deletions frontend/src/features/feature-flags/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useQuery, UseQueryResult } from 'react-query'

import { getEnabledFeatureFlags } from '~services/FeatureFlagService'

export const featureFlagsKeys = {
base: ['feature-flags'] as const,
}

// TODO: Add local caching system with interval based refresh
// Refer to https://github.com/opengovsg/FormSG/pull/6286#discussion_r1190529370
export const useFeatureFlags = (): UseQueryResult<Set<string>> => {
return useQuery(featureFlagsKeys.base, () => getEnabledFeatureFlags())
}
7 changes: 7 additions & 0 deletions frontend/src/services/FeatureFlagService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ApiService } from './ApiService'

export const getEnabledFeatureFlags = async (): Promise<Set<string>> => {
return ApiService.get<string[]>('/feature-flags/enabled').then(
({ data }) => new Set(data),
)
}
Loading

0 comments on commit 9e2c872

Please sign in to comment.