Editor: one enabled field for pages and elements, shown under Access #170

Closed
opened 2026-10-08 21:46:14 +02:00 by dominik.polakovics · 0 comments

Parent

#168 — the editing screens overhaul, Direction A (page module). Mockup and decision log: docs/mockups/editing-screens/ (README items 3 and 9), merged in #169.

Summary

Pages and elements get one editor-facing field, enabled, shown as a switch in an Access group of the page properties form and of every element form (and on item rows). Every place the editor shows or toggles the state (badges, tree, Enable/Disable actions, the disabled-page banner) reads that one field. This is the only part of the overhaul that touches the engine and the scaffold contract, so it lands alone and first.

Current behavior

  • Elements: the harness-managed reserved shortcode param disabled (internal/element, ReservedParamDisabled) marks a disabled element; the forms API (web/src/api/forms.ts, ItemsRow.disabled) and the page-elements payload (web/src/api/pageedit.ts) expose it as disabled: boolean. The UI offers Enable/Disable in the row menu and on the edit page; the form itself has no field for it.
  • Pages: the front-matter draft flag is the disabled marker (internal/pageops/draft.go, SetDraft; POST /api/page/draft in web/src/api/pagemanage.ts). Every new page is born a draft; the content root cannot be drafted; a category has no Enable/Disable. The tree marks drafted pages, the page docheader has Enable/Disable in its ⋯ menu, and the page settings form has no field for it. Modules filter status as enabled/disabled.
  • scaffold/site/AGENTS.md reserves uid and disabled as param names and documents status as "the disabled marker, front-matter draft".

Desired behavior

  • The server-described forms (POST /api/form, FormDescription) for kind: "properties" and kind: "element" include a boolean field named enabled, grouped under Access, after the sidecar's own fields. Item rows expose enabled instead of disabled.
  • The page properties Access group shows Enabled (on: "Page is built and reachable"; off: "Page is not built. Links to it are reported before publishing.") next to the page type's own fields that belong there (the scaffold hidden field stays a page-type field and is unchanged). On the content root the switch is shown but not operable, with the existing reason; a category's form has no Enabled field.
  • Every element form's Access group shows Enabled (on: "Shown on the site"; off: "Kept in the file, not shown on the site") beside the read-only anchor (#<uid>).
  • Saving a form with enabled changed has the same effect as today's Enable/Disable actions. Those actions stay (row menu, docheader) and the disabled-page banner's Enable page button (built in the page-module issue) uses the same operation.
  • A page or element with enabled: false shows a Disabled badge next to the publish badge; the tree shows the page with an eye-off icon and struck-through title; an element card shows the Disabled badge and an eye-off icon. All derive from the one field.
  • Declaring a param named enabled in an element sidecar is a load error, exactly like uid and disabled today.
  • Every API payload and form value the browser handles uses enabled; disabled no longer appears in the frontend types. Route names are the implementer's call.

Decisions

  • The field is enabled, a switch, under Access, on both pages and elements — the maintainer's call (mockup README item 3): one positive word, one place, same on both record kinds, as TYPO3 does with "Enabled" under Access.
  • Storage does not change. Pages keep Hugo's front-matter draft; elements keep the harness-managed disabled shortcode param, written only when the element is disabled. Reason: the content must stay vanilla Hugo (draft is how stock hugo excludes a page) and enabled entries must stay byte-identical so saves produce quiet diffs (web/src/api/pageedit.ts documents that contract). enabled is the editor's name for the state; draft/disabled are its on-disk encodings.
  • enabled joins the reserved param names so a sidecar cannot declare a param that collides with the form's own field.
  • Existing rules stand: the content root cannot be disabled; categories have no Enabled field; new pages are born disabled (draft: true) so an unfinished page never ships by accident.

Key interfaces

  • FormDescription / FormField (web/src/api/forms.ts, web/src/widgets/types) and their server side (internal/element/form.go, the properties/create form description) — grow the enabled field and whatever grouping the description carries; ItemsRow.disabled → enabled.
  • internal/element ReservedParamDisabled, values.go (managed keys ignored on write), schema.go (load error for reserved names) — add enabled to the reserved set; keep disabled as the written key.
  • internal/pageops/draft.go SetDraft and the handler behind POST /api/page/draft; the page settings save path (web/src/api/pagesettings.ts, its server handler) must accept enabled as part of the properties form.
  • DocumentNode / page-elements payload (web/src/api/pageedit.ts): the per-element flag the tree and cards read.
  • Tree payload (web/src/api/tree.ts, internal/pagetree): the per-page flag.
  • scaffold/site/AGENTS.md: reserved param names; the Access group on forms; the status built-in wording. internal/element/agentsdoc_test.go is the drift test.

