feat(18.1-01): task 3 flat reorder on the server

- config_reorder.yaml without parentColumn on a record with no parent_id
  column compiles as a flat (WinterCMS Sortable) reorder; maxDepth above 0
  on it fails boot, an explicit parentColumn still means a tree
- ListReorder.Flat and AdminReorderTree.Flat (flat, omitempty); flat nodes
  carry parent_id null, a save writes only the sort column, a parent is a
  422 on nodes (reorder.flat_parent); 409 and duplicate rules unchanged
- swag descriptions, OpenAPI and schema.d.ts regenerated
- acme.catalog badges reorder fixture, TestReorderFlatCompile and
  TestReorderFlatSmoke; docs Flat reorder section and cabana README
This commit is contained in:
Jakub Zych
2026-10-14 15:56:57 +02:00
parent cf63fb3152
commit 9edff8890f
13 changed files with 300 additions and 28 deletions

View File

@@ -483,10 +483,10 @@ func AdminRelationSchema() {}
// @Router /{vendor}/{plugin}/{controller}/fields/{field}/options [get]
func AdminFieldOptions() {}
// AdminReorderGet documents the tree reorder load route (D-09).
// AdminReorderGet documents the reorder load route (D-09, flat D-17).
//
// @Summary Load a reorder tree
// @Description The records of a controller with config_reorder.yaml, scoped by the list scope (ListExtendQuery) and, when the page has a partition, by one partition: `partition` picks it (an id among `partition.options`; another id answers 404) and defaults to the first option. Nodes carry the id, parent_id (null at the top), sort_order and the nameFrom column as name, ordered by the sort column and then the id. A controller without a reorder page answers 404.
// @Description The records of a controller with config_reorder.yaml, scoped by the list scope (ListExtendQuery) and, when the page has a partition, by one partition: `partition` picks it (an id among `partition.options`; another id answers 404) and defaults to the first option. Nodes carry the id, parent_id (null at the top), sort_order and the nameFrom column as name, ordered by the sort column and then the id. A flat reorder (no parentColumn key and no parent_id column on the record, WinterCMS Sortable) answers `flat: true` and parent_id null on every node; a tree reorder omits `flat`. A controller without a reorder page answers 404.
// @Tags admin
// @Produce json
// @Security BackendBearer
@@ -502,10 +502,10 @@ func AdminFieldOptions() {}
// @Router /{vendor}/{plugin}/{controller}/reorder [get]
func AdminReorderGet() {}
// AdminReorderSave documents the tree reorder save route (D-09).
// AdminReorderSave documents the reorder save route (D-09, flat D-17).
//
// @Summary Save a reorder tree
// @Description Saves the parent and sort columns of every record of the scoped set in one transaction that locks the set (ListExtendQuery plus the partition). `nodes` must list exactly the records of that set: any difference (a record added, removed or moved to another partition meanwhile) answers 409 `reorder_stale` and writes nothing. A duplicate id, a parent outside the set, a cycle and a depth above maxDepth answer 422 `validation_failed` on `nodes`; a missing partition on a partitioned page is a 422 on `partition`. The answer is the new tree.
// @Description Saves the parent and sort columns of every record of the scoped set in one transaction that locks the set (ListExtendQuery plus the partition). `nodes` must list exactly the records of that set: any difference (a record added, removed or moved to another partition meanwhile) answers 409 `reorder_stale` and writes nothing. A duplicate id, a parent outside the set, a cycle and a depth above maxDepth answer 422 `validation_failed` on `nodes`; a missing partition on a partitioned page is a 422 on `partition`. On a flat reorder only the sort column is written, and a node with a non-null parent_id is a 422 on `nodes` (`backend::lang.reorder.flat_parent`). The answer is the new tree.
// @Tags admin
// @Accept json
// @Produce json