153 lines
5.8 KiB
Plaintext
153 lines
5.8 KiB
Plaintext
-- allium: 1
|
|
-- bDS Template Editor View
|
|
-- Scope: UI content area — template editing surface
|
|
-- Distilled from: TemplateEditor.tsx
|
|
|
|
-- Describes the layout and behaviour of the template editor.
|
|
-- See template.allium for entity model and Liquid subset.
|
|
|
|
use "./template.allium" as template
|
|
use "./i18n.allium" as i18n
|
|
|
|
-- ─── Template editor view ─────────────────────────────────────
|
|
|
|
value TemplateEditorView {
|
|
template_id: String
|
|
title: String -- editable text input
|
|
slug: String -- editable text input, auto-generated from title
|
|
kind: String -- select: post | list | not_found | partial
|
|
enabled: Boolean -- checkbox
|
|
content: String -- code editor content
|
|
can_publish: Boolean -- true while status = draft
|
|
created_at: String -- locale-formatted date
|
|
updated_at: String -- locale-formatted date
|
|
}
|
|
|
|
surface TemplateEditorSurface {
|
|
context editor: TemplateEditorView
|
|
|
|
exposes:
|
|
editor.title
|
|
editor.slug
|
|
editor.kind
|
|
editor.enabled
|
|
editor.created_at
|
|
editor.updated_at
|
|
|
|
provides:
|
|
TemplateSaveRequested(editor.template_id)
|
|
TemplatePublishRequested(editor.template_id)
|
|
when editor.can_publish
|
|
TemplateValidateRequested(editor.template_id)
|
|
TemplateDeleteRequested(editor.template_id)
|
|
TemplateDeleteConfirmed(editor.template_id)
|
|
TemplateForceDeleteConfirmed(editor.template_id)
|
|
|
|
@guarantee HeaderLayout
|
|
-- Header bar with template title tab.
|
|
-- Actions (right side): Save button, Publish button (shown only when
|
|
-- can_publish, i.e. status = draft), Validate button,
|
|
-- Delete button (danger style).
|
|
|
|
@guarantee MetadataRow
|
|
-- Two rows of metadata fields above the editor.
|
|
-- Row 1: Title (text input), Slug (text input, auto-generated from title).
|
|
-- Row 2: Kind (select: post/list/not-found/partial), Enabled (checkbox).
|
|
|
|
@guarantee EditorBody
|
|
-- Code editor with HTML/Liquid syntax highlighting.
|
|
-- Toolbar: "Content" label.
|
|
-- Syntax errors shown inline in editor on validation.
|
|
|
|
@guarantee FooterLayout
|
|
-- Created date and Updated date, locale-formatted.
|
|
}
|
|
|
|
-- ─── Template editor actions ────────────────────────────────
|
|
|
|
rule TemplateSave {
|
|
when: TemplateSaveRequested(template_id)
|
|
let target = template/Template{id: template_id}
|
|
let validation = ValidateLiquid(editor_content(template_id))
|
|
-- editor_content: the current code editor buffer
|
|
ensures:
|
|
if validation = valid:
|
|
UpdateTemplateRequested(target, editor_field_changes(template_id))
|
|
-- Version bump + DB write + .liquid rewrite:
|
|
-- template.allium UpdateTemplate,
|
|
-- engine_side_effects.allium UpdateTemplateSideEffects
|
|
else:
|
|
TemplateValidationErrorsShown(template_id, validation)
|
|
-- Save blocked; errors shown inline in the editor
|
|
}
|
|
|
|
rule TemplatePublish {
|
|
when: TemplatePublishRequested(template_id)
|
|
let target = template/Template{id: template_id}
|
|
requires: target.status = draft
|
|
-- can_publish gate on the button
|
|
let validation = ValidateLiquid(editor_content(template_id))
|
|
ensures:
|
|
if validation = valid:
|
|
UpdateTemplateRequested(target, editor_field_changes(template_id))
|
|
PublishTemplateRequested(target)
|
|
-- status -> published + .liquid file write:
|
|
-- template.allium PublishTemplate
|
|
else:
|
|
TemplateValidationErrorsShown(template_id, validation)
|
|
}
|
|
|
|
rule TemplateValidate {
|
|
when: TemplateValidateRequested(template_id)
|
|
-- Validation only, never saves
|
|
let validation = ValidateLiquid(editor_content(template_id))
|
|
ensures:
|
|
if validation = valid:
|
|
TemplateValidationOkShown(template_id)
|
|
-- toast / status indicator
|
|
else:
|
|
TemplateValidationErrorsShown(template_id, validation)
|
|
}
|
|
|
|
rule TemplateDelete {
|
|
when: TemplateDeleteRequested(template_id)
|
|
let target = template/Template{id: template_id}
|
|
let references = target.referencing_posts.count + target.referencing_tags.count
|
|
ensures:
|
|
if references > 0:
|
|
TemplateForceDeleteConfirmShown(template_id)
|
|
-- system confirm dialog: "This template is used by N posts
|
|
-- and M tags. Force delete?" (action_patterns.allium
|
|
-- confirmation_assignments: template_delete_with_references)
|
|
else:
|
|
ConfirmDeleteModalOpened(template_id)
|
|
-- custom modal (not a native dialog): template title, no
|
|
-- reference list; Cancel + Delete (destructive red style)
|
|
-- — action_patterns.allium
|
|
-- confirmation_assignments: template_delete
|
|
}
|
|
|
|
rule TemplateDeleteExecute {
|
|
when: TemplateDeleteConfirmed(template_id)
|
|
let target = template/Template{id: template_id}
|
|
ensures: DeleteTemplateRequested(target)
|
|
-- DB record + .liquid file on disk
|
|
ensures: closeTab(template_id)
|
|
-- sidebar removes the item reactively
|
|
}
|
|
|
|
rule TemplateForceDelete {
|
|
when: TemplateForceDeleteConfirmed(template_id)
|
|
let target = template/Template{id: template_id}
|
|
-- Clear references first so template.allium DeleteTemplate's
|
|
-- zero-reference precondition holds:
|
|
for p in target.referencing_posts:
|
|
ensures: p.template_slug = null
|
|
for t in target.referencing_tags:
|
|
ensures: t.post_template_slug = null
|
|
ensures: DeleteTemplateRequested(target)
|
|
-- DB record + .liquid file on disk
|
|
ensures: closeTab(template_id)
|
|
-- sidebar removes the item reactively
|
|
}
|