UNPKG

@oberoncms/core

Version:

OberonCMS is a cloud deployable CMS written in typescript based on the Puck visual editor

163 lines (162 loc) 5.55 kB
"use client"; import { jsxs, jsx } from "react/jsx-runtime"; import Link from "next/link"; import { Fragment, useOptimistic, startTransition } from "react"; import { Button, buttonVariants } from "@tohuhono/ui/button"; import { Input } from "@tohuhono/ui/input"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Form, FormField, FormItem, FormControl, FormMessage } from "@tohuhono/ui/form"; import { LocalDate } from "@tohuhono/ui/date"; import { Grid, GridHeading } from "@tohuhono/ui/grid"; import { useOberonActions } from "../hooks/use-oberon.js"; import { AddPageSchema } from "../lib/dtd.js"; function copyKey(optimisticPages, key) { let iterator = 0; let newKey = `${key}_copy`; while (optimisticPages.find((page) => page.key === newKey)) { newKey = `${key}_copy_${++iterator}`; } return newKey; } const useOberonPages = (pages) => { const { deletePage, addPage, publishPageData, getPageData } = useOberonActions(); const [optimisticPages, optimisticPageUpdate] = useOptimistic(pages); return { pages: optimisticPages, addPage: (page) => { startTransition(() => { optimisticPageUpdate([ ...optimisticPages, { ...page, updatedAt: /* @__PURE__ */ new Date(), updatedBy: "", pending: true } ]); }); return addPage(page); }, copyPage: async (key) => { const newKey = copyKey(optimisticPages, key); startTransition(() => { optimisticPageUpdate([ ...optimisticPages, { key: newKey, updatedAt: /* @__PURE__ */ new Date(), updatedBy: "", pending: true } ]); }); const data = await getPageData(key); if (data) { return publishPageData({ key: newKey, data }); } return addPage({ key: newKey }); }, deletePage: async (key) => { startTransition( () => optimisticPageUpdate( optimisticPages.map( (page) => page.key === key ? { ...page, pending: true } : page ) ) ); return deletePage({ key }); } }; }; const parsePath = (key) => { if (!key) { return ""; } return (key.charAt(0) === "/" ? key : "/" + key).replace(" ", "_"); }; function Pages({ pages: serverPages }) { const { pages, deletePage, addPage, copyPage } = useOberonPages(serverPages); const form = useForm({ resolver: zodResolver(AddPageSchema), defaultValues: { key: "" } }); return /* @__PURE__ */ jsxs(Grid, { className: "grid-cols-[1fr_auto_auto_auto_auto_auto]", children: [ /* @__PURE__ */ jsx(GridHeading, { children: "Path" }), /* @__PURE__ */ jsx(GridHeading, { children: "Updated" }), /* @__PURE__ */ jsx(GridHeading, { children: "By" }), /* @__PURE__ */ jsx(GridHeading, { className: "col-span-3" }), /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs( "form", { className: "contents", onSubmit: form.handleSubmit((data) => { addPage(data); form.reset(); }), children: [ /* @__PURE__ */ jsx( FormField, { control: form.control, name: "key", render: ({ field }) => { var _a; return /* @__PURE__ */ jsxs(FormItem, { className: "row-span-2", children: [ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx( Input, { placeholder: "", ...field, onChange: (e) => { form.setValue("key", parsePath(e.currentTarget.value)); } } ) }), /* @__PURE__ */ jsx(FormMessage, { children: (_a = form.formState.errors.key) == null ? void 0 : _a.message }) ] }); } } ), /* @__PURE__ */ jsx("div", { className: "col-span-2 row-span-2" }), /* @__PURE__ */ jsx(Button, { type: "submit", className: "col-span-3 row-span-2", children: "Add Page" }) ] } ) }), pages.map(({ key: route, updatedBy, updatedAt, pending }) => /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( Link, { className: buttonVariants({ variant: "ghost", size: "link", className: "no-underline" }), href: route, prefetch: false, children: route } ), /* @__PURE__ */ jsx("div", { className: "text-sm", children: /* @__PURE__ */ jsx(LocalDate, { date: updatedAt }) }), /* @__PURE__ */ jsx("div", { className: "text-sm", children: updatedBy }), pending ? /* @__PURE__ */ jsx(Button, { size: "sm", disabled: true, children: "Edit" }) : /* @__PURE__ */ jsx( Link, { className: buttonVariants({ size: "sm", className: "no-underline" }), href: `/cms/edit${route}`, prefetch: false, children: "Edit" } ), /* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => copyPage(route), disabled: pending, children: "Copy" }), /* @__PURE__ */ jsx( Button, { variant: "destructive", size: "sm", onClick: () => deletePage(route), disabled: pending, children: "Delete" } ) ] }, route)) ] }); } export { Pages };