Skip to content

Editor trash for chapters/sections/content elements - #2518

Merged
tf merged 29 commits into
codevise:masterfrom
tf:recycle-bin
Oct 23, 2026
Merged

tf merged 29 commits into
codevise:masterfrom
tf:recycle-bin

Conversation

@tf

@tf tf commented Oct 23, 2026

Copy link
Copy Markdown
Member

No description provided.

tf added 29 commits October 23, 2026 12:24
Section thumbnails set --vh from their own size, but full height
foregrounds and the default section paddings used raw viewport units.
Thumbnails of full height sections thus grew to the height of the
browser window and paddings changed when resizing it. Full height
foregrounds now use var(--vh). The default section paddings and the
padding scale use an --svh custom property, which thumbnails set and
which falls back to 1svh elsewhere.

Custom properties referencing other custom properties resolve where
they are declared. Theme root properties using viewport units are
therefore also declared on the thumbnail element, marked by a
data-section-thumbnail attribute, so that they pick up the thumbnail's
--svh. Other root properties are left alone so overrides from theme
stylesheets keep working inside thumbnails. These rules are only
rendered for the editor and its preview iframe, where thumbnails are
displayed.
Chapter positions keep gaps when chapters are deleted since storylines
do not consolidate positions. Deriving the displayed number from the
chapter's index in its storyline renumbers the remaining chapters.
Outline items update their number when chapters of their storyline
are added, removed or reordered.
Replaces the blinking trash glyph so the trash icon of the content
trash entrance in the outline toolbar does not read as a deletion in
progress.
Distinguishes storylines by column instead of configuration so a trash
storyline can be filtered inside SQL joins. The column is nullable and
only written for new storylines. Existing rows are not backfilled:
queries only ever look for the trash role, which old rows never have.
Storylines expose their role in the seed and the editor and frontend
identify the main storyline by role instead of configuration.main.
New storylines no longer write the main flag. Storylines created before
the role column, or by old app instances during a rolling update, fall
back to their main flag, so no backfill is needed.
all_for_revision of storylines, chapters, sections and content
elements excludes the trash storyline, so trashed content disappears
from seeds and editor endpoints without a call-site audit. Linked
entry chapters, which are loaded with a query of their own, skip it as
well. The trash storyline is created lazily after the existing
storylines while holding a lock on the revision, so parallel deletions
cannot create two of them.
Revision#copy takes a purpose and passes it to after_copy hooks of
revision components which opt in. Entries pass :publish, :snapshot and
:restore. Copies without explicit purpose, like duplicated entries or
entries created from templates, default to :duplicate. Scrolled
storylines use the hook to drop the trash storyline unless the copy
continues the draft's history, so restoring a snapshot brings back its
bin.
Deleting a section re-parents it into a container chapter in the
trash storyline instead of destroying it. The container records kind,
origin chapter perma_id, origin position and trash time so the section
can be restored later. Perma_ids of the section and its content
elements stay untouched.
Trash items wrap the chapters of the trash storyline and expose kind,
origin and trash time recorded in their configuration, so callers do
not depend on how the trash is stored. The endpoint lists items newest
first including sections and content elements so the editor can render
previews.
Re-parents the section into its origin chapter at the recorded
position, shifting later sections, and destroys the now empty
container chapter. If the origin chapter no longer exists, the section
is appended to the first chapter instead. Responds with the section
and its content elements so the editor can repopulate its collections
in one round trip.
Trash items can be fetched and restored. Restoring inserts the
section into its origin chapter like section duplication does, posting
to the restore endpoint and waiting for the response before adding
the section with its content elements. If the origin chapter is gone,
the section is appended to the first chapter, matching the server.
The trash item is removed once the section is restored.
The /scrolled/trash route lists deleted sections with a thumbnail,
origin chapter and deletion time and lets editors restore them.
Failing restores show an error in place. If loading the trash fails,
an error replaces the loading indicator.

