@tekki-forge/runtime-admin 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-dashboard.d.ts +16 -0
- package/dist/admin-dashboard.js +60 -0
- package/dist/admin-dashboard.js.map +1 -0
- package/dist/admin-orgs.d.ts +14 -0
- package/dist/admin-orgs.js +75 -0
- package/dist/admin-orgs.js.map +1 -0
- package/dist/admin-shell.d.ts +55 -0
- package/dist/admin-shell.js +141 -0
- package/dist/admin-shell.js.map +1 -0
- package/dist/admin.js +35 -4
- package/dist/admin.js.map +1 -1
- package/dist/app-pages.d.ts +19 -0
- package/dist/app-pages.js +109 -0
- package/dist/app-pages.js.map +1 -0
- package/dist/auth-pages.js +7 -2
- package/dist/auth-pages.js.map +1 -1
- package/dist/charts.d.ts +98 -2
- package/dist/charts.js +264 -24
- package/dist/charts.js.map +1 -1
- package/dist/context.js +32 -1
- package/dist/context.js.map +1 -1
- package/dist/dashboard.d.ts +63 -8
- package/dist/dashboard.js +180 -36
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/messages/de.js +751 -0
- package/dist/i18n/messages/de.js.map +1 -1
- package/dist/i18n/messages/en.js +751 -0
- package/dist/i18n/messages/en.js.map +1 -1
- package/dist/i18n/messages/es.js +751 -0
- package/dist/i18n/messages/es.js.map +1 -1
- package/dist/i18n/messages/fr.js +751 -0
- package/dist/i18n/messages/fr.js.map +1 -1
- package/dist/i18n/messages/pt.js +751 -0
- package/dist/i18n/messages/pt.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/shell.js +37 -34
- package/dist/shell.js.map +1 -1
- package/dist/site/editor/api.d.ts +74 -0
- package/dist/site/editor/api.js +93 -0
- package/dist/site/editor/api.js.map +1 -0
- package/dist/site/editor/content-page.d.ts +4 -0
- package/dist/site/editor/content-page.js +65 -0
- package/dist/site/editor/content-page.js.map +1 -0
- package/dist/site/editor/inbox-tab.d.ts +4 -0
- package/dist/site/editor/inbox-tab.js +88 -0
- package/dist/site/editor/inbox-tab.js.map +1 -0
- package/dist/site/editor/index.d.ts +1 -0
- package/dist/site/editor/index.js +3 -0
- package/dist/site/editor/index.js.map +1 -0
- package/dist/site/editor/model.d.ts +145 -0
- package/dist/site/editor/model.js +408 -0
- package/dist/site/editor/model.js.map +1 -0
- package/dist/site/editor/page-editor.d.ts +10 -0
- package/dist/site/editor/page-editor.js +257 -0
- package/dist/site/editor/page-editor.js.map +1 -0
- package/dist/site/editor/page-settings.d.ts +9 -0
- package/dist/site/editor/page-settings.js +105 -0
- package/dist/site/editor/page-settings.js.map +1 -0
- package/dist/site/editor/pages-tab.d.ts +5 -0
- package/dist/site/editor/pages-tab.js +108 -0
- package/dist/site/editor/pages-tab.js.map +1 -0
- package/dist/site/editor/posts-tab.d.ts +6 -0
- package/dist/site/editor/posts-tab.js +139 -0
- package/dist/site/editor/posts-tab.js.map +1 -0
- package/dist/site/editor/preview.d.ts +32 -0
- package/dist/site/editor/preview.js +104 -0
- package/dist/site/editor/preview.js.map +1 -0
- package/dist/site/editor/prop-fields.d.ts +53 -0
- package/dist/site/editor/prop-fields.js +233 -0
- package/dist/site/editor/prop-fields.js.map +1 -0
- package/dist/site/editor/section-list.d.ts +14 -0
- package/dist/site/editor/section-list.js +110 -0
- package/dist/site/editor/section-list.js.map +1 -0
- package/dist/site/editor/section-picker.d.ts +12 -0
- package/dist/site/editor/section-picker.js +44 -0
- package/dist/site/editor/section-picker.js.map +1 -0
- package/dist/site/editor/widgets.d.ts +84 -0
- package/dist/site/editor/widgets.js +130 -0
- package/dist/site/editor/widgets.js.map +1 -0
- package/dist/site/format.d.ts +31 -0
- package/dist/site/format.js +106 -0
- package/dist/site/format.js.map +1 -0
- package/dist/site/forms.d.ts +43 -0
- package/dist/site/forms.js +155 -0
- package/dist/site/forms.js.map +1 -0
- package/dist/site/header.d.ts +32 -0
- package/dist/site/header.js +76 -0
- package/dist/site/header.js.map +1 -0
- package/dist/site/icons.d.ts +10 -0
- package/dist/site/icons.js +28 -0
- package/dist/site/icons.js.map +1 -0
- package/dist/site/index.d.ts +11 -0
- package/dist/site/index.js +13 -0
- package/dist/site/index.js.map +1 -0
- package/dist/site/markdown.d.ts +14 -0
- package/dist/site/markdown.js +457 -0
- package/dist/site/markdown.js.map +1 -0
- package/dist/site/page.d.ts +16 -0
- package/dist/site/page.js +65 -0
- package/dist/site/page.js.map +1 -0
- package/dist/site/proxy.d.ts +13 -0
- package/dist/site/proxy.js +43 -0
- package/dist/site/proxy.js.map +1 -0
- package/dist/site/sections.d.ts +43 -0
- package/dist/site/sections.js +560 -0
- package/dist/site/sections.js.map +1 -0
- package/dist/site/server.d.ts +73 -0
- package/dist/site/server.js +235 -0
- package/dist/site/server.js.map +1 -0
- package/dist/site/types.d.ts +137 -0
- package/dist/site/types.js +2 -0
- package/dist/site/types.js.map +1 -0
- package/dist/support.d.ts +29 -0
- package/dist/support.js +165 -0
- package/dist/support.js.map +1 -0
- package/dist/system-config.d.ts +24 -0
- package/dist/system-config.js +37 -0
- package/dist/system-config.js.map +1 -0
- package/dist/system-settings.d.ts +9 -0
- package/dist/system-settings.js +60 -0
- package/dist/system-settings.js.map +1 -0
- package/dist/theme-catalog.d.ts +72 -2
- package/dist/theme-catalog.js +47 -0
- package/dist/theme-catalog.js.map +1 -1
- package/dist/theme-switcher.d.ts +8 -0
- package/dist/theme-switcher.js +39 -4
- package/dist/theme-switcher.js.map +1 -1
- package/dist/theme.js +8 -0
- package/dist/theme.js.map +1 -1
- package/dist/transactions.d.ts +4 -0
- package/dist/transactions.js +60 -0
- package/dist/transactions.js.map +1 -0
- package/package.json +9 -5
- package/styles.css +1089 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/*
|
|
4
|
+
* Editor of one page: sections on the left (reorder, add, hide, delete, revert), the live preview in the middle
|
|
5
|
+
* (real section components; click a section to select it) and the selected section's generated form on the
|
|
6
|
+
* right. Edits show in the preview at once and are saved after a short pause (or with "Save now").
|
|
7
|
+
*/
|
|
8
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
9
|
+
import { checkSiteSection, sectionSpec } from "@tekki-forge/compiler/site";
|
|
10
|
+
import { ArrowLeft, ExternalLink, Eye, EyeOff, Globe, Plus, RotateCcw, Settings2, TriangleAlert } from "lucide-react";
|
|
11
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
12
|
+
import { useForge } from "../../context.js";
|
|
13
|
+
import { DetailSkeleton } from "../../skeleton.js";
|
|
14
|
+
import { useToast } from "../../toast.js";
|
|
15
|
+
import { Alert, Button, Card, EmptyState } from "../../ui.js";
|
|
16
|
+
import { apiIssues, errorMessage, errorStatus, siteKeys, useInvalidateSite, usePageDetail, usePreviewData } from "./api.js";
|
|
17
|
+
import { AUTOSAVE_MS, cleanSectionProps, issuesByField, needsPreviewData } from "./model.js";
|
|
18
|
+
import { PageSettings } from "./page-settings.js";
|
|
19
|
+
import { DeviceToggle, PagePreview } from "./preview.js";
|
|
20
|
+
import { PropsForm } from "./prop-fields.js";
|
|
21
|
+
import { SectionList } from "./section-list.js";
|
|
22
|
+
import { SectionPicker, VariantChooser } from "./section-picker.js";
|
|
23
|
+
import { Confirm, Pill, SaveIndicator, Switch, useAnnouncer } from "./widgets.js";
|
|
24
|
+
export function pageViewHref(page) {
|
|
25
|
+
return page.status === "draft" ? `${page.path}?preview=1` : page.path;
|
|
26
|
+
}
|
|
27
|
+
export function PageEditor({ pageId, overview, onBack }) {
|
|
28
|
+
const { api, app, t } = useForge();
|
|
29
|
+
const toast = useToast();
|
|
30
|
+
const qc = useQueryClient();
|
|
31
|
+
const invalidate = useInvalidateSite();
|
|
32
|
+
const detail = usePageDetail(pageId);
|
|
33
|
+
const fetchPreview = usePreviewData();
|
|
34
|
+
const [region, announce] = useAnnouncer();
|
|
35
|
+
const [drafts, setDrafts] = useState({});
|
|
36
|
+
const draftsRef = useRef(drafts);
|
|
37
|
+
draftsRef.current = drafts;
|
|
38
|
+
const [errors, setErrors] = useState({});
|
|
39
|
+
const [saveState, setSaveState] = useState("idle");
|
|
40
|
+
const [saveMessage, setSaveMessage] = useState();
|
|
41
|
+
const [previewData, setPreviewData] = useState({});
|
|
42
|
+
const [selected, setSelected] = useState(null);
|
|
43
|
+
const [device, setDevice] = useState("desktop");
|
|
44
|
+
const [picker, setPicker] = useState(false);
|
|
45
|
+
const [settings, setSettings] = useState(false);
|
|
46
|
+
const [deleting, setDeleting] = useState(null);
|
|
47
|
+
const [busy, setBusy] = useState(false);
|
|
48
|
+
const timers = useRef(new Map());
|
|
49
|
+
const previewTimers = useRef(new Map());
|
|
50
|
+
const formRef = useRef(null);
|
|
51
|
+
const page = detail.data;
|
|
52
|
+
const pageKey = useMemo(() => siteKeys.page(pageId), [pageId]);
|
|
53
|
+
const checkApp = useMemo(() => ({ entities: app.entities, plugins: app.plugins, embedHosts: app.site?.embedHosts ?? [] }), [app]);
|
|
54
|
+
const live = useMemo(() => (page?.sections ?? []).filter((s) => !s.removed).sort((a, b) => a.position - b.position), [page]);
|
|
55
|
+
const removed = useMemo(() => (page?.sections ?? []).filter((s) => s.removed), [page]);
|
|
56
|
+
const merged = useMemo(() => live.map((s) => (drafts[s.id] ? { ...s, variant: drafts[s.id].variant, props: drafts[s.id].props } : s)), [live, drafts]);
|
|
57
|
+
const current = merged.find((s) => s.id === selected) ?? null;
|
|
58
|
+
// Select the first section once the page arrives (or when the selected one disappears).
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!page)
|
|
61
|
+
return;
|
|
62
|
+
if (!selected || !live.some((s) => s.id === selected))
|
|
63
|
+
setSelected(live[0]?.id ?? null);
|
|
64
|
+
}, [page, live, selected]);
|
|
65
|
+
const patchCache = useCallback((fn) => qc.setQueryData(pageKey, (old) => (old ? fn(old) : old)), [qc, pageKey]);
|
|
66
|
+
const save = useCallback(async (id) => {
|
|
67
|
+
timers.current.delete(id);
|
|
68
|
+
const draft = draftsRef.current[id];
|
|
69
|
+
const section = qc.getQueryData(pageKey)?.sections.find((s) => s.id === id);
|
|
70
|
+
if (!draft || !section)
|
|
71
|
+
return;
|
|
72
|
+
const props = cleanSectionProps(section.type, draft.props);
|
|
73
|
+
const check = checkSiteSection(checkApp, { type: section.type, variant: draft.variant, props });
|
|
74
|
+
if (check.issues.length) {
|
|
75
|
+
setErrors((e) => ({ ...e, [id]: issuesByField(check.issues) }));
|
|
76
|
+
setSaveState("invalid");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
setSaveState("saving");
|
|
80
|
+
try {
|
|
81
|
+
const saved = await api(`/site/admin/sections/${id}`, { method: "PATCH", body: JSON.stringify({ variant: draft.variant, props }) });
|
|
82
|
+
setErrors((e) => ({ ...e, [id]: {} }));
|
|
83
|
+
// Keep the draft when it changed while saving (the next save sends it).
|
|
84
|
+
if (draftsRef.current[id]?.version === draft.version) {
|
|
85
|
+
setDrafts(({ [id]: _done, ...rest }) => rest);
|
|
86
|
+
patchCache((p) => ({ ...p, edited: true, sections: p.sections.map((s) => (s.id === id ? (saved && saved.id ? { ...s, ...saved } : { ...s, variant: draft.variant, props, edited: s.origin === "config" ? true : s.edited }) : s)) }));
|
|
87
|
+
}
|
|
88
|
+
setSaveState(timers.current.size ? "dirty" : "saved");
|
|
89
|
+
void invalidate("overview");
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
const issues = apiIssues(e);
|
|
93
|
+
if (issues.length) {
|
|
94
|
+
setErrors((all) => ({ ...all, [id]: issuesByField(issues) }));
|
|
95
|
+
setSaveState("invalid");
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
setSaveState("error");
|
|
99
|
+
setSaveMessage(errorMessage(e));
|
|
100
|
+
toast.error(t("siteAdmin.save.error"), errorMessage(e));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}, [api, checkApp, invalidate, patchCache, pageKey, qc, t, toast]);
|
|
104
|
+
const refreshPreview = useCallback((id, type, variant, props) => {
|
|
105
|
+
const existing = previewTimers.current.get(id);
|
|
106
|
+
if (existing)
|
|
107
|
+
clearTimeout(existing);
|
|
108
|
+
if (!needsPreviewData(type, props))
|
|
109
|
+
return;
|
|
110
|
+
previewTimers.current.set(id, setTimeout(() => {
|
|
111
|
+
previewTimers.current.delete(id);
|
|
112
|
+
fetchPreview([{ type, variant, props: cleanSectionProps(type, props) }])
|
|
113
|
+
.then((data) => setPreviewData((d) => ({ ...d, [id]: data[0] ?? undefined })))
|
|
114
|
+
.catch(() => undefined);
|
|
115
|
+
}, 600));
|
|
116
|
+
}, [fetchPreview]);
|
|
117
|
+
const edit = (s, next) => {
|
|
118
|
+
const prev = draftsRef.current[s.id];
|
|
119
|
+
const draft = { variant: next.variant ?? prev?.variant ?? s.variant, props: next.props ?? prev?.props ?? s.props, version: (prev?.version ?? 0) + 1 };
|
|
120
|
+
setDrafts((d) => ({ ...d, [s.id]: draft }));
|
|
121
|
+
draftsRef.current = { ...draftsRef.current, [s.id]: draft };
|
|
122
|
+
setSaveState("dirty");
|
|
123
|
+
const timer = timers.current.get(s.id);
|
|
124
|
+
if (timer)
|
|
125
|
+
clearTimeout(timer);
|
|
126
|
+
timers.current.set(s.id, setTimeout(() => void save(s.id), AUTOSAVE_MS));
|
|
127
|
+
refreshPreview(s.id, s.type, draft.variant, draft.props);
|
|
128
|
+
};
|
|
129
|
+
const saveNow = () => {
|
|
130
|
+
for (const [id, timer] of timers.current) {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
void save(id);
|
|
133
|
+
}
|
|
134
|
+
if (current && drafts[current.id] && !timers.current.size)
|
|
135
|
+
void save(current.id);
|
|
136
|
+
};
|
|
137
|
+
const saveRef = useRef(save);
|
|
138
|
+
saveRef.current = save;
|
|
139
|
+
// Leaving the editor: send what's pending; warn before closing the tab with unsaved edits.
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
const pending = timers.current;
|
|
142
|
+
const onUnload = (e) => {
|
|
143
|
+
if (pending.size)
|
|
144
|
+
e.preventDefault();
|
|
145
|
+
};
|
|
146
|
+
window.addEventListener("beforeunload", onUnload);
|
|
147
|
+
return () => {
|
|
148
|
+
window.removeEventListener("beforeunload", onUnload);
|
|
149
|
+
for (const [id, timer] of pending) {
|
|
150
|
+
clearTimeout(timer);
|
|
151
|
+
void saveRef.current(id);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}, []);
|
|
155
|
+
const run = async (fn, success) => {
|
|
156
|
+
setBusy(true);
|
|
157
|
+
try {
|
|
158
|
+
await fn();
|
|
159
|
+
if (success) {
|
|
160
|
+
toast.success(success);
|
|
161
|
+
announce(success);
|
|
162
|
+
}
|
|
163
|
+
await qc.invalidateQueries({ queryKey: pageKey });
|
|
164
|
+
void invalidate("overview");
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
toast.error(t("siteAdmin.error.action"), errorMessage(e));
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
setBusy(false);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
const reorder = async (ids) => {
|
|
176
|
+
const before = qc.getQueryData(pageKey);
|
|
177
|
+
patchCache((p) => ({ ...p, sections: p.sections.map((s) => (ids.includes(s.id) ? { ...s, position: ids.indexOf(s.id) } : s)) }));
|
|
178
|
+
try {
|
|
179
|
+
await api(`/site/admin/pages/${pageId}/order`, { method: "PUT", body: JSON.stringify({ ids }) });
|
|
180
|
+
setSaveState("saved");
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
if (before)
|
|
184
|
+
qc.setQueryData(pageKey, before);
|
|
185
|
+
toast.error(t("siteAdmin.error.reorder"), errorMessage(e));
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const toggleHidden = async (s) => {
|
|
189
|
+
const hidden = !s.hidden;
|
|
190
|
+
patchCache((p) => ({ ...p, sections: p.sections.map((x) => (x.id === s.id ? { ...x, hidden } : x)) }));
|
|
191
|
+
try {
|
|
192
|
+
await api(`/site/admin/sections/${s.id}`, { method: "PATCH", body: JSON.stringify({ hidden }) });
|
|
193
|
+
announce(hidden ? t("siteAdmin.section.hiddenNow", { name: t(`siteAdmin.section.${s.type}.label`) }) : t("siteAdmin.section.shownNow", { name: t(`siteAdmin.section.${s.type}.label`) }));
|
|
194
|
+
}
|
|
195
|
+
catch (e) {
|
|
196
|
+
patchCache((p) => ({ ...p, sections: p.sections.map((x) => (x.id === s.id ? { ...x, hidden: s.hidden } : x)) }));
|
|
197
|
+
toast.error(t("siteAdmin.error.action"), errorMessage(e));
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const add = async (type, variant) => {
|
|
201
|
+
const index = selected ? live.findIndex((s) => s.id === selected) : -1;
|
|
202
|
+
setBusy(true);
|
|
203
|
+
try {
|
|
204
|
+
// `after` = index of the section the new one follows (the selected one); the API answers with the page.
|
|
205
|
+
const updated = await api(`/site/admin/pages/${pageId}/sections`, { method: "POST", body: JSON.stringify({ type, variant, ...(index >= 0 ? { after: index } : {}) }) });
|
|
206
|
+
setPicker(false);
|
|
207
|
+
if (updated?.sections) {
|
|
208
|
+
qc.setQueryData(pageKey, updated);
|
|
209
|
+
const ordered = updated.sections.filter((s) => !s.removed).sort((a, b) => a.position - b.position);
|
|
210
|
+
const created = ordered[index >= 0 ? index + 1 : ordered.length - 1];
|
|
211
|
+
if (created)
|
|
212
|
+
setSelected(created.id);
|
|
213
|
+
}
|
|
214
|
+
else
|
|
215
|
+
await qc.invalidateQueries({ queryKey: pageKey });
|
|
216
|
+
const name = t(`siteAdmin.section.${type}.label`);
|
|
217
|
+
announce(t("siteAdmin.section.added", { name }));
|
|
218
|
+
toast.success(t("siteAdmin.section.added", { name }));
|
|
219
|
+
void invalidate("overview");
|
|
220
|
+
requestAnimationFrame(() => formRef.current?.querySelector("input, textarea, select")?.focus());
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
toast.error(t("siteAdmin.error.add"), errorMessage(e));
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
setBusy(false);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
const revertSection = (s) => {
|
|
230
|
+
const pendingTimer = timers.current.get(s.id);
|
|
231
|
+
if (pendingTimer)
|
|
232
|
+
clearTimeout(pendingTimer);
|
|
233
|
+
timers.current.delete(s.id);
|
|
234
|
+
setDrafts(({ [s.id]: _gone, ...rest }) => rest);
|
|
235
|
+
setErrors(({ [s.id]: _e, ...rest }) => rest);
|
|
236
|
+
void run(() => api(`/site/admin/sections/${s.id}/revert`, { method: "POST" }), t("siteAdmin.section.reverted", { name: t(`siteAdmin.section.${s.type}.label`) }));
|
|
237
|
+
};
|
|
238
|
+
if (detail.isLoading)
|
|
239
|
+
return _jsx(DetailSkeleton, { fields: 4 });
|
|
240
|
+
if (detail.error || !page) {
|
|
241
|
+
return (_jsx(Card, { children: _jsx(EmptyState, { illustration: "search", title: errorStatus(detail.error) === 404 ? t("siteAdmin.page.notFound") : t("siteAdmin.error.load"), description: detail.error ? errorMessage(detail.error) : undefined, action: _jsxs(Button, { onClick: onBack, children: [_jsx(ArrowLeft, { className: "size-4", "aria-hidden": true }), " ", t("siteAdmin.page.back")] }) }) }));
|
|
242
|
+
}
|
|
243
|
+
const isRedirect = !!page.redirect;
|
|
244
|
+
const publish = (status) => run(() => api(`/site/admin/pages/${page.id}`, { method: "PATCH", body: JSON.stringify({ status }) }), status === "published" ? t("siteAdmin.page.publishedNow", { title: page.title }) : t("siteAdmin.page.unpublishedNow", { title: page.title }));
|
|
245
|
+
const preview = merged.map((s) => ({ ...s, data: previewData[s.id] ?? s.data }));
|
|
246
|
+
const spec = current ? sectionSpec(current.type) : undefined;
|
|
247
|
+
const columns = Array.isArray(current?.props.columns) ? current.props.columns.filter((c) => typeof c === "string") : [];
|
|
248
|
+
const ctx = current ? { app, storage: !!overview?.storage, type: current.type, errors: errors[current.id] ?? {}, columns, idPrefix: `sec-${current.id.slice(0, 8)}` } : null;
|
|
249
|
+
const original = current ? live.find((s) => s.id === current.id) : null;
|
|
250
|
+
return (_jsxs("div", { className: "space-y-4", children: [region, _jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: onBack, "aria-label": t("siteAdmin.page.back"), children: _jsx(ArrowLeft, { className: "size-4", "aria-hidden": true }) }), _jsxs("div", { className: "min-w-0", children: [_jsxs("h2", { className: "forge-heading flex items-center gap-2 truncate text-lg font-semibold text-ink", children: [_jsx("span", { className: "truncate", children: page.title }), _jsx(Pill, { tone: page.status === "published" ? "success" : "muted", children: page.status === "published" ? t("siteAdmin.status.published") : t("siteAdmin.status.draft") })] }), _jsxs("p", { className: "flex items-center gap-2 truncate font-mono text-xs text-ink-muted", children: [page.path, _jsx(SaveIndicator, { state: saveState, message: saveMessage })] })] })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [(saveState === "dirty" || saveState === "invalid" || saveState === "error") && (_jsx(Button, { size: "sm", onClick: saveNow, children: t("siteAdmin.save.now") })), _jsxs("a", { href: pageViewHref(page), target: "_blank", rel: "noreferrer", className: "forge-btn forge-btn-ghost inline-flex h-7 items-center gap-1.5 px-2.5 text-xs font-medium", children: [_jsx(ExternalLink, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.view"), _jsx("span", { className: "sr-only", children: t("siteAdmin.newTab") })] }), _jsxs(Button, { size: "sm", onClick: () => setSettings(true), children: [_jsx(Settings2, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.settings")] }), page.status === "published" ? (_jsxs(Button, { size: "sm", loading: busy, onClick: () => publish("draft"), children: [_jsx(EyeOff, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.unpublish")] })) : (_jsxs(Button, { size: "sm", variant: "primary", loading: busy, onClick: () => publish("published"), children: [_jsx(Globe, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.publish")] }))] })] }), page.conflict && (_jsx(Alert, { tone: "info", children: _jsxs("span", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("span", { className: "flex items-center gap-2", children: [_jsx(TriangleAlert, { className: "size-4 shrink-0", "aria-hidden": true }), " ", t("siteAdmin.conflict.page")] }), _jsx(Button, { size: "sm", loading: busy, onClick: () => run(() => api(`/site/admin/pages/${page.id}/revert`, { method: "POST" }), t("siteAdmin.page.reverted")), children: t("siteAdmin.conflict.useConfig") })] }) })), isRedirect && _jsx(Alert, { tone: "info", children: t("siteAdmin.page.redirectNote", { target: page.redirect }) }), _jsxs("div", { className: "grid items-start gap-4 lg:grid-cols-[300px_minmax(0,1fr)] xl:grid-cols-[290px_minmax(0,1fr)_360px]", children: [_jsxs(Card, { className: "p-2 lg:sticky lg:top-4 lg:col-start-1 lg:row-start-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1 pt-1 pb-2", children: [_jsx("h3", { className: "text-xs font-semibold tracking-wide text-ink-muted uppercase", children: t("siteAdmin.sections.title") }), _jsxs(Button, { size: "sm", variant: "primary", onClick: () => setPicker(true), disabled: busy, children: [_jsx(Plus, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.sections.add")] })] }), _jsx(SectionList, { sections: merged, removed: removed, selected: selected, busy: busy, announce: announce, onSelect: setSelected, onReorder: reorder, onToggleHidden: toggleHidden, onDelete: setDeleting, onRevert: revertSection })] }), _jsx("div", { ref: formRef, className: "lg:col-start-1 lg:row-start-2 xl:sticky xl:top-4 xl:col-start-3 xl:row-start-1 xl:max-h-[calc(100dvh-2rem)] xl:overflow-y-auto", children: _jsx(Card, { className: "p-4", children: !current || !spec || !ctx || !original ? (_jsx("p", { className: "py-8 text-center text-sm text-ink-muted", children: live.length ? t("siteAdmin.form.pick") : t("siteAdmin.sections.empty") })) : (_jsxs("section", { "aria-labelledby": "site-section-form-title", className: "space-y-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { id: "site-section-form-title", className: "text-sm font-semibold text-ink", children: t(`siteAdmin.section.${current.type}.label`) }), _jsx("p", { className: "text-xs text-ink-muted", children: t(`siteAdmin.section.${current.type}.description`) })] }), _jsx(Pill, { tone: original.origin === "config" ? "info" : "muted", title: original.origin === "config" ? t("siteAdmin.origin.configHint") : undefined, children: original.origin === "config" ? t("siteAdmin.origin.config") : t("siteAdmin.origin.admin") })] }), original.conflict && (_jsxs("div", { className: "forge-alert px-3 py-2 text-xs", "data-forge-alert": "info", role: "status", children: [_jsxs("p", { className: "flex items-center gap-1.5", children: [_jsx(TriangleAlert, { className: "size-3.5 shrink-0", "aria-hidden": true }), " ", t("siteAdmin.conflict.section")] }), _jsx(Button, { size: "sm", className: "mt-2", loading: busy, onClick: () => revertSection(original), children: t("siteAdmin.conflict.useConfig") })] })), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("label", { htmlFor: "site-section-visible", className: "flex items-center gap-1.5 text-sm text-ink", children: [current.hidden ? _jsx(EyeOff, { className: "size-4 text-ink-muted", "aria-hidden": true }) : _jsx(Eye, { className: "size-4 text-ink-muted", "aria-hidden": true }), t("siteAdmin.section.visible")] }), _jsx(Switch, { id: "site-section-visible", checked: !current.hidden, onChange: () => toggleHidden(original) })] }), _jsx(VariantChooser, { type: current.type, value: current.variant, onChange: (variant) => edit(original, { variant }) }), ctx.errors[""] && _jsx(Alert, { children: ctx.errors[""] }), ctx.errors.variant && _jsx(Alert, { children: ctx.errors.variant }), spec.props.length ? _jsx(PropsForm, { fields: spec.props, value: current.props, path: "", ctx: ctx, onChange: (props) => edit(original, { props }) }, current.id) : _jsx("p", { className: "text-sm text-ink-muted", children: t("siteAdmin.form.noProps") }), original.origin === "config" && original.edited && !original.conflict && (_jsxs("div", { className: "border-t border-line pt-3", children: [_jsxs(Button, { size: "sm", variant: "ghost", loading: busy, onClick: () => revertSection(original), children: [_jsx(RotateCcw, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.section.revert")] }), _jsx("p", { className: "mt-1 text-xs text-ink-subtle", children: t("siteAdmin.section.revertHint") })] }))] })) }) }), _jsxs("section", { "aria-label": t("siteAdmin.preview.title"), className: "min-w-0 lg:col-start-2 lg:row-span-2 lg:row-start-1 xl:row-span-1", children: [_jsxs("div", { className: "mb-2 flex flex-wrap items-center justify-between gap-2", children: [_jsx("h3", { className: "text-xs font-semibold tracking-wide text-ink-muted uppercase", children: t("siteAdmin.preview.title") }), _jsx(DeviceToggle, { value: device, onChange: setDevice })] }), _jsx(PagePreview, { sections: preview, selected: selected, onSelect: setSelected, device: device, pagePath: page.path }), _jsx("p", { className: "mt-2 text-xs text-ink-subtle", children: t("siteAdmin.preview.hint") })] })] }), _jsx(SectionPicker, { open: picker, busy: busy, onClose: () => setPicker(false), onPick: add }), _jsx(PageSettings, { open: settings, page: page, overview: overview, onClose: () => setSettings(false), onDeleted: onBack }), _jsx(Confirm, { open: !!deleting, danger: true, loading: busy, title: t("siteAdmin.section.deleteTitle", { name: deleting ? t(`siteAdmin.section.${deleting.type}.label`) : "" }), message: deleting?.origin === "config" ? t("siteAdmin.section.deleteConfig") : t("siteAdmin.section.deleteAdmin"), confirmLabel: t("common.delete"), onClose: () => setDeleting(null), onConfirm: async () => {
|
|
251
|
+
const s = deleting;
|
|
252
|
+
const ok = await run(() => api(`/site/admin/sections/${s.id}`, { method: "DELETE" }), t("siteAdmin.section.deleted", { name: t(`siteAdmin.section.${s.type}.label`) }));
|
|
253
|
+
if (ok)
|
|
254
|
+
setDeleting(null);
|
|
255
|
+
} })] }));
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=page-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-editor.js","sourceRoot":"","sources":["../../../src/site/editor/page-editor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SitePageDetail } from "../types.js";
|
|
2
|
+
import { type SiteOverview } from "./api.js";
|
|
3
|
+
export declare function PageSettings({ open, page, overview, onClose, onDeleted }: {
|
|
4
|
+
open: boolean;
|
|
5
|
+
page: SitePageDetail;
|
|
6
|
+
overview: SiteOverview | undefined;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
onDeleted: () => void;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/*
|
|
4
|
+
* Page settings drawer: title, path, SEO (with length counters), menu placement, redirect, publish state,
|
|
5
|
+
* revert to the config version, delete (pages created in the admin only).
|
|
6
|
+
*/
|
|
7
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
8
|
+
import { RotateCcw, Trash2 } from "lucide-react";
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { useForge } from "../../context.js";
|
|
11
|
+
import { useToast } from "../../toast.js";
|
|
12
|
+
import { Alert, Button, Input, Label, Textarea } from "../../ui.js";
|
|
13
|
+
import { apiIssues, errorMessage, siteKeys, useInvalidateSite } from "./api.js";
|
|
14
|
+
import { issuesByField, navForm, navValue, pagePathIssue } from "./model.js";
|
|
15
|
+
import { ImageField } from "./prop-fields.js";
|
|
16
|
+
import { Confirm, Counter, Drawer, Switch } from "./widgets.js";
|
|
17
|
+
const formOf = (page) => ({
|
|
18
|
+
title: page.title,
|
|
19
|
+
path: page.path,
|
|
20
|
+
seoTitle: page.seo.title ?? "",
|
|
21
|
+
seoDescription: page.seo.description ?? "",
|
|
22
|
+
seoImage: page.seo.image ?? "",
|
|
23
|
+
redirect: page.redirect ?? "",
|
|
24
|
+
nav: navForm(page.nav),
|
|
25
|
+
});
|
|
26
|
+
export function PageSettings({ open, page, overview, onClose, onDeleted }) {
|
|
27
|
+
const { api, app, t, tv } = useForge();
|
|
28
|
+
const toast = useToast();
|
|
29
|
+
const qc = useQueryClient();
|
|
30
|
+
const invalidate = useInvalidateSite();
|
|
31
|
+
const [form, setForm] = useState(() => formOf(page));
|
|
32
|
+
const [loadedFor, setLoadedFor] = useState(null);
|
|
33
|
+
const [errors, setErrors] = useState({});
|
|
34
|
+
const [saving, setSaving] = useState(false);
|
|
35
|
+
const [confirm, setConfirm] = useState(null);
|
|
36
|
+
const [busy, setBusy] = useState(false);
|
|
37
|
+
// Fresh values each time the drawer opens.
|
|
38
|
+
const openKey = open ? `${page.id}:${page.updatedAt}` : null;
|
|
39
|
+
if (open && openKey !== loadedFor) {
|
|
40
|
+
setLoadedFor(openKey);
|
|
41
|
+
setForm(formOf(page));
|
|
42
|
+
setErrors({});
|
|
43
|
+
}
|
|
44
|
+
if (!open && loadedFor)
|
|
45
|
+
setLoadedFor(null);
|
|
46
|
+
const others = (overview?.pages ?? []).filter((p) => p.id !== page.id).map((p) => p.path);
|
|
47
|
+
const pathIssue = form.path !== page.path ? pagePathIssue(form.path, app, others) : null;
|
|
48
|
+
const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));
|
|
49
|
+
const save = async () => {
|
|
50
|
+
if (pathIssue || !form.title.trim())
|
|
51
|
+
return;
|
|
52
|
+
setSaving(true);
|
|
53
|
+
setErrors({});
|
|
54
|
+
try {
|
|
55
|
+
const seo = { ...(form.seoTitle.trim() ? { title: form.seoTitle.trim() } : {}), ...(form.seoDescription.trim() ? { description: form.seoDescription.trim() } : {}), ...(form.seoImage ? { image: form.seoImage } : {}) };
|
|
56
|
+
await api(`/site/admin/pages/${page.id}`, { method: "PATCH", body: JSON.stringify({ title: form.title.trim(), path: form.path, seo, nav: navValue(form.nav), redirect: form.redirect.trim() || null }) });
|
|
57
|
+
toast.success(t("siteAdmin.settings.saved"));
|
|
58
|
+
await qc.invalidateQueries({ queryKey: siteKeys.page(page.id) });
|
|
59
|
+
void invalidate("overview");
|
|
60
|
+
onClose();
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
const issues = apiIssues(e);
|
|
64
|
+
if (issues.length)
|
|
65
|
+
setErrors(issuesByField(issues));
|
|
66
|
+
else
|
|
67
|
+
toast.error(t("siteAdmin.save.error"), errorMessage(e));
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
setSaving(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const err = (k) => errors[k] ?? Object.entries(errors).find(([p]) => p.startsWith(`${k}.`))?.[1];
|
|
74
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Drawer, { open: open, onClose: onClose, title: t("siteAdmin.settings.title"), footer: _jsxs(_Fragment, { children: [_jsx(Button, { onClick: onClose, children: t("common.cancel") }), _jsx(Button, { variant: "primary", loading: saving, disabled: !!pathIssue || !form.title.trim(), onClick: save, children: t("common.save") })] }), children: [_jsxs("form", { className: "space-y-5", onSubmit: (e) => {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
void save();
|
|
77
|
+
}, children: [errors[""] && _jsx(Alert, { children: errors[""] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "page-title", required: true, children: t("siteAdmin.settings.pageTitle") }), _jsx(Input, { id: "page-title", value: form.title, maxLength: 120, "aria-invalid": err("title") || !form.title.trim() ? true : undefined, onChange: (e) => set("title", e.target.value) }), err("title") && _jsx("p", { className: "mt-1 text-xs text-danger", children: tv(err("title")) })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "page-path", required: true, children: t("siteAdmin.settings.path") }), _jsx(Input, { id: "page-path", className: "font-mono", value: form.path, disabled: page.path === "/", "aria-invalid": pathIssue || err("path") ? true : undefined, "aria-describedby": "page-path-help", onChange: (e) => set("path", e.target.value) }), _jsx("p", { id: "page-path-help", className: `mt-1 text-xs ${pathIssue || err("path") ? "text-danger" : "text-ink-muted"}`, children: pathIssue ? t(pathIssue.key, { segment: pathIssue.segment ?? "" }) : err("path") ? tv(err("path")) : page.path === "/" ? t("siteAdmin.settings.homePath") : t("siteAdmin.path.hint") })] }), _jsxs("fieldset", { className: "space-y-3", children: [_jsx("legend", { className: "mb-1 text-xs font-semibold tracking-wide text-ink-muted uppercase", children: t("siteAdmin.settings.seo") }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-end justify-between", children: [_jsx(Label, { htmlFor: "page-seo-title", children: t("siteAdmin.settings.seoTitle") }), _jsx("span", { className: "mb-1.5", children: _jsx(Counter, { value: form.seoTitle, max: 120, recommended: 60 }) })] }), _jsx(Input, { id: "page-seo-title", value: form.seoTitle, maxLength: 120, placeholder: form.title, onChange: (e) => set("seoTitle", e.target.value) })] }), _jsxs("div", { children: [_jsxs("div", { className: "flex items-end justify-between", children: [_jsx(Label, { htmlFor: "page-seo-description", children: t("siteAdmin.settings.seoDescription") }), _jsx("span", { className: "mb-1.5", children: _jsx(Counter, { value: form.seoDescription, max: 300, recommended: 160 }) })] }), _jsx(Textarea, { id: "page-seo-description", rows: 3, value: form.seoDescription, maxLength: 300, "aria-invalid": err("seo.description") ? true : undefined, onChange: (e) => set("seoDescription", e.target.value) }), _jsx("p", { className: "mt-1 text-xs text-ink-muted", children: err("seo.description") ? tv(err("seo.description")) : t("siteAdmin.settings.seoDescriptionHint") })] }), _jsx(ImageField, { a11y: { id: "page-seo-image", ...(err("seo.image") ? { "aria-invalid": true } : {}) }, label: t("siteAdmin.settings.seoImage"), error: err("seo.image"), value: form.seoImage, onChange: (v) => set("seoImage", v), storage: !!overview?.storage })] }), _jsxs("fieldset", { className: "space-y-3", children: [_jsx("legend", { className: "mb-1 text-xs font-semibold tracking-wide text-ink-muted uppercase", children: t("siteAdmin.settings.nav") }), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("label", { htmlFor: "page-nav-shown", className: "text-sm text-ink", children: t("siteAdmin.settings.navShown") }), _jsx(Switch, { id: "page-nav-shown", checked: !form.nav.hidden, onChange: (v) => set("nav", { ...form.nav, hidden: !v }) })] }), !form.nav.hidden && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "page-nav-group", children: t("siteAdmin.settings.navGroup") }), _jsx(Input, { id: "page-nav-group", value: form.nav.group, maxLength: 40, placeholder: t("siteAdmin.settings.navGroupPlaceholder"), onChange: (e) => set("nav", { ...form.nav, group: e.target.value }) })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "page-nav-label", children: t("siteAdmin.settings.navLabel") }), _jsx(Input, { id: "page-nav-label", value: form.nav.label, maxLength: 40, placeholder: form.title, onChange: (e) => set("nav", { ...form.nav, label: e.target.value }) })] })] }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-ink", children: [_jsx("input", { type: "checkbox", className: "forge-check size-4", checked: form.nav.footerOnly, onChange: (e) => set("nav", { ...form.nav, footerOnly: e.target.checked }) }), t("siteAdmin.settings.footerOnly")] })] })), err("nav") && _jsx("p", { className: "text-xs text-danger", children: tv(err("nav")) }), _jsx("p", { className: "text-xs text-ink-muted", children: t("siteAdmin.settings.navHint") })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "page-redirect", children: t("siteAdmin.settings.redirect") }), _jsx(Input, { id: "page-redirect", className: "font-mono", value: form.redirect, placeholder: "/sign-up", "aria-invalid": err("redirect") ? true : undefined, onChange: (e) => set("redirect", e.target.value) }), _jsx("p", { className: `mt-1 text-xs ${err("redirect") ? "text-danger" : "text-ink-muted"}`, children: err("redirect") ? tv(err("redirect")) : t("siteAdmin.settings.redirectHint") })] }), _jsx("button", { type: "submit", hidden: true })] }), (page.origin === "config" && (page.edited || page.conflict)) || page.origin === "admin" ? (_jsxs("div", { className: "mt-8 space-y-3 border-t border-line pt-5", children: [_jsx("h3", { className: "text-xs font-semibold tracking-wide text-ink-muted uppercase", children: t("siteAdmin.settings.more") }), page.origin === "config" && (page.edited || page.conflict) && (_jsxs("div", { children: [_jsxs(Button, { size: "sm", onClick: () => setConfirm("revert"), children: [_jsx(RotateCcw, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.revert")] }), _jsx("p", { className: "mt-1 text-xs text-ink-muted", children: t("siteAdmin.page.revertHint") })] })), page.origin === "admin" && (_jsxs(Button, { size: "sm", variant: "danger-ghost", onClick: () => setConfirm("delete"), children: [_jsx(Trash2, { className: "size-3.5", "aria-hidden": true }), " ", t("siteAdmin.page.delete")] }))] })) : (page.origin === "config" && _jsx("p", { className: "mt-8 border-t border-line pt-5 text-xs text-ink-muted", children: t("siteAdmin.page.configOnly", { key: page.key ?? "" }) }))] }), _jsx(Confirm, { open: confirm !== null, danger: confirm === "delete", loading: busy, title: confirm === "delete" ? t("siteAdmin.page.deleteTitle", { title: page.title }) : t("siteAdmin.page.revertTitle", { title: page.title }), message: confirm === "delete" ? t("siteAdmin.page.deleteMessage") : t("siteAdmin.page.revertMessage"), confirmLabel: confirm === "delete" ? t("common.delete") : t("siteAdmin.page.revert"), onClose: () => setConfirm(null), onConfirm: async () => {
|
|
78
|
+
setBusy(true);
|
|
79
|
+
try {
|
|
80
|
+
if (confirm === "delete") {
|
|
81
|
+
await api(`/site/admin/pages/${page.id}`, { method: "DELETE" });
|
|
82
|
+
toast.success(t("siteAdmin.page.deleted", { title: page.title }));
|
|
83
|
+
setConfirm(null);
|
|
84
|
+
onClose();
|
|
85
|
+
void invalidate("overview");
|
|
86
|
+
onDeleted();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
await api(`/site/admin/pages/${page.id}/revert`, { method: "POST" });
|
|
90
|
+
toast.success(t("siteAdmin.page.reverted"));
|
|
91
|
+
setConfirm(null);
|
|
92
|
+
onClose();
|
|
93
|
+
await qc.invalidateQueries({ queryKey: siteKeys.page(page.id) });
|
|
94
|
+
void invalidate("overview");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
toast.error(t("siteAdmin.error.action"), errorMessage(e));
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
setBusy(false);
|
|
102
|
+
}
|
|
103
|
+
} })] }));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=page-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-settings.js","sourceRoot":"","sources":["../../../src/site/editor/page-settings.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/*
|
|
4
|
+
* Pages of the website: title, path, status, origin and config conflicts; "New page" from a template.
|
|
5
|
+
*/
|
|
6
|
+
import { PAGE_TEMPLATES } from "@tekki-forge/compiler/site";
|
|
7
|
+
import { ArrowRight, CornerDownRight, FileText, Plus, TriangleAlert } from "lucide-react";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { useForge } from "../../context.js";
|
|
10
|
+
import { useToast } from "../../toast.js";
|
|
11
|
+
import { Button, Card, cn, EmptyState, Input, Label } from "../../ui.js";
|
|
12
|
+
import { apiIssues, errorMessage, useInvalidateSite } from "./api.js";
|
|
13
|
+
import { normalizePath, pagePathIssue, slugify } from "./model.js";
|
|
14
|
+
import { EditorDialog, Pill } from "./widgets.js";
|
|
15
|
+
export function PagesTab({ overview, onOpen }) {
|
|
16
|
+
const { api, t } = useForge();
|
|
17
|
+
const toast = useToast();
|
|
18
|
+
const invalidate = useInvalidateSite();
|
|
19
|
+
const [creating, setCreating] = useState(false);
|
|
20
|
+
const [busy, setBusy] = useState(null);
|
|
21
|
+
const pages = [...overview.pages].sort((a, b) => (a.path === "/" ? -1 : b.path === "/" ? 1 : a.path.localeCompare(b.path)));
|
|
22
|
+
const takeConfig = async (p) => {
|
|
23
|
+
setBusy(p.id);
|
|
24
|
+
try {
|
|
25
|
+
await api(`/site/admin/pages/${p.id}/revert`, { method: "POST" });
|
|
26
|
+
toast.success(t("siteAdmin.page.reverted"));
|
|
27
|
+
void invalidate();
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
toast.error(t("siteAdmin.error.action"), errorMessage(e));
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
setBusy(null);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm text-ink-muted", children: t("siteAdmin.pages.count", { count: pages.length }) }), _jsxs(Button, { variant: "primary", onClick: () => setCreating(true), children: [_jsx(Plus, { className: "size-4", "aria-hidden": true }), " ", t("siteAdmin.pages.new")] })] }), overview.conflicts > 0 && (_jsxs("div", { className: "forge-alert flex items-start gap-2 px-3 py-2 text-sm", "data-forge-alert": "info", role: "status", children: [_jsx(TriangleAlert, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": true }), " ", t("siteAdmin.pages.conflicts", { count: overview.conflicts })] })), _jsx(Card, { children: !pages.length ? (_jsx(EmptyState, { illustration: "list", title: t("siteAdmin.pages.empty"), description: t("siteAdmin.pages.emptyHint"), action: _jsx(Button, { variant: "primary", onClick: () => setCreating(true), children: t("siteAdmin.pages.new") }) })) : (_jsx("ul", { className: "divide-y divide-line", children: pages.map((p) => (_jsxs("li", { className: "flex flex-wrap items-center gap-x-4 gap-y-2 px-4 py-3", children: [_jsxs("button", { type: "button", onClick: () => onOpen(p.id), className: "forge-focusable group flex min-w-0 flex-1 items-center gap-3 rounded text-left", children: [_jsx("span", { className: "forge-badge flex size-9 shrink-0 items-center justify-center", "aria-hidden": true, children: p.redirect ? _jsx(CornerDownRight, { className: "size-4" }) : _jsx(FileText, { className: "size-4" }) }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate text-sm font-medium text-ink group-hover:underline", children: p.title }), _jsxs("span", { className: "block truncate font-mono text-xs text-ink-muted", children: [p.path, p.redirect && ` → ${p.redirect}`] })] })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx(Pill, { tone: p.status === "published" ? "success" : "muted", children: p.status === "published" ? t("siteAdmin.status.published") : t("siteAdmin.status.draft") }), _jsx(Pill, { tone: p.origin === "config" ? "info" : "muted", title: p.origin === "config" ? t("siteAdmin.origin.configHint") : undefined, children: p.origin === "config" ? t("siteAdmin.origin.config") : t("siteAdmin.origin.admin") }), p.edited && p.origin === "config" && _jsx(Pill, { tone: "muted", children: t("siteAdmin.origin.edited") }), !p.redirect && _jsx("span", { className: "text-xs text-ink-subtle", children: t("siteAdmin.pages.sections", { count: p.sections }) })] }), _jsxs(Button, { size: "sm", variant: "ghost", onClick: () => onOpen(p.id), "aria-label": t("siteAdmin.pages.editNamed", { title: p.title }), children: [t("common.edit"), " ", _jsx(ArrowRight, { className: "size-3.5", "aria-hidden": true })] }), (p.conflict || p.sectionConflicts > 0) && (_jsxs("div", { className: "forge-alert flex w-full flex-wrap items-center justify-between gap-2 px-3 py-2 text-xs", "data-forge-alert": "info", children: [_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(TriangleAlert, { className: "size-3.5 shrink-0", "aria-hidden": true }), p.conflict ? t("siteAdmin.conflict.page") : t("siteAdmin.conflict.sections", { count: p.sectionConflicts })] }), p.conflict ? (_jsx(Button, { size: "sm", loading: busy === p.id, onClick: () => takeConfig(p), children: t("siteAdmin.conflict.useConfig") })) : (_jsx(Button, { size: "sm", onClick: () => onOpen(p.id), children: t("siteAdmin.conflict.review") }))] }))] }, p.id))) })) }), _jsx(NewPageDialog, { open: creating, existing: pages.map((p) => p.path), onClose: () => setCreating(false), onCreated: (id) => {
|
|
37
|
+
setCreating(false);
|
|
38
|
+
void invalidate("overview");
|
|
39
|
+
onOpen(id);
|
|
40
|
+
} })] }));
|
|
41
|
+
}
|
|
42
|
+
function NewPageDialog({ open, existing, onClose, onCreated }) {
|
|
43
|
+
const { api, app, t, tv } = useForge();
|
|
44
|
+
const toast = useToast();
|
|
45
|
+
const [title, setTitle] = useState("");
|
|
46
|
+
const [path, setPath] = useState("");
|
|
47
|
+
const [pathEdited, setPathEdited] = useState(false);
|
|
48
|
+
const [template, setTemplate] = useState("blank");
|
|
49
|
+
const [touched, setTouched] = useState(false);
|
|
50
|
+
const [serverError, setServerError] = useState(null);
|
|
51
|
+
const [saving, setSaving] = useState(false);
|
|
52
|
+
const [wasOpen, setWasOpen] = useState(false);
|
|
53
|
+
if (open !== wasOpen) {
|
|
54
|
+
setWasOpen(open);
|
|
55
|
+
if (open) {
|
|
56
|
+
setTitle("");
|
|
57
|
+
setPath("");
|
|
58
|
+
setPathEdited(false);
|
|
59
|
+
setTemplate("blank");
|
|
60
|
+
setTouched(false);
|
|
61
|
+
setServerError(null);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const templates = PAGE_TEMPLATES.filter((x) => x.name !== "home" || !existing.includes("/"));
|
|
65
|
+
const issue = path ? pagePathIssue(path, app, existing) : null;
|
|
66
|
+
const pickTemplate = (name) => {
|
|
67
|
+
setTemplate(name);
|
|
68
|
+
const info = PAGE_TEMPLATES.find((x) => x.name === name);
|
|
69
|
+
if (!info)
|
|
70
|
+
return;
|
|
71
|
+
if (!title.trim() || PAGE_TEMPLATES.some((x) => t(`siteAdmin.template.${x.name}.label`) === title))
|
|
72
|
+
setTitle(t(`siteAdmin.template.${name}.label`));
|
|
73
|
+
if (!pathEdited)
|
|
74
|
+
setPath(info.path === "/page" ? (title ? normalizePath(slugify(title)) : "") : info.path);
|
|
75
|
+
};
|
|
76
|
+
const submit = async () => {
|
|
77
|
+
setTouched(true);
|
|
78
|
+
if (!title.trim() || !path || issue)
|
|
79
|
+
return;
|
|
80
|
+
setSaving(true);
|
|
81
|
+
setServerError(null);
|
|
82
|
+
try {
|
|
83
|
+
const page = await api("/site/admin/pages", { method: "POST", body: JSON.stringify({ title: title.trim(), path, template }) });
|
|
84
|
+
toast.success(t("siteAdmin.pages.created", { title: title.trim() }));
|
|
85
|
+
onCreated(page.id);
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
const issues = apiIssues(e);
|
|
89
|
+
setServerError(issues.length ? issues.map((i) => tv(i.message)).join(" · ") : errorMessage(e));
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
setSaving(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const pathMessage = issue ? t(issue.key, { segment: issue.segment ?? "" }) : touched && !path ? t("siteAdmin.path.required") : null;
|
|
96
|
+
return (_jsx(EditorDialog, { open: open, onClose: onClose, size: "xl", title: t("siteAdmin.pages.new"), footer: _jsxs(_Fragment, { children: [_jsx(Button, { onClick: onClose, children: t("common.cancel") }), _jsx(Button, { variant: "primary", loading: saving, onClick: submit, children: t("common.create") })] }), children: _jsxs("form", { className: "space-y-5", onSubmit: (e) => {
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
void submit();
|
|
99
|
+
}, children: [serverError && (_jsx("div", { className: "forge-alert px-3 py-2 text-sm", "data-forge-alert": "error", role: "alert", children: serverError })), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { children: [_jsx(Label, { htmlFor: "new-page-title", required: true, children: t("siteAdmin.settings.pageTitle") }), _jsx(Input, { id: "new-page-title", "data-autofocus": true, value: title, maxLength: 120, "aria-invalid": touched && !title.trim() ? true : undefined, onChange: (e) => {
|
|
100
|
+
setTitle(e.target.value);
|
|
101
|
+
if (!pathEdited && template === "blank")
|
|
102
|
+
setPath(e.target.value.trim() ? normalizePath(e.target.value) : "");
|
|
103
|
+
} }), touched && !title.trim() && _jsx("p", { className: "mt-1 text-xs text-danger", children: t("siteAdmin.form.required") })] }), _jsxs("div", { children: [_jsx(Label, { htmlFor: "new-page-path", required: true, children: t("siteAdmin.settings.path") }), _jsx(Input, { id: "new-page-path", className: "font-mono", value: path, placeholder: "/about", "aria-invalid": pathMessage ? true : undefined, "aria-describedby": "new-page-path-help", onChange: (e) => {
|
|
104
|
+
setPathEdited(true);
|
|
105
|
+
setPath(e.target.value);
|
|
106
|
+
}, onBlur: () => path && path !== "/" && setPath(normalizePath(path)) }), _jsx("p", { id: "new-page-path-help", "aria-live": "polite", className: cn("mt-1 text-xs", pathMessage ? "text-danger" : "text-ink-muted"), children: pathMessage ?? t("siteAdmin.path.hint") })] })] }), _jsxs("fieldset", { children: [_jsx("legend", { className: "mb-2 text-sm font-medium text-ink", children: t("siteAdmin.pages.template") }), _jsx("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-3", children: templates.map((tpl) => (_jsxs("label", { className: cn("forge-card flex cursor-pointer flex-col gap-0.5 p-3 has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-primary", template === tpl.name && "bg-selected ring-2 ring-primary"), children: [_jsx("input", { type: "radio", name: "new-page-template", value: tpl.name, checked: template === tpl.name, onChange: () => pickTemplate(tpl.name), className: "sr-only" }), _jsxs("span", { className: "flex items-center justify-between gap-2 text-sm font-medium text-ink", children: [t(`siteAdmin.template.${tpl.name}.label`), _jsx("span", { className: "font-mono text-xs font-normal text-ink-subtle", children: tpl.path })] }), _jsx("span", { className: "text-xs text-ink-muted", children: t(`siteAdmin.template.${tpl.name}.description`) })] }, tpl.name))) })] }), _jsx("button", { type: "submit", hidden: true })] }) }));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=pages-tab.js.map
|