CLI: Add --reset flag to the seed command#33
Merged
Merged
Conversation
Deletes all Cortext collections, fields, and entries before re-seeding. Prompts for confirmation unless --force is passed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
priethor
added a commit
that referenced
this pull request
May 11, 2026
* Make page chrome generic so rows can reuse it
Introduces a `cortext-document` post type support flag and
`DocumentIdentity::register_for_post_type()` helper so any CPT can opt
into the shared chrome (icon meta, locked title block, identity
controls, trash mechanics). Page and dynamic row CPTs both opt in.
Renames the page-flavored pieces to their document-flavored names:
PageIdentity, PageIconBlock, PageCoverBlock, PageTrashController,
PageIdentityControls, src/blocks/page-{icon,cover}, and the
cortext_page_icon meta key all become cortext_document_*. RevisionThrottle
gates on post_type_supports('cortext-document') instead of hard-coding
the page CPT.
Extracts the shared editor body into EditorBody and the row property
panel into RowProperties so Canvas (full-page documents) and
RowDetailView (side and modal panes) render the same editor surface
for any document, with the trash banner sitting outside the locked
canvas region so the Restore button stays interactive.
* Address pages and rows by id with one URL shape
Documents (pages and rows) now live at /<slug>-<id>; the slug is
cosmetic and the trailing id is authoritative, so renames don't break
existing links and a fresh draft with no slug stays addressable.
A new /cortext/v1/documents/<id> locator endpoint takes any id and
returns its post type, rest_base, and slug, which lets a single resolver
fetch any document without the URL having to encode the post type.
Collections keep their own collection/<slug>-<id> shape since they're
schema containers, not documents.
Also fixes the row-to-collection lookup that drives the property panel
and breadcrumb on full-page rows. The previous query used REST `?slug=`
(which filters post_name) with no status param. Collections store their
canonical slug in `meta.slug` and are created `private`, so the lookup
returned nothing for any collection with a long title or a non-publish
status. Now it reuses the workspace-wide collection list query and
matches `meta.slug` client-side, mirroring the PHP helper.
* Stop persisting row peek state in the URL
Side and modal row detail panes now live in local React state instead
of being driven by `?row=<id>` (with a paired `?rowCollection=<id>`).
The URL contract was already shaky: a page with two cortext/data-view
blocks pointing at the same collection had no way to disambiguate which
block owned the open pane, and sidebar navigation would carry stale
`?row` into the next route.
Full mode is the only row state that round-trips through the URL, and
it does so as a regular document path (/<slug>-<id>). Side and modal
panes open via click and close via dismiss; refresh closes them, which
is the same trade row detail panes have always made on collection-list
embeddings.
* Update tech-debt notes for the document chrome rename
Renames page-flavored references in entries #31, #32, #33, #34 to match
the cortext-document trait. Adds #41 covering the row-properties block
that needs to land for rows to publish cleanly through `the_content()`.
* Fix Canvas mount gating so documents load
The URL unification commit gated the Canvas mount on
`active.kind === 'document'`, but `active` only flips after Canvas
fires `DOCUMENT_DISPLAYED`, which it can't fire until it mounts.
Chicken-and-egg, so opening a page (or any document) stalled with
nothing rendered.
Mount Canvas as soon as a document is mounted; pane visibility still
flows through `WorkspacePane` and the `isActive` prop.
* Show row document icons next to titles in collection tables
Surface `cortext_document_icon` in the row table response and render
it in `TitleCell` next to the title. The icon sits in the cell's
leading gutter so the title text keeps the same x-position whether or
not a row has an icon.
* Restore grid layout for title cell so row height stays compact
The previous CSS made the title cell `display: flex` always, which
disrupted the row's natural height. Bring back the grid layout for
`--with-open-action` (matches main); the icon stays absolute-positioned
in the leading gutter, so the title still doesn't shift when an icon is
present.
* Place row icon in title cell gutter so title stays aligned
Slot the icon as the leading grid column when present, instead of
absolute-positioning it outside the cell. The previous absolute
approach combined with `position: relative` on the title cell looked
like it was interacting badly with row height in selected rows.
Accepting a small title indent on rows that have icons keeps the
layout predictable.
* Stretch title cell to fill the td so selection bg covers the row
When another column wraps and grows the row, the title cell div was
content-height, so its gray selection/hover background only painted
behind the title content. Make the title cell fill the td vertically
(`height: 100%`) so the highlight reaches both edges of the column
even on tall rows.
* Highlight title cell on its own hover, not on row hover
Previously the title cell darkened whenever any cell in the row was
hovered, so hovering Status painted the title gray too. Move the bg
trigger to a direct `:hover` on the title cell so only the actually
hovered cell darkens. The Open-button visibility-on-row-hover rule
stays untouched, so the affordance still appears across the whole row.
* Scope block-list min-height to root, not nested block layouts
Side peek and modal injected `min-height: 180px` on every
`.block-editor-block-list__layout`, which affects nested block
layouts too: a `core/list` block has its own inner block list per
item, so each list item ballooned to 180px tall. Full page never
passed these extra styles, so it didn't see the rule. Limit the
min-height to the root container so the empty-editor click target
still works without distorting nested blocks.
* Suppress block move animation while EditorBody hydrates headers
When EditorBody mounts on a row that doesn't have its locked title /
icon / cover blocks in post_content yet, EnsureHeaderBlocks inserts
them on the fly. Block-editor's `useMovingAnimation` then animates the
existing body blocks sliding into their new indices, which reads as
"the icon is being inserted right now" every time the user switches
between rows in side peek.
`useMovingAnimation` already skips the animation while `isTyping` is
true (so Enter-to-split doesn't visually shove the rest of the post
around). Wrap our header-block inserts in a startTyping/stopTyping
pair to reuse that escape hatch: the animation is decided during the
layout effect with typing on, then we release the flag on the next
frame. No follow-up edits trigger animations they shouldn't.
Once a row is saved, prepend_header_blocks lands the title block
server-side and the rehydration is a no-op.
* Move full-mode hide-properties affordance next to the properties
Adds a small chevron-up button at the top-left of the
`cortext-row-detail--canvas-properties` wrapper that's only rendered
when the properties panel is visible. Click hides the panel; the
top-bar toggle ("Show fields" / "Hide fields") still flips both ways,
so it doubles as the only way to bring the panel back.
The button lives on the Canvas-only wrapper, not inside RowProperties,
so side peek and modal panes are untouched. Affordance fades in on
wrapper hover (or button focus) to keep the panel itself uncluttered.
* Show a chevron-down to expand collapsed properties in full mode
When the user hides the properties via the top-bar toggle or the
hide-chevron, the canvas now keeps a thin strip with a chevron-down
where the panel used to live. Click brings the properties back. The
top-bar toggle still works too, but the strip is the discoverable
affordance (top bar gets lost in chrome). The strip lives on the
Canvas-only wrapper, so side peek and modal panes are unaffected.
* Float canvas-properties chevron over the cover and animate the collapse
Same chevron handles both directions now, parked at the top-left of the
canvas-properties wrapper via `position: absolute`. When the panel is
expanded it sits at the top of the panel; when it's collapsed the
wrapper has zero height, so the chevron lands over the document cover
instead. No more mid-page strip when fields are hidden.
The collapse uses a `grid-template-rows: 1fr → 0fr` transition with the
body child set to `overflow: hidden`, which is the smooth way to
animate to a content-sized natural height without hard-coding it.
* Hydrate row relations and rollups in the standard WP REST response
Peek and modal panes fetch rows via `useEntityRecord`, which goes
through `/wp/v2/<rest_base>/<id>` and returns whatever `register_post_meta`
left in place: raw stored IDs for relation fields, no value at all for
rollups (they aren't real meta). `RelationReferences` and the rollup
display then drop everything as malformed, so albums / album counts /
album genres etc. read "Empty" in the side pane even when the table
view shows them populated.
Hook `rest_prepare_<post_type>` for every row CPT and overwrite
`response.meta.field-<id>` for relation and rollup fields with the
hydrated shape `/cortext/v1/rows` already produces. Same hydrators
the table feed uses (`format_relation_value`, `compute_rollup_value`),
so both surfaces stay in sync.
Pages, collections, and field CPTs aren't touched because they don't
appear in `CollectionEntries::get_entry_post_types()`.
* Give the canvas-properties chevron a solid pill so it's legible over dark covers
Floating the chevron over the cover meant relying on the cover's
brightness for the icon to be visible. On a dark cover the icon
disappeared. Add a near-white background pill with a soft shadow so
the chevron has its own contrast surface regardless of what's behind.
Also keep it always visible when properties are collapsed, since it's
the only affordance in that state.
* Divide properties from blocks with a hairline in side peek and modal
The properties form and the document body sat flush against each other
in side and modal panes, so the visual transition from form fields to
editor canvas was unclear. Add a hairline border at the top of the
EditorBody wrapper inside the row-detail context, using the existing
`--cortext-row-detail-border` token. Full mode still has the canvas
properties chevron / animation as the divider, so it stays untouched.
* Match the properties-bottom divider to the header-bottom one
Was using `var(--cortext-row-detail-border)` for the new line under
properties; the existing line above properties (`__header`'s border-
bottom) uses `$border-width solid $gray-200`. Switch to the same
token so both edges of the properties form look identical.
* Add the same divider under the full-page properties panel
Hairline below the canvas properties body so the boundary between
fields and document body is consistent with side / modal. Border lives
on the body (not the wrapper) so it collapses with the content when
the panel is closed instead of leaving a stray line over the cover.
* Drop the title cell darker bg on open rows
Title cell was getting a `gray-100` background on `--is-open` on top of
the row's own `#f8f8f8` selected bg, so the title cell looked a notch
darker than the rest of the row. The row-level highlight is already
the selection signal; let the title cell match it. Hover and
focus-within still keep their per-cell darker bg.
* Fix data view shell layout
* Isolate row peek editor in its own subregistry
Side / modal panes mounted `<EditorProvider>` for the row without
`useSubRegistry`, so the row shared the global `core/editor` store
with whatever editor was already on screen. When a row peek opens
inside a `cortext/data-view` block on a page, the row and the parent
page fight for the same store: the autosave selector ends up reading
the wrong post's flags, and `flushNow()` reports success of the row's
REST write as a failure (because the page is clean so its
`didPostSaveRequestFail` may be set, or its `isDirty` is false). The
user sees a "failed to save" notice on writes that actually went
through.
Spinning up a subregistry per pane gives the row its own editor store,
isolated from the parent page editor (and from other simultaneously
open peeks). Saves dispatch against the right post, and the parent
page's editor state isn't touched at all. Full mode is unaffected
because Canvas already passes `useSubRegistry` through.
* Stop bouncing hydrated relation/rollup values back through meta on save
Two compounding bugs caused infinite `POST /wp/v2/<row-cpt>/<id>` 400
loops when editing any row property:
1. The new `rest_prepare_<row-cpt>` filter overwrote
`meta.field-<id>` for relation and rollup fields with hydrated
objects/arrays. Those meta keys are registered as `string`, so on
save the editor round-tripped the hydrated shape back to REST and
WP rejected the payload. The autosave then retried, hit the same
400, retried again, etc.
2. `splitPropertyPatch` was merging the entire current meta into
every patch before handing it to `editPost`. That made every meta
key look edited even when the user only touched one field, which
ensured the offending hydrated values got included in the save
payload.
Server: keep `meta` as the canonical raw store. Move the hydrated
relation/rollup map onto a parallel `cortext_hydrated_meta` response
key so consumers that need display values have them, but the save
path still writes strings back and round-trips cleanly.
Client: `splitPropertyPatch` only emits the changed keys now; the
caller no longer passes `currentMeta`. `RowProperties` reads
relation/rollup display values from the new
`cortext_hydrated_meta` attribute and keeps using `meta` for the
text/number/select fields that are actually editable in the form.
* Revert "Stop bouncing hydrated relation/rollup values back through meta on save"
This reverts commit bb188ce.
* Stop merging current meta into row property edits
`splitPropertyPatch` was building `{ ...currentMeta, ...patch }` and
handing that to `editPost`, marking every meta key edited even when
the user only touched one field. With relation / rollup meta hydrated
in the response (registered as `string` but populated with objects /
computed values), every save round-tripped the hydrated shape back to
REST and got 400, looping the autosave.
Only emit the changed keys. `editPost` merges meta partially in
`core/editor`, so unchanged hydrated values stay out of the save
payload entirely.
* Reapply "Stop bouncing hydrated relation/rollup values back through meta on save"
This reverts commit c06c248.
* Update e2e specs for the document URL refactor
The PR dropped the `/page/` prefix from page document URLs (everything
is just `<slug>-<id>` now) and stopped persisting the row peek's
state in the URL (`?row` / `?rowCollection` are gone). The CI's
Playwright suite still expected the old shape in a handful of places:
- `admin.visitAdminPage(..., 'page=cortext&p=/page/<id>')` no longer
loads the page because `parseIdFromUri` doesn't find an id behind a
slash. Switched the visits to `p=/<id>`.
- `appPath.toContain('/page/')` was the old way to assert "we landed
on a page document." Now we just check the path contains the
document's id.
- The data-view-block spec was verifying row peek navigation by
polling `?row` and exercising browser Back / Forward. Side and
modal panes are local React state now, so neither path holds. The
Row above / Row below button assertions already cover the same
thing semantically.
* Surface row system fields on the standard WP REST response
Full-page row documents pull their `row` prop from `useResolveDocument`,
which hits `/wp/v2/<rest_base>/<id>`. That response only exposed the
raw post (`author`, `date_gmt`, …), not the hydrated `created_by` /
`modified_by` display names the field getters expect, so the system
columns rendered as "Empty" in full mode even though side peek and
modal (which load via `/cortext/v1/rows`) showed them correctly.
Extend the existing `rest_prepare_<row-cpt>` filter to also surface
`created_at`, `created_by`, `modified_at`, `modified_by` at the
top level of the row response, mirroring `format_row` on the table
feed. Resolver's `_fields` query is widened to pull them through.
* Update e2e specs for the document trait rename and dual-iframe context
Two CI Playwright failures after the latest merge:
- The trashed-document banner says "This document is in trash." since
we generalised page identity to documents. The test was still
asserting the old "This page is in trash." copy.
- The data-view-block test scoped its frame via
`.cortext-canvas__visual iframe[name="editor-canvas"]`. When the
row peek opens, RowDetailView mounts its own EditorBody (and
another such iframe), so the locator now resolves to two elements
and trips Playwright's strict mode. Pin the canvas to the parent
page's `role="region" name="Content"` region so the row peek's
iframe doesn't get picked up.
* Update row-detail e2e to mirror the chrome-title / iframe-edit split
The row detail chrome now renders the post title as a read-only
`<h2>` and the editable title lives inside the row's EditorBody
iframe (locked `core/post-title` block). The spec was still expecting
a `<textbox name="Title">` inside the dialog.
- Switch the `detailTitle` locator to the chrome heading and use
`toHaveText` instead of `toHaveValue`.
- Drop the title-edit-via-chrome step. The Author / Year edits below
still cover the row-property save round-trip, so the test's intent
is preserved.
- Adjust downstream breadcrumb / REST assertions to expect the
original title ("The Left Hand of Darkness") since the title is
no longer being changed in the spec.
* Drop DOM-identity check on Tags label across row switches
The spec stamped a `data-e2e-stable-label` attribute on row 1's Tags
property label, then asserted it survived on row 2 to prove React
reused the same DOM node across the switch. With per-pane editor
subregistries the second row mounts a fresh subtree, so the marker
is gone. Replace the survival check with a plain visibility check
on the Tags label using its normal selector. The functional intent
("row 2 still renders the Tags field") is preserved without
asserting an internal DOM identity that's not user-visible.
* Preserve unsaved edits across cross-type navigation
Switching between a page and a row document re-mounted the editor
immediately, dropping any in-flight edits on the previous document. The
type-mismatch fallback in `renderedPost` short-circuited before the
`pendingPost`/`flushNow` path that handles same-type swaps, so the flush
only ran for page-to-page navigation.
Keep `displayedPost` mounted regardless of type until CanvasEditor has
flushed, route the rendered type downstream so child chrome stays
coherent during the transition, and tighten the pending-post effect to
compare both id and type.
* Update row-detail e2e for hide-fields toggle and breadcrumb collection nav
`.cortext-row-detail__fields-indicator` and `.cortext-row-detail__content-editor`
no longer exist after the iframe refactor; the properties panel stays
mounted with `data-visible="false"` when collapsed.
Clicking the collection in a row's breadcrumb now navigates to the
collection's management surface, which renders DataViews directly
(no editor iframe), so scope the post-navigation assertion to the page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--resetflag towp cortext seedthat deletes all collections, fields, and entries (but not pages) before re-seeding--forceTest plan
wp cortext seed— seeds normally, no change in behaviorwp cortext seed --reset— prompts for confirmation, then deletes all cortext data and re-seedswp cortext seed --reset --force— skips the prompt🤖 Generated with Claude Code