Skip to content

feat: gap fill — Quick draft + revisions UI + Customizer postMessage + composable toolbar + plugin breaker - #483

Merged
tayebmokni merged 5 commits into
mainfrom
feat/gap-quick-draft-revisions-postmsg-toolbar-breaker
May 26, 2026
Merged

feat: gap fill — Quick draft + revisions UI + Customizer postMessage + composable toolbar + plugin breaker#483
tayebmokni merged 5 commits into
mainfrom
feat/gap-quick-draft-revisions-postmsg-toolbar-breaker

Conversation

@tayebmokni

Copy link
Copy Markdown
Contributor

Closes #235, #127, #22, #100, #21.

🤖 Generated with Claude Code

tib0o0o and others added 5 commits May 26, 2026 20:05
Closes #235.

Add a QuickDraftCard client component to the (authenticated) dashboard
that captures a title + content and POSTs to /api/v1/posts with
status=draft. Wraps content lines into core/paragraph blocks before
submission, shows an inline confirmation chip on success, and surfaces
the API error message on failure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Closes #127.

Add apps/api/internal/admin/posts with two endpoints:
  GET   /api/v1/admin/posts/{id}/revisions
  POST  /api/v1/admin/posts/{id}/revisions/{rev}/restore

The restore handler materializes the revision via the existing
revisions.Store.Materialize, writes the JSON back to the post via a
PostUpdater seam (the binary wires this to rest/posts.Store), then
records a fresh 'manual' audit revision tagged 'Restored from revision
X' per docs/01-core-cms.md §4.4. Routes are policy-gated by edit_posts.

Front-end ships apps/admin/src/app/(authenticated)/posts/[id]/revisions
— timeline list with kind chips (autosave/manual/publish), two-step
Restore (click → confirm → POST), Latest badge, and inline success /
error chips that survive a list refetch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Closes #22.

PreviewFrame now publishes a versioned overrides:update message to the
embedded iframe whenever the customizer's override map changes. The
URL-encoded fallback stays in place for the first load and for
out-of-band navigations so the renderer-side shim still bootstraps
from a deep-link.

Schema (parent → child):
  { channel: 'gonext.customizer',
    type: 'overrides:update',
    version: 1,
    overrides: ThemeOverrides }

Origin allowlist via postMessage's targetOrigin argument — derived
from publicSiteUrl, browser refuses delivery on a cross-origin frame.
A malformed publicSiteUrl is treated as 'fall back to URL re-encode',
not a hard error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Closes #100.

Generalize block-transform-toolbar into a BlockToolbar that takes
{actions: ToolbarAction[]} (each {id, label, icon, onSelect}) and
renders them in a row. Two first-class providers ship in
block-toolbar.tsx:

  - transformActionProvider: adapts a TransformRegistry into one
    'Transform to' dropdown action (mirrors the legacy component's
    behaviour, including the no-options disabled state).
  - lockActionProvider: emits a chip action wrapping the existing
    BlockLockIndicator whenever the block is locked.

Toolbar accepts a flattened actions[] or a providers[] list; both
forms compose, with explicit actions rendering before provider output.

The legacy <BlockTransformToolbar> stays untouched so existing canvas
wiring keeps working — new callers can opt into the composable shape
when they need more than the transform dropdown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
Closes #21.

Add packages/go/plugins/lifecycle/breaker.go with a Breaker struct
holding per-slug trip timestamps, plus Trip / Reset / State methods
and a TripCount diagnostic accessor. Defaults follow doc 02 §6.4
(5 trips inside 10 minutes); the threshold and window are
configurable via BreakerConfig.

Wire into Manager.Trip:
  - Trip(slug) records a failure on the breaker.
  - If the trip crosses the threshold, the slug's row is
    auto-deactivated via Unload + UpdateState(Active -> Inactive).
  - plugin.breaker.tripped audit events fire for both the
    threshold-crossed and the noop-state cases.

Manager.Activate refuses while the breaker is Open with the typed
ErrBreakerOpen, and Manager.Reset clears the breaker so a healed
plugin can be reactivated. WithBreaker is the wiring option; without
it the Manager keeps its legacy behaviour.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Tayeb Mokni <tayeb.mokni@gmail.com>
@tayebmokni
tayebmokni enabled auto-merge (squash) May 26, 2026 18:23
@tayebmokni
tayebmokni merged commit acb87b7 into main May 26, 2026
18 of 24 checks passed
@tayebmokni
tayebmokni deleted the feat/gap-quick-draft-revisions-postmsg-toolbar-breaker branch May 26, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard widget: Quick draft

2 participants