@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
JavaScript
"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
};