feat(editor): one enabled field for pages and elements, under Access #173

Merged
dominik.polakovics merged 2 commits from afk/170 into main 2026-10-08 23:12:06 +02:00

Closes #170

What

Pages and elements get one editor-facing boolean, enabled, shown as an Enabled switch in an Access group of the server-described forms. Badges, tree, Enable/Disable actions all read that one field. On-disk storage is unchanged: pages keep front-matter draft, elements keep the harness-managed disabled shortcode param, written only while disabled.

Engine / server

  • FormField gains group ("access"), readOnly, note; new switch widget (settings {on, off} hints).
  • POST /api/form: properties forms end with the Enabled field (read-only with a note on the content root, absent on categories); element forms end with it too; item rows are {uid, enabled, fields}. /api/form/check validates enabled through the same code path as the saves.
  • POST /api/page/save (values.enabled, items rows' enabled) and POST /api/page/settings/save (values.enabled → draft, in the same single write; no change when the state is unchanged). An enabled element saves byte-identical.
  • POST /api/page/draft {draft} → POST /api/page/enabled {enabled} (the hosted product does not call it). GET /api/tree nodes and module entries carry enabled instead of draft.
  • enabled is a reserved element param name and a reserved page-type field name (load error naming it).

Theme

Previously only item templates (card, img) honored disabled. Now that any block element can be switched off, every element shortcode renders nothing when disabled is true/"true", through one shared partials/ce/disabled.html check (testdata/site templates inline it). Covered by a real-Hugo test (internal/theme/disabled_test.go).

Frontend

Switch widget; Access group (element forms also show the read-only #<uid> anchor); enabled throughout the API types (the page tree is normalized once at the API boundary); Disabled badge on the page docheader, element card (with eye-off icon) and element docheader; tree shows eye-off + struck-through title. Enable/Disable actions and the switch stay in agreement (an open, clean properties form follows the tree's state).

Docs

scaffold/site/AGENTS.md documents the Enabled field, the Access group, the reserved enabled name and the template contract for disabled; the drift test now checks enabled. README wire docs updated.

Verification

  • npm test (2056 passing), tsc --noEmit, npm run build, go vet ./..., go test ./... (with Hugo on PATH) are all green.
  • Smoke test against harness serve on a copy of testdata/site:
    • Properties form returns the Enabled field, and it is read-only with a note on _index.md.
    • Saving with enabled:false writes draft = true; saving with true writes draft = false.
    • The element form's Enabled switch adds and then removes only disabled=true, leaving the file byte-identical to the original.
    • A sidecar param named enabled is reported as a load error.

Notes

  • The settings save re-quotes the title ('…' → "…"). Main does the same, so this PR did not introduce it.
  • The form-screen tabs, the disabled-page banner and the page-module screen are out of scope (follow-up issues). togglePageEnabled / setPageEnabled are plain operations the banner can reuse.

🤖 Generated with Claude Code

Closes #170 ## What Pages and elements get one editor-facing boolean, `enabled`, shown as an **Enabled** switch in an **Access** group of the server-described forms. Badges, tree, Enable/Disable actions all read that one field. On-disk storage is unchanged: pages keep front-matter `draft`, elements keep the harness-managed `disabled` shortcode param, written only while disabled. ### Engine / server - `FormField` gains `group` (`"access"`), `readOnly`, `note`; new `switch` widget (settings `{on, off}` hints). - `POST /api/form`: properties forms end with the Enabled field (read-only with a note on the content root, absent on categories); element forms end with it too; item rows are `{uid, enabled, fields}`. `/api/form/check` validates `enabled` through the same code path as the saves. - `POST /api/page/save` (`values.enabled`, items rows' `enabled`) and `POST /api/page/settings/save` (`values.enabled` → `draft`, in the same single write; no change when the state is unchanged). An enabled element saves byte-identical. - `POST /api/page/draft {draft}` → `POST /api/page/enabled {enabled}` (the hosted product does not call it). `GET /api/tree` nodes and module entries carry `enabled` instead of `draft`. - `enabled` is a reserved element param name and a reserved page-type field name (load error naming it). ### Theme Previously only item templates (`card`, `img`) honored `disabled`. Now that any block element can be switched off, every element shortcode renders nothing when `disabled` is `true`/`"true"`, through one shared `partials/ce/disabled.html` check (testdata/site templates inline it). Covered by a real-Hugo test (`internal/theme/disabled_test.go`). ### Frontend Switch widget; Access group (element forms also show the read-only `#<uid>` anchor); `enabled` throughout the API types (the page tree is normalized once at the API boundary); **Disabled** badge on the page docheader, element card (with eye-off icon) and element docheader; tree shows eye-off + struck-through title. Enable/Disable actions and the switch stay in agreement (an open, clean properties form follows the tree's state). ### Docs `scaffold/site/AGENTS.md` documents the Enabled field, the Access group, the reserved `enabled` name and the template contract for `disabled`; the drift test now checks `enabled`. README wire docs updated. ## Verification - `npm test` (2056 passing), `tsc --noEmit`, `npm run build`, `go vet ./...`, `go test ./...` (with Hugo on PATH) are all green. - Smoke test against `harness serve` on a copy of `testdata/site`: - Properties form returns the Enabled field, and it is read-only with a note on `_index.md`. - Saving with `enabled:false` writes `draft = true`; saving with `true` writes `draft = false`. - The element form's Enabled switch adds and then removes only `disabled=true`, leaving the file byte-identical to the original. - A sidecar param named `enabled` is reported as a load error. ## Notes - The settings save re-quotes the title (`'…'` → `"…"`). Main does the same, so this PR did not introduce it. - The form-screen tabs, the disabled-page banner and the page-module screen are out of scope (follow-up issues). `togglePageEnabled` / `setPageEnabled` are plain operations the banner can reuse. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(editor): one enabled field for pages and elements, under Access
All checks were successful
ci / build-and-test (pull_request) Successful in 11m21s
9eb0cbb03d
Pages and elements get one editor-facing boolean, `enabled`, shown as a
switch in an Access group of the server-described forms. Storage is
unchanged: pages keep front-matter `draft`, elements the harness-managed
`disabled` shortcode param, written only while disabled.

Engine and server:
- FormField gains group/readOnly/note; new `switch` widget; the Enabled
  field is appended to properties forms (read-only on the content root,
  absent on categories) and element forms; item rows carry `enabled`.
- /api/page/save, items rows and /api/page/settings/save accept
  `enabled`; an enabled element saves byte-identical.
- POST /api/page/draft becomes POST /api/page/enabled; tree and module
  payloads carry `enabled` instead of `draft`.
- `enabled` is a reserved element param and page-type field name.

Theme: every element shortcode renders nothing when disabled (shared
ce/disabled.html check), so any block element can be switched off.

Frontend: switch widget, Access group (with the element's #uid anchor),
`enabled` throughout the API types, Disabled badges on the page
docheader, element card and element docheader, eye-off + strike-through
in the tree; Enable/Disable actions and the switch stay in agreement.

AGENTS.md documents the Enabled field, the Access group, the reserved
name and the template contract; the drift test checks `enabled`.

Closes #170

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

[autoland] verdict: pass

This was generated by AI while landing a PR.

Validated — CONCERNS (non-blocking).

Signal relied on: Forgejo Actions ci / build-and-test green on the head (npm build + test, go vet, go test with Hugo 0.163.3 on PATH, go build). It covers both the frontend and the Go/Hugo paths this diff touches, so nothing was re-run. The head merges cleanly into main.

Conventions: Conventional Commits title; Closes #170 present; scaffold/site/AGENTS.md updated in the same change (Enabled field, Access group, reserved enabled, template contract for disabled); the drift test covers enabled.

Diff vs #170: every acceptance criterion is met.

  • Properties form: Enabled in the access group, read-only with a note on the content root, absent on categories.
  • Element form and item rows carry enabled; disabled is gone from the frontend types.
  • On disk: draft and the disabled param are written only on change, and an enabled element saves byte-identical.
  • enabled is a reserved param and page-type field name.
  • Badges, tree, docheader and the clean properties form all read one field.
  • /api/page/draft was renamed to /api/page/enabled. Checked: the hosted product does not call it and does not read the tree/modules draft field.

The theme change (every shortcode honors disabled through partials/ce/disabled.html) is required for scope: before this, only item rows could be disabled and only card/img honored it. Without it the new "Kept in the file, not shown on the site" hint would be false. A real-Hugo test covers it.

CONCERN (non-blocking): scaffold/themes/deckle/README.md:126-135 ("The reserved disabled param") is now stale. It still says only a collection row's eye toggle stamps disabled, that only item-element templates must honor it, and it shows the old inline check. Every element template must now honor it, through ce/disabled.html. A theme author who follows the README would ship block templates that ignore the Enabled switch. Suggested follow-up: a small docs fix.

[autoland] verdict: pass > *This was generated by AI while landing a PR.* **Validated — CONCERNS (non-blocking).** **Signal relied on:** Forgejo Actions `ci / build-and-test` green on the head (npm build + test, go vet, go test with Hugo 0.163.3 on PATH, go build). It covers both the frontend and the Go/Hugo paths this diff touches, so nothing was re-run. The head merges cleanly into main. **Conventions:** Conventional Commits title; `Closes #170` present; `scaffold/site/AGENTS.md` updated in the same change (Enabled field, Access group, reserved `enabled`, template contract for `disabled`); the drift test covers `enabled`. **Diff vs #170:** every acceptance criterion is met. - Properties form: Enabled in the access group, read-only with a note on the content root, absent on categories. - Element form and item rows carry `enabled`; `disabled` is gone from the frontend types. - On disk: `draft` and the `disabled` param are written only on change, and an enabled element saves byte-identical. - `enabled` is a reserved param and page-type field name. - Badges, tree, docheader and the clean properties form all read one field. - `/api/page/draft` was renamed to `/api/page/enabled`. Checked: the hosted product does not call it and does not read the tree/modules `draft` field. The theme change (every shortcode honors `disabled` through `partials/ce/disabled.html`) is required for scope: before this, only item rows could be disabled and only `card`/`img` honored it. Without it the new "Kept in the file, not shown on the site" hint would be false. A real-Hugo test covers it. **CONCERN (non-blocking):** `scaffold/themes/deckle/README.md:126-135` ("The reserved `disabled` param") is now stale. It still says only a collection row's eye toggle stamps `disabled`, that only item-element templates must honor it, and it shows the old inline check. Every element template must now honor it, through `ce/disabled.html`. A theme author who follows the README would ship block templates that ignore the Enabled switch. Suggested follow-up: a small docs fix.
docs(theme): every element template honors the reserved disabled flag
All checks were successful
ci / build-and-test (pull_request) Successful in 13m41s
6d7b702429
The Enabled switch can now turn off any element, not only a collection
row, and every shipped template wraps its output in the shared
ce/disabled.html check. Bring the theme README's reserved-param section
and partials list in line: the contract now covers block, inline and
item templates alike, through the shared partial.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

This was generated by AI while landing a PR.

The lander pushed 6d7b702 to the head, a docs-only fix for the non-blocking CONCERN in the approval. scaffold/themes/deckle/README.md now documents the reserved disabled contract as it stands after this PR: the Enabled switch can turn off any element, so block, inline and item templates all wrap their output in the shared partials/ce/disabled.html check, and the partials list names ce/disabled. No code changed. go test ./internal/initcmd/ ./internal/element/ passes locally, and CI re-runs on the new head before the merge.

> *This was generated by AI while landing a PR.* The lander pushed 6d7b702 to the head, a docs-only fix for the non-blocking CONCERN in the approval. `scaffold/themes/deckle/README.md` now documents the reserved `disabled` contract as it stands after this PR: the Enabled switch can turn off any element, so block, inline and item templates all wrap their output in the shared `partials/ce/disabled.html` check, and the partials list names `ce/disabled`. No code changed. `go test ./internal/initcmd/ ./internal/element/` passes locally, and CI re-runs on the new head before the merge.
Sign in to join this conversation.
No reviewers
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!173
No description provided.