Skip to content

Commit

Permalink
feat(tiptap): save updates to db + invalidate queries (#367)
Browse files Browse the repository at this point in the history
* fix: complex editor

wire save through to db

* refactor: complex editor state drawer

refactor so props correctness handled otuside

* fix: update page

invalidate on update

* fix: updatePageBlob

now requires db

* feat: tiptap component

update db on save + invalidate old queries

* chore: use exported schema
  • Loading branch information
seaerchin authored Jul 29, 2024
1 parent efda029 commit 3281001
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 15 deletions.
7 changes: 6 additions & 1 deletion apps/studio/src/components/PageEditor/ComponentSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ function ComponentSelector({ pageId, siteId }: ComponentSelectorProps) {
setPreviewPageState,
setAddedBlock,
} = useEditorDrawerContext()
const { mutate } = trpc.page.updatePageBlob.useMutation()
const utils = trpc.useUtils()
const { mutate } = trpc.page.updatePageBlob.useMutation({
onSuccess: async () => {
await utils.page.readPageAndBlob.invalidate({ pageId, siteId })
},
})
const [page] = trpc.page.readPageAndBlob.useSuspenseQuery({
pageId,
siteId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
import type { IsomerComponent } from "@opengovsg/isomer-components"
import { Box, Heading, HStack, Icon } from "@chakra-ui/react"
import { Button, IconButton } from "@opengovsg/design-system-react"
import { getComponentSchema } from "@opengovsg/isomer-components"
import { BiDollar, BiX } from "react-icons/bi"

import { useEditorDrawerContext } from "~/contexts/EditorDrawerContext"
import { useQueryParse } from "~/hooks/useQueryParse"
import { editPageSchema } from "~/pages/sites/[siteId]/pages/[pageId]"
import { trpc } from "~/utils/trpc"
import FormBuilder from "./form-builder/FormBuilder"

export default function ComplexEditorStateDrawer(): JSX.Element {
interface ComplexEditorStateDrawerProps {
component: IsomerComponent
}

const ComplexEditorStateDrawer = ({
component,
}: ComplexEditorStateDrawerProps) => {
const { pageId, siteId } = useQueryParse(editPageSchema)
const [{ content: pageContent }] = trpc.page.readPageAndBlob.useSuspenseQuery(
{ siteId, pageId },
)
const {
currActiveIdx,
setDrawerState,
savedPageState,
setSavedPageState,
previewPageState,
setPreviewPageState,
} = useEditorDrawerContext()

if (currActiveIdx === -1 || currActiveIdx > savedPageState.length) {
return <></>
}

const component = previewPageState[currActiveIdx]

if (!component) {
return <></>
}

const { title } = getComponentSchema(component.type)
const utils = trpc.useUtils()

const { mutate, isLoading } = trpc.page.updatePageBlob.useMutation({
onSuccess: async () => {
await utils.page.readPageAndBlob.invalidate({ pageId, siteId })
},
})

return (
<Box position="relative" h="100%" w="100%" overflow="auto">
Expand Down Expand Up @@ -74,11 +83,36 @@ export default function ComplexEditorStateDrawer(): JSX.Element {
onClick={() => {
setDrawerState({ state: "root" })
setSavedPageState(previewPageState)
mutate({
pageId,
siteId,
content: JSON.stringify({
...pageContent,
content: previewPageState,
}),
})
}}
isLoading={isLoading}
>
Save
</Button>
</Box>
</Box>
)
}

export default function ComplexEditorStateDrawerContainer(): JSX.Element {
const { currActiveIdx, savedPageState, previewPageState } =
useEditorDrawerContext()
if (currActiveIdx === -1 || currActiveIdx > savedPageState.length) {
return <></>
}

const component = previewPageState[currActiveIdx]

if (!component) {
return <></>
}

return <ComplexEditorStateDrawer component={component} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { cloneDeep } from "lodash"
import { BiText, BiX } from "react-icons/bi"

import { useEditorDrawerContext } from "~/contexts/EditorDrawerContext"
import { useQueryParse } from "~/hooks/useQueryParse"
import { editPageSchema } from "~/pages/sites/[siteId]/pages/[pageId]"
import { trpc } from "~/utils/trpc"
import { TiptapEditor } from "./form-builder/renderers/TipTapEditor"

interface TipTapComponentProps {
Expand Down Expand Up @@ -34,6 +37,18 @@ function TipTapComponent({ content }: TipTapComponentProps) {
})
}

const utils = trpc.useUtils()

const { pageId, siteId } = useQueryParse(editPageSchema)
const { mutate } = trpc.page.updatePageBlob.useMutation({
onSuccess: async () => {
await utils.page.readPageAndBlob.invalidate({ pageId, siteId })
},
})
const [{ content: pageContent }] = trpc.page.readPageAndBlob.useSuspenseQuery(
{ siteId, pageId },
)

// TODO: Add a loading state or use suspsense
return (
<VStack bg="white" h="100%" gap="0">
Expand Down Expand Up @@ -77,6 +92,14 @@ function TipTapComponent({ content }: TipTapComponentProps) {
onClick={() => {
setDrawerState({ state: "root" })
setSavedPageState(previewPageState)
mutate({
pageId,
siteId,
content: JSON.stringify({
...pageContent,
content: previewPageState,
}),
})
}}
>
Save
Expand Down
2 changes: 1 addition & 1 deletion apps/studio/src/server/modules/page/page.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export const pageRouter = router({
.mutation(async ({ input }) => {
// @ts-expect-error we need this because we sanitise as a string
// but this accepts a nested JSON object
await updateBlobById({ ...input, pageId: input.pageId })
await updateBlobById(db, { ...input, pageId: input.pageId })

return input
}),
Expand Down

0 comments on commit 3281001

Please sign in to comment.