xingchuangyang/dcat-admin-sortable
xingchuangyang/dcat-admin-sortable is a Laravel/Dcat Admin extension that adds drag-and-drop row sorting to admin list grids. Reorder records directly in the table and persist their positions via a sortable field, with straightforward installation and configuration for Dcat Admin projects.
Architecture fit. xingchuangyang/dcat-admin-sortable is a Dcat Admin extension, not a general-purpose Laravel sorting library. That makes the first TPM filter binary: this is only relevant if we are standardized on Dcat Admin 2.x. On Nova, Filament, Backpack, or a bespoke admin, it is a non-fit and should be closed at triage — those ecosystems have native reorderable tables and importing a Dcat plugin buys nothing. For a Dcat-based product, the fit is idiomatic and low blast radius: it occupies Dcat's Grid extension points, touches only internal admin surfaces, adds no customer-facing code, and requires no data-model change beyond one indexed integer column. It is a UI affordance layered on an ordering field we should own regardless of whether we keep the package. It does not model hierarchy, scheduled ordering, audit history, or concurrency — so it cannot be the home for those requirements if they appear.
Integration feasibility. Effort is small; the blocker is not engineering complexity, it is provenance. Realistic sequence: composer install, register the extension in config/admin.php, add an unsignedInteger('sort')->default(0) with an index via our own migration, backfill deterministically, set a default model scope with a stable tie-breaker, attach the drag tool to one grid. Spike estimate is 0.5–1 engineer-day including QA, contingent on confirming the exact Grid API surface the package hooks into against the README before locking the estimate. Two gates must clear first: the Composer package name (xingchuangyang/dcat-admin-sortable) and repository name (doct-admin-sortable) diverge, which is a legitimate provenance red flag — confirm the package actually resolves to this source and that published tags are immutable; and confirm the license permits an internal fork.
Technical risk. High relative to value, but bounded and cheap to contain:
Key questions. Which Laravel/PHP/Dcat versions are constrained in composer.json, and do those intersect our version matrix? Does reordering behave correctly across pagination, active filters, and tree/nested grids? Is the write transactional, and what happens under two concurrent admins? Does the endpoint enforce authorization and CSRF scoped to the resource policy? Is the license forkable, and is the footprint small enough to own outright? Does the write pattern scale acceptably on our largest ordered table? And what is the real Composer package → repository mapping?
Recommendation. Conditionally viable as a vendored, version-pinned fork, scoped to internal admin tooling on a Dcat stack. Not viable as a trusted upstream dependency without a named internal owner, and not worth adopting at all if ordering turns out to be a core workflow rather than an admin convenience.
Stack fit. Requires Laravel (8/9/10 depending on tag) + Dcat Admin 2.x + PHP 7.4/8.x. It assumes one flat integer sort column per table and a flat grid. Treat it strictly as a presentation layer over an ordering field we own — not as domain ordering logic. Any nesting, scheduling, or audit requirement routes to a different solution (kalnoy/nestedset for trees; our own table for scheduled merchandising).
Migration path.
sort ourselves — unsignedInteger, NOT NULL DEFAULT 0, indexed — via our own migration. Do not let a third-party package own schema on our tables.ROW_NUMBER() over created_at, id) so existing lists do not reshuffle on first load — the fastest way to lose admin trust is a silent reorder on deploy.orderBy('sort')->orderBy('id') for stable tie-breaking, and expose an ordered() scope so no call site forgets and pagination stays deterministic.Compatibility. Pin an exact tagged version and record the Dcat constraint explicitly in our composer.json rather than relying on a caret range. Fork into an internal namespace (acme/dcat-admin-sortable) at adoption time, not reactively after the first Dcat upgrade breaks the grid tool. The footprint is small enough that forking is cheaper than waiting on upstream responsiveness we should assume will never come.
Sequencing.
Where this sits on the roadmap. Reordering is usually a buried prerequisite inside larger epics — CMS content ordering, navigation builders, product merchandising, workflow stage ordering, form field arrangement. Adopting it cheaply unblocks those rather than letting "add manual sort" consume its own sprint slot. That makes it a good filler-sprint candidate: low blast radius, fully reversible, no customer-facing surface, and a visible win on admin friction. It is not a headline initiative and should not be presented as one.
Maintenance. Plan for internal ownership from day one. The consolation is that "maintain" here means reading a few hundred lines of PHP and JS once, not sustaining a framework. Budget a recurring line item to re-verify against each Dcat minor upgrade, since Grid tool registration is the most likely breakage point. Keep the fork in an internal namespace so our upgrade cadence is not gated on a maintainer who has no obligation to us.
Support. Documentation is thin and largely non-English, and there is no upstream SLA to escalate into. Route questions to the internal owner, not the maintainer, and write a short runbook at adoption: where ordering is stored, how to reorder programmatically for data fixes, how to disable the tool if the asset fails, and who to page. Without that runbook the package's opacity becomes a support liability the first time a merchandiser reports "it didn't save."
Scaling. Two dimensions matter. Vertically, watch the write pattern: per-drag O(n) row rewrites are fine on a 50-row banner table and painful on a thousands-row catalog. Benchmark on our largest intended ordered table before committing, and cap adoption to tables where the rewrite cost is negligible. Horizontally, the package has no concurrency model — multiple admins reordering the same list will silently clobber each other. That is acceptable for low-traffic internal lists and unacceptable if ordering becomes a routine multi-editor workflow; treat the concurrency threshold as a trigger to build our own transactional implementation.
Failure modes. Expect these, in order of likelihood: (1) silent last-write-wins under concurrent admins, presenting as intermittent "my drag reverted"; (2) duplicate or NULL sort keys after filter- or pagination-scoped reordering, causing unstable list order that looks like a cache bug; (3) endpoint reachable without the resource policy applied, an authorization gap rather than a functional one; (4) grid tool failing to register after a Dcat upgrade, degrading to a broken or invisible handle; (5) asset loading failures leaving admins with no ordering mechanism at all. Mitigations are cheap: deterministic tie-breaking in the default scope, an indexed NOT NULL sort column, an explicit authorization test under a real admin role, a version pin plus fork, and the documented manual fallback so ordering never becomes hard-dependent on JS.
Ramp-up. Effectively zero for end users — a drag handle is self-explanatory, and the fallback form field is already familiar. Engineering ramp-up is an afternoon: read the package, read the fork, read the runbook. The real ramp-up cost is organizational, not technical — naming an internal owner, accepting the fork into our namespace, and getting the keep/fork/replace decision onto a calendar with a date attached. If we cannot secure that owner, we should not adopt, regardless of how small the code is.
How can I help you explore Laravel packages today?