From ec1ce2667885db548a4082f1593112e5e993ad64 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:14:59 +0800 Subject: [PATCH] Feat/fixSLStyling (#1440) * fix(sl constants): ensure route is intercepted * feat(sl): add mocks for sl * feat(sl): checklist copy changes + copied tooltip * feat(sl): change API so that step no. can increase * feat(sl): add storybooks * fix(cl): fix visual bug for no of tasks * fix(sl checklist): fix colors --- src/contexts/SiteLaunchContext.tsx | 36 ++++- .../SiteLaunchPad/SiteLaunchPad.stories.tsx | 140 +++++++++++++++++- src/layouts/SiteLaunchPad/SiteLaunchPad.tsx | 54 +------ .../components/SiteLaunchCheckList.tsx | 90 +++++++---- src/mocks/constants.ts | 34 ++++- src/mocks/utils.ts | 8 +- 6 files changed, 273 insertions(+), 89 deletions(-) diff --git a/src/contexts/SiteLaunchContext.tsx b/src/contexts/SiteLaunchContext.tsx index 40aa37293..374d1295c 100644 --- a/src/contexts/SiteLaunchContext.tsx +++ b/src/contexts/SiteLaunchContext.tsx @@ -9,6 +9,7 @@ import { useGetSiteLaunchStatus } from "hooks/siteDashboardHooks" import { launchSite } from "services/SiteLaunchService" import { + NEW_DOMAIN_SITE_LAUNCH_TASKS_LENGTH, SiteLaunchBEStatus, SiteLaunchFEStatus, SiteLaunchFEStatusType, @@ -17,6 +18,7 @@ import { SiteLaunchTaskTypeIndex, SITE_LAUNCH_PAGES, SITE_LAUNCH_TASKS, + SITE_LAUNCH_TASKS_LENGTH, } from "types/siteLaunch" interface SiteLaunchContextProps { @@ -29,6 +31,8 @@ interface SiteLaunchContextProps { increasePageNumber: () => void decreasePageNumber: () => void pageNumber: SiteLaunchPageIndex + handleIncrementStepNumber: () => void + handleDecrementStepNumber: () => void } interface SiteLaunchProviderProps { @@ -79,7 +83,6 @@ export const SiteLaunchProvider = ({ }) const { data: siteLaunchDto } = useGetSiteLaunchStatus(siteName) - const queryClient = useQueryClient() const refetchSiteLaunchStatus = () => { /** @@ -109,6 +112,29 @@ export const SiteLaunchProvider = ({ setPageNumber((pageNumber - 1) as SiteLaunchPageIndex) } + const handleIncrementStepNumber = () => { + if ( + siteLaunchStatusProps && + siteLaunchStatusProps.stepNumber < SITE_LAUNCH_TASKS_LENGTH + ) { + setSiteLaunchStatusProps({ + ...siteLaunchStatusProps, + stepNumber: (siteLaunchStatusProps.stepNumber + + 1) as SiteLaunchTaskTypeIndex, // safe to assert since we do a check + siteLaunchStatus: SiteLaunchFEStatus.ChecklistTasksPending, + }) + } + } + const handleDecrementStepNumber = () => { + if (siteLaunchStatusProps && siteLaunchStatusProps.stepNumber > 0) { + setSiteLaunchStatusProps({ + ...siteLaunchStatusProps, + stepNumber: (siteLaunchStatusProps?.stepNumber - + 1) as SiteLaunchTaskTypeIndex, // safe to assert since we do a check + }) + } + } + const generateDNSRecords = async () => { if ( siteLaunchStatusProps.siteUrl && @@ -165,6 +191,12 @@ export const SiteLaunchProvider = ({ !isSiteLaunchFEAndBESynced ) { setPageNumber(SITE_LAUNCH_PAGES.CHECKLIST) + setSiteLaunchStatusProps((prevStatusProps) => ({ + ...prevStatusProps, + stepNumber: prevStatusProps.isNewDomain + ? NEW_DOMAIN_SITE_LAUNCH_TASKS_LENGTH + : SITE_LAUNCH_TASKS_LENGTH, + })) } if ( @@ -185,6 +217,8 @@ export const SiteLaunchProvider = ({ return ( = (args) => ( // NOTE: This is just a mock, so no need actual functions const siteLaunchPadArgs = { pageNumber: 1, - // eslint-disable-next-line @typescript-eslint/no-empty-function - setPageNumber: () => {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function - handleDecrementStepNumber: () => {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function - handleIncrementStepNumber: () => {}, } export const Default = Template.bind({}) @@ -87,6 +83,20 @@ siteLaunchChecklistOldDomain.args = { pageNumber: 4, } +siteLaunchChecklistOldDomain.decorators = [ + (Story) => { + return ( + + + + ) + }, +] + export const siteLaunchChecklistNewDomain = Template.bind({}) siteLaunchChecklistNewDomain.args = { @@ -98,7 +108,7 @@ siteLaunchChecklistNewDomain.decorators = [ (Story) => { return ( @@ -108,6 +118,122 @@ siteLaunchChecklistNewDomain.decorators = [ }, ] +export const NewDomainNonWwwDnsRecords = Template.bind({}) + +NewDomainNonWwwDnsRecords.args = { + ...siteLaunchPadArgs, + pageNumber: 4, +} +NewDomainNonWwwDnsRecords.parameters = { + msw: { + handlers: { + siteLaunchStatusProps: buildSiteLaunchDto( + MOCK_NON_WWW_LAUNCHING_SITE_LAUNCH_DTO + ), + }, + }, +} + +NewDomainNonWwwDnsRecords.decorators = [ + (Story) => { + return ( + + + + ) + }, +] + +export const NewDomainWwwDnsRecords = Template.bind({}) + +NewDomainWwwDnsRecords.args = { + ...siteLaunchPadArgs, + pageNumber: 4, +} +NewDomainWwwDnsRecords.parameters = { + msw: { + handlers: { + siteLaunchStatusProps: buildSiteLaunchDto( + MOCK_WWW_LAUNCHING_SITE_LAUNCH_DTO + ), + }, + }, +} + +NewDomainWwwDnsRecords.decorators = [ + (Story) => { + return ( + + + + ) + }, +] + +export const OldDomainWwwDnsRecords = Template.bind({}) + +OldDomainWwwDnsRecords.args = { + ...siteLaunchPadArgs, + pageNumber: 4, +} +OldDomainWwwDnsRecords.parameters = { + msw: { + handlers: { + siteLaunchStatusProps: buildSiteLaunchDto( + MOCK_WWW_LAUNCHING_SITE_LAUNCH_DTO + ), + }, + }, +} + +OldDomainWwwDnsRecords.decorators = [ + (Story) => { + return ( + + + + ) + }, +] + +export const OldDomainNonWwwDnsRecords = Template.bind({}) + +OldDomainNonWwwDnsRecords.args = { + ...siteLaunchPadArgs, + pageNumber: 4, +} +OldDomainNonWwwDnsRecords.parameters = { + msw: { + handlers: { + siteLaunchStatusProps: buildSiteLaunchDto( + MOCK_NON_WWW_LAUNCHING_SITE_LAUNCH_DTO + ), + }, + }, +} + +OldDomainNonWwwDnsRecords.decorators = [ + (Story) => { + return ( + + + + ) + }, +] + export const siteLaunchPendingState = Template.bind({}) siteLaunchPendingState.args = { diff --git a/src/layouts/SiteLaunchPad/SiteLaunchPad.tsx b/src/layouts/SiteLaunchPad/SiteLaunchPad.tsx index 1949fe417..dbc537f48 100644 --- a/src/layouts/SiteLaunchPad/SiteLaunchPad.tsx +++ b/src/layouts/SiteLaunchPad/SiteLaunchPad.tsx @@ -28,12 +28,7 @@ import { SiteViewHeader } from "layouts/layouts/SiteViewLayout/SiteViewHeader" import { isSiteLaunchEnabled } from "utils/siteLaunchUtils" -import { - SiteLaunchFEStatus, - SiteLaunchTaskTypeIndex, - SITE_LAUNCH_PAGES, - SITE_LAUNCH_TASKS_LENGTH, -} from "types/siteLaunch" +import { SITE_LAUNCH_PAGES } from "types/siteLaunch" import { useErrorToast } from "utils" import { @@ -56,9 +51,6 @@ interface RiskAcceptanceModalProps { interface SiteLaunchPadProps { pageNumber: number - - handleDecrementStepNumber: () => void - handleIncrementStepNumber: () => void } const RiskAcceptanceModal = ({ @@ -130,8 +122,6 @@ const RiskAcceptanceModal = ({ export const SiteLaunchPad = ({ pageNumber, - handleDecrementStepNumber, - handleIncrementStepNumber, }: SiteLaunchPadProps): JSX.Element => { let title: JSX.Element let body: JSX.Element @@ -147,12 +137,7 @@ export const SiteLaunchPad = ({ break case SITE_LAUNCH_PAGES.CHECKLIST: title = - body = ( - - ) + body = break case SITE_LAUNCH_PAGES.FINAL_STATE: title = <> // No title for final state @@ -177,11 +162,7 @@ export const SiteLaunchPad = ({ } export const SiteLaunchPadPage = (): JSX.Element => { - const { - siteLaunchStatusProps, - setSiteLaunchStatusProps, - pageNumber, - } = useSiteLaunchContext() + const { pageNumber } = useSiteLaunchContext() const { siteName } = useParams<{ siteName: string }>() const errorToast = useErrorToast() @@ -197,38 +178,11 @@ export const SiteLaunchPadPage = (): JSX.Element => { } }, [siteName, errorToast, role, isLoaded]) - const handleIncrementStepNumber = () => { - if ( - siteLaunchStatusProps && - siteLaunchStatusProps.stepNumber < SITE_LAUNCH_TASKS_LENGTH - ) { - setSiteLaunchStatusProps({ - ...siteLaunchStatusProps, - stepNumber: (siteLaunchStatusProps.stepNumber + - 1) as SiteLaunchTaskTypeIndex, // safe to assert since we do a check - siteLaunchStatus: SiteLaunchFEStatus.ChecklistTasksPending, - }) - } - } - const handleDecrementStepNumber = () => { - if (siteLaunchStatusProps && siteLaunchStatusProps.stepNumber > 0) { - setSiteLaunchStatusProps({ - ...siteLaunchStatusProps, - stepNumber: (siteLaunchStatusProps?.stepNumber - - 1) as SiteLaunchTaskTypeIndex, // safe to assert since we do a check - }) - } - } - return ( <> {isSiteLaunchEnabled(siteName, role) ? ( - + ) : ( /** * Without the isLoaded check, the site will redirect prematurely. diff --git a/src/layouts/SiteLaunchPad/components/SiteLaunchCheckList.tsx b/src/layouts/SiteLaunchPad/components/SiteLaunchCheckList.tsx index aae98454d..63225aa79 100644 --- a/src/layouts/SiteLaunchPad/components/SiteLaunchCheckList.tsx +++ b/src/layouts/SiteLaunchPad/components/SiteLaunchCheckList.tsx @@ -12,6 +12,12 @@ import { TextProps, Skeleton, HStack, + Popover, + PopoverTrigger, + PopoverArrow, + PopoverContent, + PopoverBody, + useClipboard, } from "@chakra-ui/react" import { Button, Checkbox, Link } from "@opengovsg/design-system-react" import { useForm } from "react-hook-form" @@ -19,7 +25,7 @@ import { useParams, Link as RouterLink } from "react-router-dom" import { useSiteLaunchContext } from "contexts/SiteLaunchContext" -import { BxCopy, BxLifeBuoy } from "assets" +import { BxCopy } from "assets" import { DNSRecord, getNewDomainTaskFrmIdx, @@ -64,25 +70,55 @@ const getTextProps = (index: number, tasksDone: number): TextProps => { } const textWithCopyIcon = (text: string): JSX.Element => { + const { onCopy, hasCopied } = useClipboard(text) return ( - ) } -const generateDNSTable = (dnsRecords: DNSRecord[] | undefined): JSX.Element => { +const DnsTable = ({ + dnsRecords, +}: { + dnsRecords?: DNSRecord[] +}): JSX.Element => { return ( @@ -106,7 +142,7 @@ const generateDNSTable = (dnsRecords: DNSRecord[] | undefined): JSX.Element => { {textWithCopyIcon(record.source)} diff --git a/src/mocks/constants.ts b/src/mocks/constants.ts index f194dd1a9..ccd2200c2 100644 --- a/src/mocks/constants.ts +++ b/src/mocks/constants.ts @@ -565,9 +565,39 @@ export const MOCK_LAUNCHING_SITE_LAUNCH_DTO: SiteLaunchDto = { siteLaunchStatus: SiteLaunchBEStatus.Launching, dnsRecords: [ { - source: "sourceURL", + source: "www.isomer.gov.sg", type: "CNAME", - target: "targetURL", + target: "d2fdsaf8ft15h.cloudfront.net", + }, + { + source: "_123456787202a1b56dd8a5545efee05.isomer.gov.sg", + type: "CNAME", + target: + "_fae940f7aa0gfd51754f18ed50bgf521.wrfxpmntfs.acm-validations.aws", + }, + { + source: "isomer.gov.sg", + type: "A Record", + target: "18.136.36.203", + }, + ], +} + +export const MOCK_WWW_LAUNCHING_SITE_LAUNCH_DTO: SiteLaunchDto = MOCK_LAUNCHING_SITE_LAUNCH_DTO + +export const MOCK_NON_WWW_LAUNCHING_SITE_LAUNCH_DTO: SiteLaunchDto = { + siteLaunchStatus: SiteLaunchBEStatus.Launching, + dnsRecords: [ + { + source: "isomer.gov.sg", + type: "CNAME", + target: "d2fdsaf8ft15h.cloudfront.net", + }, + { + source: "_123456787202a1b56dd8a5545efee05.isomer.gov.sg", + type: "CNAME", + target: + "_fae940f7aa0gfd51754f18ed50bgf521.wrfxpmntfs.acm-validations.aws", }, ], } diff --git a/src/mocks/utils.ts b/src/mocks/utils.ts index b61603bee..9f359f099 100644 --- a/src/mocks/utils.ts +++ b/src/mocks/utils.ts @@ -208,7 +208,13 @@ export const buildDiffData = apiDataBuilder( ) export const buildSiteLaunchDto = apiDataBuilder( - "*/sites/:siteName/launchInfo" + "*/sites/:siteName/launchInfo", + "get" +) + +export const buildLaunchSite = apiDataBuilder( + "*/sites/:siteName/launch", + "post" ) export const buildSgidUserData = apiDataBuilder(
- {record.type} + {record.type} {textWithCopyIcon(record.target)} @@ -119,11 +155,6 @@ const generateDNSTable = (dnsRecords: DNSRecord[] | undefined): JSX.Element => { ) } -interface SiteLaunchChecklistBodyProps { - handleIncrementStepNumber: () => void - handleDecrementStepNumber: () => void -} - interface TableMappingProps { stepNumber: number title: JSX.Element @@ -179,11 +210,10 @@ const addSubtitlesForChecklist = ( return newTask } -export const SiteLaunchChecklistBody = ({ - handleIncrementStepNumber, - handleDecrementStepNumber, -}: SiteLaunchChecklistBodyProps): JSX.Element => { +export const SiteLaunchChecklistBody = (): JSX.Element => { const { + handleIncrementStepNumber, + handleDecrementStepNumber, siteLaunchStatusProps, setSiteLaunchStatusProps, generateDNSRecords, @@ -215,7 +245,9 @@ export const SiteLaunchChecklistBody = ({ const handleGenerateDNSRecordsOnClick = () => { setSiteLaunchStatusProps({ ...siteLaunchStatusProps, - stepNumber: SITE_LAUNCH_TASKS.GENERATE_NEW_DNS_RECORDS, + stepNumber: siteLaunchStatusProps?.isNewDomain + ? NEW_DOMAIN_SITE_LAUNCH_TASKS_LENGTH + : SITE_LAUNCH_TASKS_LENGTH, siteLaunchStatus: SiteLaunchFEStatus.Launching, }) @@ -292,8 +324,8 @@ export const SiteLaunchChecklistBody = ({ status. - You may leave this page and return later to continue from where you left - off. If you run into issues,{" "} + Do not close this tab until you complete all the tasks. If you run into + issues,{" "} contact Isomer support. )} - {generateDNSTable(siteLaunchStatusProps?.dnsRecords)} +