Acceptance criteria

  • POST /api/form for a page's properties returns an enabled boolean field grouped under Access; for the content root it is marked not operable; for a category it is absent.
  • POST /api/form for a block element and each of its item rows returns enabled; no payload or frontend type the browser uses carries disabled any more.
  • Saving page properties with enabled: false writes draft: true to the page's front matter; saving with enabled: true removes/clears it; the file is otherwise unchanged.
  • Saving an element form with enabled: false writes the disabled shortcode param; saving with enabled: true leaves no disabled key, and the content file is byte-identical to one saved by today's editor for an enabled element.
  • A sidecar declaring a param named enabled fails to load with an error naming the reserved param, like uid and disabled.
  • Page docheader, tree node, element card and element docheader show the Disabled state from the one field; Enable/Disable actions and the Enabled switch agree after either is used.
  • scaffold/site/AGENTS.md documents the enabled field, the Access group, and the reserved name; the drift test passes.

How to verify

  • make test (web vitest + go test ./...), including internal/element/agentsdoc_test.go.
  • make run on testdata/site: open a page's Properties, flip Enabled, save, inspect the markdown front matter; open an element, flip Enabled on the Access tab, save, git diff shows only the disabled param appearing/disappearing.
  • Add a sidecar param named enabled to a testdata element: harness serve reports the load error.

Assumptions to check

  • Whether FormDescription already has a notion of field groups/tabs; if not, the field needs a place in the description that the form screen issue can later map to tabs (a group or tab marker on FormField is enough).
  • Whether the theme or any shortcode template reads the disabled param directly (scaffold/site/..., testdata/): storage is unchanged, so they keep working, but confirm nothing reads enabled.
  • Whether POST /api/page/draft is used by the hosted header or another client (deckle-hosted import) before renaming or replacing it.

Out of scope

  • The new page-module screen, insert dialog, drag and drop, clipboard (next issue).
  • The form screen rebuild with tabs and validation at rest (third issue). This issue only adds the field to the server-described forms and to the existing forms' rendering.
  • Renaming the on-disk markers (draft, disabled).
  • The page type's hidden/footer navigation flags.

Blocked by

None - can start immediately