Thumbnails render from the editor seed, which does not contain files.
They subscribe to the editor's file collections only, since watching
all collections would replace the trashed sections with the live
ones.
A trash button view sits on the tab line left of the ellipsis menu,
shows a trash can with a restore arrow and carries its name as tooltip
and accessible name.
Deleting a chapter re-parents it with its sections into the trash
storyline instead of destroying it. No container is needed since the
chapter itself is the trash item. Kind, origin storyline perma_id,
origin position and trash time are recorded next to its existing
configuration. The trash listing includes chapter titles.
Re-parents the chapter into its origin storyline at the recorded
position, shifting later chapters, and removes the trash metadata
from its configuration. Excursion chapters return to the excursions
storyline. Responds with the chapter, its sections and their content
elements.
Restoring a trashed chapter inserts it into its origin storyline,
waiting for the restore response before adding the chapter with its
sections and their content elements. The first section of the restored
chapter is selected and scrolled into view.
Chapter trash items read as one thing rather than a number of loose
sections. Failing chapter restores show a generic error since the
origin chapter message does not apply. The trash hint now mentions
chapters as well.
Batch items flagged with _trash in addition to _delete are moved into
a container chapter and section in the trash storyline instead of
being destroyed. The container section copies invert and layout of the
origin section so previews can match how the elements looked. Elements
removed by merging adjacent text blocks are only flagged _delete and
stay destroyed, since their content lives on in the merged block. The
origin position counts the elements that remain in front of the
trashed ones.
Inline text edits are debounced in the preview and flushed when the
content element unmounts, which happens only after the batch moved it
to the trash. Letting the update endpoint find trashed content elements
of the draft writes those last edits into the trashed copy instead of
dropping them.
Inserts the trashed content elements into their origin section at the
recorded position, shifting later elements, and destroys the container
chapter and section. If the origin section is gone or itself in the
trash, the elements are appended to the first section instead.
Responds with the restored content elements.
Deleting a content element flags its batch item with _trash. Adjacent
content elements removed by merging stay plain deletions.
Restoring trashed content elements inserts the returned elements into
their origin section at the recorded position, or appends them to the
first section if the origin section is gone, matching the server. The
first restored element is selected and scrolled into view. Trash items
now resolve their restore target by kind.
Content element trash items name the types of the deleted elements
and the section they were deleted from. Their previews render the
container section full height with the theme's smallest non-zero
paddings so that less of the elements is clipped. The stored container
section is left unchanged. Failing restores show a content element
specific error. The trash hint now mentions content elements as well.
Deleting chapters, sections and content elements is no longer final,
so the confirmations point to the trash instead of warning that the
operation cannot be undone.
Single trash items can be deleted and the whole trash can be emptied.
Both destroy the trash item chapters with their sections and content
elements and keep the trash storyline in place. There is no time
based pruning: revisions already keep copies of everything.
Trash items can be deleted individually and the trash collection can
be emptied. Items are only removed from the collection once the server
confirmed the deletion.
An Actions menu at the top of the trash view offers emptying the
trash and each trash item gets a menu to delete it permanently. Both
ask for confirmation and display an error if the request fails.
Successful deletions of chapters, sections and content elements mark
the entry as having unseen trash items. When the trash button is
rendered with the mark set, or right away while it is visible, a
circle contracts onto it and the icon briefly takes the primary color.
The mark is cleared. The circle lives in a container passed by the
outline since the tab bar clips its content, and is positioned once
the outline is attached. Reduced motion only tints the icon.
The default backdrop background can be overridden via the
--backdrop-default-background custom property. Previews of trashed
content elements use it to show a checkerboard, which makes clear that
the elements are rendered out of their original section.
@tf tf added this to the v17.3 milestone Oct 23, 2026
@tf
tf merged commit 86e31d3 into codevise:master Oct 23, 2026
18 checks passed
@tf
tf deleted the recycle-bin branch October 23, 2026 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant