Skip to content

Commit

Permalink
feat: use JSONForms for complex block editing
Browse files Browse the repository at this point in the history
  • Loading branch information
dcshzj committed Jun 25, 2024
1 parent a43ad30 commit bb4a05e
Show file tree
Hide file tree
Showing 18 changed files with 602 additions and 764 deletions.
6 changes: 0 additions & 6 deletions apps/studio/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,10 @@
"@chakra-ui/styled-system": "^2.9.2",
"@chakra-ui/theme-tools": "^2.1.2",
"@chakra-ui/utils": "^2.0.15",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@hello-pangea/dnd": "^16.6.0",
"@hookform/resolvers": "^3.6.0",
"@jsonforms/core": "^3.3.0",
"@jsonforms/material-renderers": "^3.3.0",
"@jsonforms/react": "^3.3.0",
"@mui/icons-material": "^5.15.20",
"@mui/material": "^5.15.19",
"@mui/x-date-pickers": "^7.6.1",
"@opengovsg/design-system-react": "^1.15.0",
"@opengovsg/isomer-components": "*",
"@opengovsg/sgid-client": "^2.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import { Box } from '@chakra-ui/react'
import FormBuilder from './form-builder/FormBuilder'

export default function ComplexEditorStateDrawer(): JSX.Element {
return (
<Box p={4}>
<h1>Complex Editor State Drawer</h1>
<FormBuilder component="infocards" />
</Box>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { type DrawerState } from '~/types/editorDrawer'
import { useEditorDrawerContext } from '~/contexts/EditorDrawerContext'
import ComponentSelector from '~/components/PageEditor/ComponentSelector'
import TipTapComponent from './TipTapComponent'
import ComplexEditorStateDrawer from "./ComplexEditorStateDrawer"

type EditPageDrawerProps = {
isOpen: boolean
Expand Down Expand Up @@ -51,6 +52,8 @@ export function EditPageDrawer({ isOpen: open, state }: EditPageDrawerProps) {
type="paragraph"
/>
)
case 'complexEditor':
return <ComplexEditorStateDrawer />
default:
return <h1>Edit Page Drawer</h1>
}
Expand Down
166 changes: 0 additions & 166 deletions apps/studio/src/features/editing-experience/components/FormBuilder.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { type JsonFormsRendererRegistryEntry } from '@jsonforms/core'
import { JsonForms } from '@jsonforms/react'

import { useState } from 'react'
import IsomerSchema from '../../data/0.1.0.json'

import {
JsonFormsBooleanControl,
jsonFormsBooleanControlTester,
JsonFormsDropdownControl,
jsonFormsDropdownControlTester,
JsonFormsIntegerControl,
jsonFormsIntegerControlTester,
JsonFormsRadioControl,
jsonFormsRadioControlTester,
JsonFormsTextControl,
jsonFormsTextControlTester,
jsonFormsVerticalLayoutRenderer,
jsonFormsVerticalLayoutTester,
} from './renderers'

const renderers: JsonFormsRendererRegistryEntry[] = [
{ tester: jsonFormsBooleanControlTester, renderer: JsonFormsBooleanControl },
{
tester: jsonFormsDropdownControlTester,
renderer: JsonFormsDropdownControl,
},
{ tester: jsonFormsIntegerControlTester, renderer: JsonFormsIntegerControl },
{ tester: jsonFormsTextControlTester, renderer: JsonFormsTextControl },
{ tester: jsonFormsRadioControlTester, renderer: JsonFormsRadioControl },
{
tester: jsonFormsVerticalLayoutTester,
renderer: jsonFormsVerticalLayoutRenderer,
},
]

export interface FormBuilderProps {
component: keyof typeof IsomerSchema.components.complex
}

export default function FormBuilder({
component,
}: FormBuilderProps): JSX.Element {
const { properties, ...rest } = IsomerSchema.components.complex[component]
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { type, ...props } = properties
const newSchema = {
...rest,
properties: props,
components: IsomerSchema.components,
}

const [formData, setFormData] = useState({})

return (
<JsonForms
schema={newSchema}
data={formData}
renderers={renderers}
onChange={({ data }) => {
console.log(data)
setFormData(data)
}}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Box, FormControl } from '@chakra-ui/react'
import {
isBooleanControl,
rankWith,
type ControlProps,
type RankedTester,
} from '@jsonforms/core'
import { withJsonFormsControlProps } from '@jsonforms/react'
import {
FormErrorMessage,
FormLabel,
Switch,
} from '@opengovsg/design-system-react'

export const jsonFormsBooleanControlTester: RankedTester = rankWith(
2,
isBooleanControl,
)

export function JsonFormsBooleanControl({
data,
label,
id,
enabled,
handleChange,
errors,
path,
description,
}: ControlProps) {
return (
<Box py={2}>
<FormControl>
<FormLabel description={description} htmlFor={id}>
{label}
</FormLabel>
<Switch
id={id}
isDisabled={!enabled}
checked={data || false}
onChange={(e) => handleChange(path, e.target.checked)}
/>
<FormErrorMessage>{errors}</FormErrorMessage>
</FormControl>
</Box>
)
}

export default withJsonFormsControlProps(JsonFormsBooleanControl)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Box, FormControl } from '@chakra-ui/react'
import {
isEnumControl,
rankWith,
type ControlProps,
type OwnPropsOfEnum,
type RankedTester,
} from '@jsonforms/core'
import { withJsonFormsEnumProps } from '@jsonforms/react'
import { FormLabel, SingleSelect } from '@opengovsg/design-system-react'
import { useState } from 'react'

export const jsonFormsDropdownControlTester: RankedTester = rankWith(
2,
isEnumControl,
)

export function JsonFormsDropdownControl({
data,
label,
handleChange,
path,
description,
required,
options,
}: ControlProps & OwnPropsOfEnum) {
const [dropdownValue, setDropdownValue] = useState(data || '')

if (!options) {
return null
}

const items = options.map((option) => ({
label: option.label.charAt(0).toUpperCase() + option.label.slice(1),
value: option.value,
}))

return (
<Box py={2}>
<FormControl isRequired={required}>
<FormLabel description={description}>{label}</FormLabel>
<SingleSelect
value={dropdownValue}
name={label}
items={items}
isClearable={false}
onChange={(value) => {
setDropdownValue(value)
handleChange(path, value)
}}
/>
</FormControl>
</Box>
)
}

export default withJsonFormsEnumProps(JsonFormsDropdownControl)
Loading

0 comments on commit bb4a05e

Please sign in to comment.