48 lines
1.6 KiB
Markdown
48 lines
1.6 KiB
Markdown
---
|
|
title: "Float sort_order (drag-and-drop volgorde)"
|
|
status: active
|
|
audience: [ai-agent, contributor]
|
|
language: nl
|
|
last_updated: 2026-05-03
|
|
when_to_read: "When implementing drag-and-drop reordering or inserting between items."
|
|
---
|
|
|
|
# Patroon: Float sort_order (drag-and-drop volgorde)
|
|
|
|
## Berekening bij tussenvoeging
|
|
|
|
```ts
|
|
function getSortOrder(before: number | null, after: number | null): number {
|
|
if (before === null && after === null) return 1.0
|
|
if (before === null) return after! / 2
|
|
if (after === null) return before + 1.0
|
|
return (before + after) / 2
|
|
}
|
|
```
|
|
|
|
## Herindexeer als precisie opraakt
|
|
|
|
Trigger wanneer het kleinste verschil tussen twee opeenvolgende items < 0.001 is.
|
|
|
|
```ts
|
|
async function reindexIfNeeded(items: { id: string; sort_order: number }[]) {
|
|
const minGap = Math.min(...items.slice(1).map((item, i) =>
|
|
item.sort_order - items[i].sort_order
|
|
))
|
|
if (minGap < 0.001) {
|
|
await Promise.all(items.map((item, i) =>
|
|
prisma.pbi.update({ where: { id: item.id }, data: { sort_order: i + 1.0 } })
|
|
))
|
|
}
|
|
}
|
|
```
|
|
|
|
## Reorder Server Actions
|
|
|
|
Een drag-and-drop reorder stuurt altijd client-controlled ID-lijsten naar de server. Behandel die lijst als onbetrouwbaar.
|
|
|
|
- Weiger dubbele IDs.
|
|
- Haal alle IDs op met de parent-scope, bijvoorbeeld `product_id`, `pbi_id`, `sprint_id` of `story_id`.
|
|
- Weiger de operatie als het aantal gevonden records niet exact gelijk is aan het aantal aangeleverde IDs.
|
|
- Update pas daarna `sort_order` in een transactie.
|
|
- Gebruik bij priority changes dezelfde parent uit de database, niet een los meegegeven `productId`.
|