Skip to content

Commit 65fb92c

Browse files
authored
fix(site-settings/navbar/footer): fix dogfoodign findings (#1718)
* fix: make object control always full widht * fix: update equality comparison * chore: links always open in new tab * chore: cpoy changes * chore: add error message * chore: prevent infinite renders * chore: fix equality check for integations * chore: remove package * chore: update deafult colour * fix: update asPath * chore: fix conditoinal * chore: fix lints * chore: fix lint findings * chore: fix formatting
1 parent e9be39e commit 65fb92c

File tree

15 files changed

+118
-33
lines changed

15 files changed

+118
-33
lines changed

apps/studio/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
"react-hook-form": "^7.52.1",
158158
"react-icons": "^5.2.0",
159159
"react-markdown": "^10.1.0",
160+
"rehype-external-links": "^3.0.0",
160161
"sass": "^1.83.4",
161162
"superjson": "^2.2.1",
162163
"tiptap-text-direction": "^0.3.1",

apps/studio/src/components/MarkdownLabel.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Box, useToken } from "@chakra-ui/react"
22
import Markdown from "react-markdown"
3+
import rehypeExternalLinks from "rehype-external-links"
34

45
export const MarkdownLabel = ({ description }: { description?: string }) => {
56
const [linkColor, linkHoverColor, linkActiveColor] = useToken("colors", [
@@ -25,7 +26,9 @@ export const MarkdownLabel = ({ description }: { description?: string }) => {
2526
},
2627
}}
2728
>
28-
<Markdown>{description}</Markdown>
29+
<Markdown rehypePlugins={[[rehypeExternalLinks, { target: "_blank" }]]}>
30+
{description}
31+
</Markdown>
2932
</Box>
3033
)
3134
}

apps/studio/src/features/editing-experience/components/form-builder/renderers/controls/JsonFormsColourPickerControl.tsx

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import {
1111
} from "@chakra-ui/react"
1212
import { rankWith, schemaMatches } from "@jsonforms/core"
1313
import { useJsonForms, withJsonFormsControlProps } from "@jsonforms/react"
14-
import { FormLabel, Input } from "@opengovsg/design-system-react"
14+
import {
15+
FormErrorMessage,
16+
FormLabel,
17+
Input,
18+
} from "@opengovsg/design-system-react"
1519
import get from "lodash/get"
1620
import { isHexadecimal } from "validator"
1721

@@ -23,6 +27,8 @@ export const jsonFormsColourPickerControlTester: RankedTester = rankWith(
2327
schemaMatches((schema) => schema.format === "color-picker"),
2428
)
2529

