Skip to content

feat: migrate Manage Categories to the shared tile-ordering workflow - #999

Open
devin-ai-integration[bot] wants to merge 3 commits into
devin/1785280588-drag-performancefrom
devin/1785282182-manage-categories-ordering
Open

feat: migrate Manage Categories to the shared tile-ordering workflow#999
devin-ai-integration[bot] wants to merge 3 commits into
devin/1785280588-drag-performancefrom
devin/1785282182-manage-categories-ordering

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Closes #982 (epic #975). Manage Categories no longer has its own ordering contract — it persists through the same coordinator + atomic PUT /api/tile-order path as Browse.

Before, a dialog drop persisted via two independent requests that could partially succeed:

handleDrop -> interleavedSortOrders() -> PUT /categories/reorder
                                      -> PUT /images/reorder

Now the drop is decomposed into parent moves and per-scope mixed orders:

handleDrop -> diffParentMoves() + interleavedTileOrders()
           -> reorderTilesFromManage(moves, scopes)   // useCategoryActions
                for each move:  PATCH /categories/{id} (versioned, validated move path)
                for each scope: tileOrderingCoordinator.reportOrder(scope, fullOrder)
                                  -> PUT /api/tile-order (CAS revision, one transaction)

Key pieces:

  • interleavedTileOrders(newCats, oldCats, imagesByParent): ScopeOrder[] replaces interleavedSortOrders, emitting the full interleaved TileOrderItemRef[] per changed scope (image slots keep their positions; unchanged scopes are omitted).
  • Move vs. reorder stays distinct: parent changes go first through the versioned category PATCH; only then are scope orders reported, so tile-order membership validation matches.
  • The dialog renders sibling order from the coordinator's per-scope displayOrder (reorderFlatOptions + a coordinator subscription), so pending order doesn't snap back while a save is in flight, and shows the shared ReorderStatusIndicator (unsaved/saving/saved/conflict Refresh–Keep my order/error Retry) for the last-reordered scope.
  • Legacy reorderCategoriesInline/reorderImagesInline wrappers are removed; no runtime frontend caller uses PUT /categories/reorder / PUT /images/reorder anymore. Remaining legacy surface (backend endpoints, api.ts wrappers, SortableTileGrid non-coordinator fallback used only by tests) is tracked for removal in chore: remove legacy per-entity reorder endpoints and SortableTileGrid fallback #998.
  • docs/tile-ordering.md gains a "Manage Categories migration (Migrate Manage Categories to the shared ordering workflow and complete end-to-end verification #982)" section and updated legacy-endpoint notes.

Needs human verification (non-blocking): drag feel of the dialog tree with the coordinator-driven order, and the conflict UX ("Keep my order") when two tabs reorder the same scope from Browse and Manage simultaneously.

Refs #975.

Link to Devin session: https://app.devin.ai/sessions/414754bd88374dc693f47100ac269e78

The Manage Categories dialog now persists ordering through the shared
tile-ordering coordinator and the atomic PUT /api/tile-order contract
instead of the legacy per-entity reorder endpoints. Parent moves persist
first via the versioned category PATCH, then the full interleaved order
of every changed scope is reported to the coordinator (CAS revisions,
explicit conflict handling). The dialog renders sibling order from the
coordinator's display orders and shows the shared save-state indicator.

Legacy endpoint/fallback removal is tracked in #998.

Refs #975. Closes #982.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot requested a review from kphunter as a code owner July 28, 2026 23:59
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

- Use the coordinator's pending display order as the interleaving template
  so a category-only reorder never reverts a pending image reorder for the
  same scope; skip scopes left with no members.
- Memoize the reordered flat options on baseOptions + coordinator version.
- Track all scopes touched by a dialog reorder and surface the one that
  most urgently needs attention (useMostSevereScope) in the indicator.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…ly stale

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 new potential issues.

Open in Devin Review

Comment thread frontend/src/components/manageCategoriesDialogUtils.ts
Comment thread frontend/src/components/ManageCategoriesDialog.tsx
Comment thread frontend/src/useCategoryActions.ts
Comment thread frontend/src/components/ManageCategoriesDialog.tsx
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.

0 participants