## Parent #168 — the editing screens overhaul, Direction A (page module). Mockup and decision log: `docs/mockups/editing-screens/` (README items 3 and 9), merged in #169. ## Summary Pages and elements get one editor-facing field, `enabled`, shown as a switch in an **Access** group of the page properties form and of every element form (and on item rows). Every place the editor shows or toggles the state (badges, tree, Enable/Disable actions, the disabled-page banner) reads that one field. This is the only part of the overhaul that touches the engine and the scaffold contract, so it lands alone and first. ## Current behavior - Elements: the harness-managed reserved shortcode param `disabled` (`internal/element`, `ReservedParamDisabled`) marks a disabled element; the forms API (`web/src/api/forms.ts`, `ItemsRow.disabled`) and the page-elements payload (`web/src/api/pageedit.ts`) expose it as `disabled: boolean`. The UI offers Enable/Disable in the row menu and on the edit page; the form itself has no field for it. - Pages: the front-matter `draft` flag is the disabled marker (`internal/pageops/draft.go`, `SetDraft`; `POST /api/page/draft` in `web/src/api/pagemanage.ts`). Every new page is born a draft; the content root cannot be drafted; a category has no Enable/Disable. The tree marks drafted pages, the page docheader has Enable/Disable in its ⋯ menu, and the page settings form has no field for it. Modules filter `status` as enabled/disabled. - `scaffold/site/AGENTS.md` reserves `uid` and `disabled` as param names and documents `status` as "the disabled marker, front-matter `draft`". ## Desired behavior - The server-described forms (`POST /api/form`, `FormDescription`) for `kind: "properties"` and `kind: "element"` include a boolean field named `enabled`, grouped under **Access**, after the sidecar's own fields. Item rows expose `enabled` instead of `disabled`. - The page properties Access group shows **Enabled** (on: "Page is built and reachable"; off: "Page is not built. Links to it are reported before publishing.") next to the page type's own fields that belong there (the scaffold `hidden` field stays a page-type field and is unchanged). On the content root the switch is shown but not operable, with the existing reason; a category's form has no Enabled field. - Every element form's Access group shows **Enabled** (on: "Shown on the site"; off: "Kept in the file, not shown on the site") beside the read-only anchor (`#<uid>`). - Saving a form with `enabled` changed has the same effect as today's Enable/Disable actions. Those actions stay (row menu, docheader) and the disabled-page banner's **Enable page** button (built in the page-module issue) uses the same operation. - A page or element with `enabled: false` shows a **Disabled** badge next to the publish badge; the tree shows the page with an eye-off icon and struck-through title; an element card shows the Disabled badge and an eye-off icon. All derive from the one field. - Declaring a param named `enabled` in an element sidecar is a load error, exactly like `uid` and `disabled` today. - Every API payload and form value the browser handles uses `enabled`; `disabled` no longer appears in the frontend types. Route names are the implementer's call. ## Decisions - **The field is `enabled`, a switch, under Access, on both pages and elements** — the maintainer's call (mockup README item 3): one positive word, one place, same on both record kinds, as TYPO3 does with "Enabled" under Access. - **Storage does not change.** Pages keep Hugo's front-matter `draft`; elements keep the harness-managed `disabled` shortcode param, written only when the element is disabled. Reason: the content must stay vanilla Hugo (`draft` is how stock `hugo` excludes a page) and enabled entries must stay byte-identical so saves produce quiet diffs (`web/src/api/pageedit.ts` documents that contract). `enabled` is the editor's name for the state; `draft`/`disabled` are its on-disk encodings. - **`enabled` joins the reserved param names** so a sidecar cannot declare a param that collides with the form's own field. - **Existing rules stand**: the content root cannot be disabled; categories have no Enabled field; new pages are born disabled (`draft: true`) so an unfinished page never ships by accident. ## Key interfaces - `FormDescription` / `FormField` (`web/src/api/forms.ts`, `web/src/widgets/types`) and their server side (`internal/element/form.go`, the properties/create form description) — grow the `enabled` field and whatever grouping the description carries; `ItemsRow.disabled` → `enabled`. - `internal/element` `ReservedParamDisabled`, `values.go` (managed keys ignored on write), `schema.go` (load error for reserved names) — add `enabled` to the reserved set; keep `disabled` as the written key. - `internal/pageops/draft.go` `SetDraft` and the handler behind `POST /api/page/draft`; the page settings save path (`web/src/api/pagesettings.ts`, its server handler) must accept `enabled` as part of the properties form. - `DocumentNode` / page-elements payload (`web/src/api/pageedit.ts`): the per-element flag the tree and cards read. - Tree payload (`web/src/api/tree.ts`, `internal/pagetree`): the per-page flag. - `scaffold/site/AGENTS.md`: reserved param names; the Access group on forms; the `status` built-in wording. `internal/element/agentsdoc_test.go` is the drift test. ## Acceptance criteria - [ ] `POST /api/form` for a page's properties returns an `enabled` boolean field grouped under Access; for the content root it is marked not operable; for a category it is absent. - [ ] `POST /api/form` for a block element and each of its item rows returns `enabled`; no payload or frontend type the browser uses carries `disabled` any more. - [ ] Saving page properties with `enabled: false` writes `draft: true` to the page's front matter; saving with `enabled: true` removes/clears it; the file is otherwise unchanged. - [ ] Saving an element form with `enabled: false` writes the `disabled` shortcode param; saving with `enabled: true` leaves no `disabled` key, and the content file is byte-identical to one saved by today's editor for an enabled element. - [ ] A sidecar declaring a param named `enabled` fails to load with an error naming the reserved param, like `uid` and `disabled`. - [ ] Page docheader, tree node, element card and element docheader show the Disabled state from the one field; Enable/Disable actions and the Enabled switch agree after either is used. - [ ] `scaffold/site/AGENTS.md` documents the `enabled` field, the Access group, and the reserved name; the drift test passes. ## How to verify - `make test` (web vitest + `go test ./...`), including `internal/element/agentsdoc_test.go`. - `make run` on `testdata/site`: open a page's Properties, flip Enabled, save, inspect the markdown front matter; open an element, flip Enabled on the Access tab, save, `git diff` shows only the `disabled` param appearing/disappearing. - Add a sidecar param named `enabled` to a testdata element: `harness serve` reports the load error. ## Assumptions to check - Whether `FormDescription` already has a notion of field groups/tabs; if not, the field needs a place in the description that the form screen issue can later map to tabs (a `group` or `tab` marker on `FormField` is enough). - Whether the theme or any shortcode template reads the `disabled` param directly (`scaffold/site/...`, `testdata/`): storage is unchanged, so they keep working, but confirm nothing reads `enabled`. - Whether `POST /api/page/draft` is used by the hosted header or another client (`deckle-hosted` import) before renaming or replacing it. ## Out of scope - The new page-module screen, insert dialog, drag and drop, clipboard (next issue). - The form screen rebuild with tabs and validation at rest (third issue). This issue only adds the field to the server-described forms and to the existing forms' rendering. - Renaming the on-disk markers (`draft`, `disabled`). - The page type's `hidden`/`footer` navigation flags. ## Blocked by None - can start immediately
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#170
No description provided.