Arrange sidebar
The Arrange Docs page is the editor surface for the docs sidebar. It replaces the older up / down / nest buttons with a single drag interaction, so reordering and nesting happen in one motion. The page is a Filament custom page (slug docs-sidebar, nav label "Docs sidebar") that renders the filament-docs::sidebar-editor Blade view. Access is gated by the viewAny Doc policy — the same gate as the Doc resources.
Interaction
Each row shows the page title and its current path, plus a drag handle (the Bars2 icon). Drag the handle to reorder among siblings. Drop onto a nested list (the indented child <ul> beneath a row) to nest the page under that parent.
The editor is an Alpine x-sortable group named docs-outline. On end, a small serializer walks the DOM and emits a tree of { id, children: [...] } nodes to the Livewire reorder() method. The page first authorizes update for every id in the tree, then wraps DocOutline::applyTree() in a DB transaction.
applyTree
DocOutline::applyTree($nodes, $parentId = null, $ancestors = []) walks the payload depth-first. For each node it:
- Validates the id (
>= 1) and rejects cycles by checking the node id is not in theancestorsstack passed down the recursion. A cycle (a node re-parented under one of its own descendants) throwsInvalidArgumentException. - Loads the
Doc, setsparent_idand a 1-basedposition, and saves. - Recurses into
childrenwith[...$ancestors, $id]as the new ancestor stack.
Saving each Doc fires the model's saving hook, which rebuilds path via buildPath() (parent path + / + slug, or just slug at the root). The saved hook then flushes the outline cache and, when path, slug, or parent_id changed, cascades by re-saving each child — which rebuilds their paths and recurses down the subtree.
Public sidebar
The public sidebar (clone Blade) renders the cached published outline recursively, with no depth limit. The docs index page visually indents three levels; deeper pages still appear in the sidebar, just without further indentation.
sequenceDiagram
participant Editor as Sidebar editor (drag)
participant Page as ArrangeDocs::reorder
participant Outline as DocOutline::applyTree
participant DB as doc_pages
participant Doc as Doc saved hook
participant Cache as Outline cache
Editor->>Page: payload {id, children:[...]}
Page->>Page: authorize update per id
Page->>Outline: applyTree(tree) (DB::transaction)
loop each node depth-first
Outline->>Outline: validate id + ancestor check (no cycles)
Outline->>DB: set parent_id, position; save()
DB->>Doc: saving → buildPath()
Doc->>DB: write path
Doc->>Cache: flushCache()
Doc->>DB: cascade → re-save children (path rebuild)
end