From fe23b6a91bc34a2965ae1ceea9751267fe1489ef Mon Sep 17 00:00:00 2001 From: corsacca Date: Thu, 23 Apr 2026 12:01:17 +0100 Subject: [PATCH] CMS page layout and saving changes --- app/pages/admin/pages/[id].vue | 370 +++++++++++++++++---------------- 1 file changed, 196 insertions(+), 174 deletions(-) diff --git a/app/pages/admin/pages/[id].vue b/app/pages/admin/pages/[id].vue index d8d41411..d5e64b74 100644 --- a/app/pages/admin/pages/[id].vue +++ b/app/pages/admin/pages/[id].vue @@ -51,6 +51,18 @@ const toast = useToast() const pageId = computed(() => String(route.params.id)) +// Live public URL for the "View page" link in the Publish card. Uses the +// committed slug (data) not the in-flight slug ref, so the link always +// points to an existing route even if the author is editing the slug. +// English is the default locale, so `prefix_except_default` means no prefix. +const publicUrl = computed(() => { + const committedSlug = data.value?.page.slug + if (!committedSlug) return null + return activeLocale.value === 'en' + ? `/${committedSlug}` + : `/${activeLocale.value}/${committedSlug}` +}) + const EMPTY_DOC = { type: 'doc', content: [{ type: 'paragraph' }] } const { data, pending, refresh } = await useFetch(() => `/api/admin/pages/${pageId.value}`) @@ -152,9 +164,19 @@ for (const l of ENABLED_LANGUAGES) { watch(() => forms[l.code]?.body_json, () => markDirty(l.code), { deep: true }) } -const savingMeta = ref(false) -async function saveMetadata() { - savingMeta.value = true +// Single save action: page-level metadata (PATCH /pages/:id) + the +// active locale's translation (PUT /translations/:locale) in one click. +// Passing a statusOverride also flips published/draft on the translation. +const saving = ref(false) +async function saveAll(statusOverride?: 'draft' | 'published') { + const locale = activeLocale.value + const f = forms[locale] + if (!f) return + if (!f.title.trim()) { + toast.add({ title: 'Title is required', color: 'error' }) + return + } + saving.value = true try { await $fetch(`/api/admin/pages/${pageId.value}`, { method: 'PATCH', @@ -166,29 +188,7 @@ async function saveMetadata() { custom_css: customCss.value.trim() ? customCss.value : null } }) - toast.add({ title: 'Page metadata saved', color: 'success' }) - await refresh() - } catch (e: any) { - toast.add({ - title: 'Could not save metadata', - description: e?.data?.statusMessage || e?.message, - color: 'error' - }) - } finally { - savingMeta.value = false - } -} -const savingTranslation = ref(false) -async function saveTranslation(locale: string, statusOverride?: 'draft' | 'published') { - const f = forms[locale] - if (!f) return - if (!f.title.trim()) { - toast.add({ title: 'Title is required', color: 'error' }) - return - } - savingTranslation.value = true - try { const body: Record = { title: f.title, body_json: f.body_json, @@ -207,7 +207,13 @@ async function saveTranslation(locale: string, statusOverride?: 'draft' | 'publi if (statusOverride) f.status = statusOverride f.loaded = true f.dirty = false - toast.add({ title: `Saved ${locale}`, color: 'success' }) + + const verb = statusOverride === 'published' + ? 'Published' + : statusOverride === 'draft' + ? 'Unpublished' + : 'Saved' + toast.add({ title: `${verb} ${locale}`, color: 'success' }) await refresh() } catch (e: any) { toast.add({ @@ -216,33 +222,7 @@ async function saveTranslation(locale: string, statusOverride?: 'draft' | 'publi color: 'error' }) } finally { - savingTranslation.value = false - } -} - -async function setStatus(locale: string, status: 'draft' | 'published') { - const f = forms[locale] - if (!f) return - if (f.dirty) { - // Save current content along with the publish action so published - // state never diverges from the draft the editor is looking at - await saveTranslation(locale, status) - return - } - try { - await $fetch(`/api/admin/pages/${pageId.value}/publish`, { - method: 'POST', - body: { locale, status } - }) - f.status = status - toast.add({ title: status === 'published' ? 'Published' : 'Unpublished', color: 'success' }) - await refresh() - } catch (e: any) { - toast.add({ - title: 'Status change failed', - description: e?.data?.statusMessage || e?.message, - color: 'error' - }) + saving.value = false } } @@ -351,38 +331,9 @@ const enabledLanguages = ENABLED_LANGUAGES