Files
verdande/web/src/lib/dnd.js
T
Kristian WindandClaude Opus 5 e46aaa462a feat(projects): sektioner kan trækkes op og ned, og båndet står ikke længere skævt
Rækkefølgen af sektioner *er* planen — "Planlægning" står før "I gang", fordi det
er den vej arbejdet går — og indtil nu kunne den kun laves om ved at slette en
sektion og lave den igen, hvilket smider dens opgaver ud i det usektionerede
område på vejen.

Hele overskriften er håndtaget. En sektionsoverskrift indeholder ikke noget, der
selv bliver trukket, så der er ingen geste at stjæle — hvilket er grunden til, at
sidebjælkens rækker skulle have et greb, og grunden til at disse ikke skal. Ikke
draggable mens den omdøbes: et draggable element lader ikke markøren vælge tekst
i det felt, det indeholder.

Serversiden er hele listen på én gang som projekter og grupper, og af samme
grund: et projekt har en håndfuld sektioner, så 0, 1, 2 … er én lille transaktion
uden præcision at løbe tør for, og en liste kan ikke ende halvt anvendt.
`ReorderSections` er scopet til projektet og ikke til en ejer — en sektion har
ingen ejer, den hører til et projekt, og om du må rykke rundt er et spørgsmål om
det projekt, som handleren allerede har stillet. Id'er fra et andet projekt
springes over af WHERE-klausulen; der er en prøve på præcis det, fordi ingenting
ellers kontrollerer id'erne enkeltvis.

Båndet stod fire pixels skævt. Det var trukket ud med --s2 og polstret med --s3 —
samme idé gjort med to forskellige tal — så det blev otte pixels bredere end
listen i hver side, og teksten landede fire pixels uden for den kolonne, rækkerne
holder. Til venstre var det usynligt. Til højre var det Omdøb og Slet, der stod
fire pixels forbi alt over og under sig, hvilket er præcis langt nok til at ligne
en fejl og ikke langt nok til at se hvorfor. En række er `.row` med
`padding: var(--s2)` inde i en boks uden, så båndet har nu samme polstring og
ingen margen.

Board-visningen er ikke rørt: der er kolonnerne vandrette, og det er en anden
geste.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-20 14:56:26 +02:00

46 lines
1.8 KiB
JavaScript

/**
* What a drag is carrying.
*
* More than one kind of thing is now dragged onto the same targets: the sidebar
* takes a project (to reorder it, or file it under a group) *and* a task (to move
* it into that project), and Kommende takes a task onto a day.
*
* The distinction has to be a MIME type rather than something read out of the
* payload, because `getData` is deliberately unreadable while a drag is in the
* air — the browser only hands the data over on drop, so that a page cannot read
* what is being dragged across it. During `dragover`, `dataTransfer.types` is all
* a drop target has to decide with, and deciding is exactly what it has to do:
* `preventDefault` on a drag it cannot accept is what turns "no" into a silent,
* wrong drop.
*/
export const TASK = 'application/x-verdande-task';
export const PROJECT = 'application/x-verdande-project';
export const GROUP = 'application/x-verdande-group';
export const NOTE = 'application/x-verdande-note';
export const SECTION = 'application/x-verdande-section';
/** Starts a drag carrying one id of the given kind. */
export function startDrag(event, type, id) {
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData(type, id);
// Firefox refuses to start a drag unless text/plain is set as well.
event.dataTransfer.setData('text/plain', id);
}
/** Whether the drag in flight is of this kind. Safe to call during dragover. */
export function carries(event, type) {
return event.dataTransfer?.types?.includes(type) ?? false;
}
/** The id being dragged. Only meaningful in a drop handler. */
export function dragged(event, type) {
return event.dataTransfer?.getData(type) ?? '';
}
/** Marks a drop target as willing, which is what allows the drop to happen at all. */
export function accept(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}