30+
export const DEFAULT_CONTENT_INVERSE_COLOUR = "2164da"
31+
2632
const THEME_PATHS = [
2733
"colors.brand.canvas.default",
2834
"colors.brand.canvas.alt",
@@ -65,7 +71,7 @@ const JsonFormsColourPickerControl = ({
6571
</InputLeftAddon>
6672
<Input
6773
value={displayedColour?.replace("#", "")}
68-
placeholder="FFFFFF"
74+
placeholder={DEFAULT_CONTENT_INVERSE_COLOUR}
6975
w="86px"
7076
onChange={(e) => {
7177
const rawString = e.target.value
@@ -86,7 +92,10 @@ const JsonFormsColourPickerControl = ({
8692
const palette = getPalette(parsedHex)
8793

8894
THEME_PATHS.forEach((p) => {
89-
handleChange(p, palette[p] ?? "#FFFFFF")
95+
handleChange(
96+
p,
97+
palette[p] ?? `#${DEFAULT_CONTENT_INVERSE_COLOUR}`,
98+
)
9099
})
91100
}}
92101
/>
@@ -96,22 +105,29 @@ const JsonFormsColourPickerControl = ({
96105
border="1px solid"
97106
borderColor="base.divider.strong"
98107
bgColor={
99-
displayedColour ? `#${normalizeHex(displayedColour)}` : "white"
108+
displayedColour
109+
? `#${normalizeHex(displayedColour)}`
110+
: `#${DEFAULT_CONTENT_INVERSE_COLOUR}`
100111
}
101112
w="2rem"
102113
h="2rem"
103114
></Box>
104115
</HStack>
116+
{!data && (
117+
<FormErrorMessage>
118+
Enter a hex code to generate a colour palette.
119+
</FormErrorMessage>
120+
)}
105121
</FormControl>
106122
<Box alignSelf="flex-start">
107123
<FormLabel
108124
description={
109-
"This palette makes your website accessibility compliant."
125+
"We’ve generated this palette from your brand colour. It makes your website compliant with accessibility standards."
110126
}
111127
mb={0}
112128
isRequired
113129
>
114-
Color palette
130+
Generated colour palette
115131
</FormLabel>
116132
<Flex mt="0.75rem" h="3rem">
117133
{THEME_PATHS.map((p) => {
@@ -129,7 +145,10 @@ const JsonFormsColourPickerControl = ({
129145
borderColor="base.divider.medium"
130146
borderLeftRadius={isFirst ? "6px" : "auto"}
131147
borderRightRadius={isLast ? "6px" : "auto"}
132-
bgColor={get(ctx.core?.data as string | undefined, p)}
148+
bgColor={
149+
(get(ctx.core?.data, p) as string | undefined) ??
150+
`#${DEFAULT_CONTENT_INVERSE_COLOUR}`
151+
}
133152
></Box>
134153
)
135154
})}

apps/studio/src/features/editing-experience/components/form-builder/renderers/controls/JsonFormsObjectControl.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function JsonFormsObjectControl({
6868

6969
if (!required) {
7070
return (
71-
<HStack spacing="0.5rem" alignItems="flex-start">
71+
<HStack spacing="0.5rem" alignItems="flex-start" w="full">
7272
<VStack w="full" gap="0.75rem" pt="0.5rem" alignItems="start">
7373
<HStack alignItems="space-between" w="full" spacing="1rem">
7474
<FormControl

apps/studio/src/pages/sites/[siteId]/settings/footer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react"
33
import { useRouter } from "next/router"
44
import { useToast } from "@opengovsg/design-system-react"
55
import { ResourceType } from "~prisma/generated/generatedEnums"
6+
import isEqual from "lodash/isEqual"
67

78
import { PermissionsBoundary } from "~/components/AuthWrappers"
89
import {
@@ -52,7 +53,7 @@ const FooterSettingsPage: NextPageWithLayout = () => {
5253
FooterSchemaType | undefined
5354
>(content)
5455
const isOpen = !!nextUrl
55-
const isDirty = JSON.stringify(previewFooterState) !== JSON.stringify(content)
56+
const isDirty = !isEqual(previewFooterState, content)
5657

5758
const handleSaveFooter = (data?: FooterSchemaType) => {
5859
if (!data) return

apps/studio/src/pages/sites/[siteId]/settings/integrations.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from "@opengovsg/isomer-components"
1313
import { Value } from "@sinclair/typebox/value"
1414
import { ResourceType } from "~prisma/generated/generatedEnums"
15-
import { isEqual } from "lodash"
15+
import { isEqual, pickBy } from "lodash"
1616
import { BiWrench } from "react-icons/bi"
1717

1818
import type { NextPageWithLayout } from "~/lib/types"
@@ -82,8 +82,11 @@ const IntegrationsSettingsPage: NextPageWithLayout = () => {
8282
useState<ComplexIntegrationsSettings>({ askgov, vica })
8383

8484
const isDirty = !isEqual(
85-
{ siteGtmId, search, askgov, vica },
86-
{ ...simpleIntegrationSettings, ...complexIntegrationSettings },
85+
pickBy({ siteGtmId, search, askgov, vica }, (val) => !!val),
86+
pickBy(
87+
{ ...simpleIntegrationSettings, ...complexIntegrationSettings },
88+
(val) => !!val,
89+
),
8790
)
8891

8992
const updateSiteIntegrationsMutation =
@@ -167,13 +170,19 @@ const IntegrationsSettingsPage: NextPageWithLayout = () => {
167170
data={complexIntegrationSettings}
168171
handleChange={(data) => {
169172
if (data.vica) {
170-
setComplexIntegrationSettings({
171-
...data,
172-
vica: {
173-
...data.vica,
174-
"app-name": agencyName ?? siteName,
175-
},
176-
})
173+
const newVicaState = {
174+
...data.vica,
175+
"app-name": agencyName ?? siteName,
176+
}
177+
178+
if (!isEqual(newVicaState, data.vica)) {
179+
setComplexIntegrationSettings({
180+
...data,
181+
vica: newVicaState,
182+
})
183+
} else {
184+
setComplexIntegrationSettings(data)
185+
}
177186
} else {
178187
setComplexIntegrationSettings(data)
179188
}

apps/studio/src/pages/sites/[siteId]/settings/navbar.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { useEffect, useState } from "react"
33
import { useRouter } from "next/router"
44
import { useToast } from "@opengovsg/design-system-react"
55
import { ResourceType } from "~prisma/generated/generatedEnums"
6+
import isEqual from "lodash/isEqual"
67

8+
import type { NextPageWithLayout } from "~/lib/types"
79
import { PermissionsBoundary } from "~/components/AuthWrappers"
810
import {
911
SettingsEditorGridItem,
@@ -22,7 +24,6 @@ import { NavbarEditor } from "~/features/settings/NavbarEditor"
2224
import { useNavigationEffect } from "~/hooks/useNavigationEffect"
2325
import { useNewSettingsPage } from "~/hooks/useNewSettingsPage"
2426
import { useQueryParse } from "~/hooks/useQueryParse"
25-
import { type NextPageWithLayout } from "~/lib/types"
2627
import { SiteSettingsLayout } from "~/templates/layouts/SiteSettingsLayout"
2728
import { trpc } from "~/utils/trpc"
2829

@@ -60,7 +61,7 @@ const NavbarSettingsPage: NextPageWithLayout = () => {
6061
NavbarSchemaType | undefined
6162
>(content)
6263
const isOpen = !!nextUrl
63-
const isDirty = JSON.stringify(previewNavbarState) !== JSON.stringify(content)
64+
const isDirty = !isEqual(previewNavbarState, content)
6465

6566
const handleSaveNavbar = (data: NavbarSchemaType | undefined) => {
6667
if (!data) return

apps/studio/src/pages/sites/[siteId]/settings/notification.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ const NotificationSettingsPage: NextPageWithLayout = () => {
109109
isLoading={notificationMutation.isPending}
110110
isDisabled={!isDirty}
111111
/>
112-
<Box>
112+
<Box w="100%">
113113
<Box mb="-0.5rem" />
114114
<FormBuilder<Notification>
115115
schema={NotificationSettingsSchema}

apps/studio/src/stories/Page/SettingsPage/Colour.stories.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { userEvent, within } from "storybook/test"
33
import { pageHandlers } from "tests/msw/handlers/page"
44
import { sitesHandlers } from "tests/msw/handlers/sites"
55

6+
import { DEFAULT_CONTENT_INVERSE_COLOUR } from "~/features/editing-experience/components/form-builder/renderers/controls/JsonFormsColourPickerControl"
67
import ColoursSettingsPage from "~/pages/sites/[siteId]/settings/colours"
78
import { ADMIN_HANDLERS } from "~/stories/handlers"
89

@@ -28,7 +29,7 @@ const meta: Meta<typeof ColoursSettingsPage> = {
2829
},
2930
nextjs: {
3031
router: {
31-
asPath: "/sites/1/settings/logo",
32+
asPath: "/sites/1/settings/colours",
3233
query: {
3334
siteId: "1",
3435
},
@@ -61,7 +62,9 @@ export const DarkPalette: Story = {
6162
play: async ({ canvasElement }) => {
6263
const rootScreen = within(canvasElement.ownerDocument.body)
6364

64-
const colourInput = await rootScreen.findByPlaceholderText("FFFFFF")
65+
const colourInput = await rootScreen.findByPlaceholderText(
66+
DEFAULT_CONTENT_INVERSE_COLOUR,
67+
)
6568

6669
await userEvent.clear(colourInput)
6770
await userEvent.type(colourInput, "#000000")
@@ -72,18 +75,22 @@ export const LightPalette: Story = {
7275
play: async ({ canvasElement }) => {
7376
const rootScreen = within(canvasElement.ownerDocument.body)
7477

75-
const colourInput = await rootScreen.findByPlaceholderText("FFFFFF")
78+
const colourInput = await rootScreen.findByPlaceholderText(
79+
DEFAULT_CONTENT_INVERSE_COLOUR,
80+
)
7681

7782
await userEvent.clear(colourInput)
78-
await userEvent.type(colourInput, "FFFFFF")
83+
await userEvent.type(colourInput, DEFAULT_CONTENT_INVERSE_COLOUR)
7984
},
8085
}
8186

8287
export const Empty: Story = {
8388
play: async ({ canvasElement }) => {
8489
const rootScreen = within(canvasElement.ownerDocument.body)
8590

86-
const colourInput = await rootScreen.findByPlaceholderText("FFFFFF")
91+
const colourInput = await rootScreen.findByPlaceholderText(
92+
DEFAULT_CONTENT_INVERSE_COLOUR,
93+
)
8794

8895
await userEvent.clear(colourInput)
8996
},

package-lock.json

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)