16 KiB
Feature 7 – Radera uppgift
Status
Färdig och mergad till main.
Bakgrund
HemHub stödjer skapande, visning, tilldelning, statusändring och drag-and-drop av uppgifter. Det saknas möjlighet att ta bort uppgifter som inte längre är relevanta eller som skapats av misstag.
Feature 7 inför permanent radering av en enskild uppgift. Radering hålls separat från generell redigering så att det destruktiva flödet, dess bekräftelse och felhantering kan implementeras och verifieras isolerat.
Mål
Feature 7 ska:
- införa ett backend-API för permanent radering av en uppgift;
- låta användaren initiera radering från uppgiftskortet;
- kräva en tydlig bekräftelse före radering;
- ta bort kortet från brädan först efter serverbekräftelse;
- återanvända befintlig låsning och felhantering per task-id;
- fungera tillsammans med statusändring, tilldelning och drag-and-drop utan parallella state- eller requestflöden.
Omfattning
Feature 7 omfattar endast permanent radering av en befintlig uppgift.
En uppgift får raderas oavsett om dess status är WAITING, IN_PROGRESS eller
COMPLETED. Uppgiftens ansvariga användare och aktiv browseranvändare påverkar
inte möjligheten att radera. Det lokala användarvalet är inte autentisering
eller behörighetskontroll.
Avgränsningar
Feature 7 ska inte införa:
- mjuk radering, papperskorg, återställning eller undo;
- arkivering, versions-, status- eller poänghistorik;
- generell redigering;
- batchradering eller markering av flera kort;
- radering av användare;
- behörigheter eller ägarskap;
- realtidsuppdatering mellan browsers;
- automatisk gallring;
- persistent kortordning;
- nya relationer till uppgifter;
- generell cascade-logik för framtida modeller.
Permanent radering
Radering är permanent. När användaren har bekräftat raderingen tas uppgiften
bort ur databasen. Ingen deleted-flagga, deletedAt, dold arkiveringsmodell
eller annan form av mjuk radering införs.
HemHub är en liten familjeapplikation utan revisionslogg, papperskorg eller återställningsflöde. En mjukraderingsmodell skulle därför öka komplexiteten utan ett tydligt nuvarande produktvärde.
Om framtida features för återkommande uppgifter eller poänghistorik behöver bevara information efter radering ska deras datamodeller och raderingsregler beslutas i respektive feature.
Tillåtna statusar
Samtliga uppgifter får raderas oavsett status. Det krävs inte att en
IN_PROGRESS-uppgift först flyttas till WAITING, och en COMPLETED-uppgift
behandlas inte annorlunda än övriga uppgifter.
Bekräftelseflödet är samma för alla statusar. Ingen extra varning eller ytterligare bekräftelse införs för pågående uppgifter.
Raderingskontroll
Raderingskontrollen ska visas som en diskret sopkorgsikon direkt på det befintliga uppgiftskortet, uppe till höger i ett eget åtgärdsområde. Feature 7 inför inget kompakt eller expanderat kortläge.
Kontrollen ska:
- visas på befintliga uppgiftskort;
- ha en tillgänglig etikett som identifierar uppgiften, exempelvis
Radera Töm diskmaskinen; - öppna bekräftelsedialogen;
- inte starta drag-and-drop;
- ha en rimlig klickyta för touch;
- ha neutral stil i normalläge och tydlig hover- och fokusmarkering;
- vara inaktiverad när samma uppgift har en pågående operation.
Sopkorgen implementeras som inline-SVG enligt projektets befintliga ikonmönster. Feature 7 lägger inte till något ikonbibliotek.
Den destruktiva visuella betoningen ska primärt ligga i bekräftelsedialogen. Kontrollen ska kunna flyttas till en framtida meny eller detaljdialog utan att backend-API eller delete-flödet behöver göras om.
Bekräftelsedialog
Radering bekräftas i en separat delete-modal. Den ska följa beteendemönstret i
CreateTaskModal, men Feature 7 inför ingen gemensam modalkomponent och gör
ingen bred modalrefaktorering. Dialogen ska visa:
- rubriken
Radera uppgift?; - uppgiftens titel;
- tydlig information om att raderingen är permanent;
- knappen
Avbryt; - den destruktivt utformade knappen
Radera.
Exempel:
Är du säker på att du vill radera Töm diskmaskinen? Uppgiften raderas permanent och kan inte återställas.
Delete-modalen har inget stängningskryss. Innan delete-anropet har startat ska
den kunna stängas med Avbryt, Escape eller klick på bakgrunden. Under
pågående delete-anrop blockeras samtliga stängningsvägar.
Dialogen ska följa projektets befintliga modalstruktur och fokusprinciper.
Avbryt får initialt fokus när dialogen öppnas; den destruktiva knappen
Radera får inte initialt fokus. Båda knapparna ska vara
tangentbordsåtkomliga.
Backend-API
Radering sker genom:
DELETE /api/tasks/{taskId}
Lyckad radering
När uppgiften finns och raderas svarar backend med 204 No Content utan body.
Okänd uppgift
Om uppgiften inte finns svarar backend med 404 Not Found och projektets
befintliga felformat:
TASK_NOT_FOUND
Det gäller även om samma task-id tidigare har raderats. Ett andra delete-anrop
mot samma id ger därför 404 TASK_NOT_FOUND.
Ogiltigt task-id
Ett task-id som inte kan tolkas som UUID ger 400 Bad Request med repositoryts
nuvarande requestfel och felformat. Den befintliga felkoden
INVALID_TASK_ASSIGNMENT ändras inte inom Feature 7. Feature 7 inför ingen
separat felmodell för UUID-fel.
Konflikter och transaktion
Radering är tillåten för samtliga statusar och oavsett ansvarig. Feature 7 har
därför inget domänfall som ger 409 Conflict.
Raderingen ska ske inom backendens normala transaktionsgräns och endast ta bort den identifierade uppgiften. Den får inte ändra eller radera ansvarig användare, andra användare eller andra uppgifter.
Databas
Feature 7 raderar raden permanent ur tabellen task.
Nuvarande datamodell har inga dokumenterade beroendeentiteter som kräver en ny
migrering eller särskild cascade-policy. Den befintliga relationen från
task.assignee_id till app_user.id ska verifieras så att den inte hindrar
radering av uppgiften. Den ansvariga användaren ska finnas kvar.
Ingen databasmigrering ska skapas om det faktiska schemat redan stödjer radering. Framtida relationer till uppgifter får definiera sin delete-policy när de införs.
Frontendens uppdateringsstrategi
Frontend använder serverbekräftad radering. När användaren bekräftar ska frontend:
- markera uppgiften som upptagen;
- behålla kortet i dess nuvarande kolumn;
- behålla bekräftelsedialogen öppen;
- skicka delete-anropet;
- vänta på serverns svar;
- vid
204 No Contentta bort uppgiften ur den lokala task-listan; - stänga dialogen;
- frigöra låsningen för task-id.
Kortet ska inte tas bort optimistiskt. Ingen rollback-modell behövs eftersom kortet ligger kvar under anropet.
Vänteläge
När delete-anropet pågår ska:
- bekräftelsedialogen ligga kvar öppen;
RaderaochAvbrytvara inaktiverade;- Escape och bakgrundsklick inte kunna stänga dialogen;
- kortet ligga kvar i sin kolumn och tonas ned lätt;
- alla interaktiva kontroller på samma kort vara inaktiverade.
Ingen spinner eller text som Raderar… krävs.
Låsning och samspel med andra operationer
Delete ska återanvända den befintliga låsningen per task-id. När uppgiften har en pågående status-, tilldelnings- eller dragoperation ska radering inte kunna initieras.
När delete-anropet pågår ska samma uppgift inte kunna dras, ändra status, ändra ansvarig, öppna en ny raderingsdialog eller skicka ytterligare delete-anrop. Andra kort ska förbli interaktiva och kunna ha egna samtidiga operationer.
Feature 7 inför inget globalt vänteläge, separat delete-lås eller parallell requestmodell.
Felhantering
Vanliga delete-fel
Vid nätverksfel, serverfel eller annat vanligt delete-fel ska:
- kortet ligga kvar oförändrat;
- dialogen ligga kvar öppen;
- vänteläget avslutas;
- kontrollerna aktiveras igen;
- felmeddelandet
Det gick inte att radera uppgiften. Försök igen.visas i dialogen; - användaren kunna försöka igen eller avbryta.
Delete-felet ska inte blandas med status- eller tilldelningsfel på kortet.
404 TASK_NOT_FOUND
Om backend svarar med 404 TASK_NOT_FOUND betraktas kortet som inaktuellt.
Frontend ska då ta bort uppgiften ur den lokala task-listan, stänga dialogen
och frigöra låsningen utan att visa det generella delete-felet.
Frontendens generella ApiError-typ utökas med ett valfritt code. Delete-
flödet ska använda code === "TASK_NOT_FOUND" och status 404 för detta fall
och får inte tolka meddelandetexten.
Andra typer av 404 ska inte behandlas som en redan borttagen uppgift.
Frontendtester
Frontendtesterna ska minst verifiera:
- att sopkorgsknappen visas direkt på det befintliga uppgiftskortet;
- att ikonen är inline-SVG och inte kräver ett ikonbibliotek;
- tillgänglig etikett och rätt uppgift i bekräftelsedialogen;
- information om permanent radering;
- initialt fokus på
Avbryt, aldrig påRadera; - att modalen saknar stängningskryss;
- stängning med
Avbryt, Escape och bakgrundsklick före anrop; DELETE /api/tasks/{taskId}först efter bekräftelse;- att kort och dialog ligger kvar under anropet;
- att dialogen inte kan stängas medan anropet pågår;
- gemensam låsning för status, tilldelning, drag och radering;
- att andra kort förblir interaktiva;
- blockering av dubbla delete-anrop;
- att
204 No Contenttar bort rätt kort och stänger dialogen; - att vanliga fel behåller kort och dialog samt kan återförsökas;
- att
404 TASK_NOT_FOUNDtar bort det inaktuella kortet; - att ett annat
404-fel inte feltolkas somTASK_NOT_FOUND; - att raderingskontrollen inte bryter drag-and-drop;
- grundläggande tangentbordsfokus och knappaktivering.
Testerna ska verifiera beteende och state, inte exakt ikonplacering, färg eller pixelmått.
Backendtester
Backendtesterna ska minst verifiera:
- radering i
WAITING,IN_PROGRESSochCOMPLETED; 204 No Contentutan body;- att den raderade uppgiften inte längre finns i
GET /api/tasks; - att andra uppgifter och den ansvariga användaren finns kvar oförändrade;
404 TASK_NOT_FOUNDför okänt id och ett andra delete-anrop;- projektets befintliga
400-fel för ogiltigt UUID-format.
Testerna ska följa repositoryts befintliga integrationsteststil.
Manuell verifiering
Följande ska verifieras manuellt:
- Sopkorgsknappens placering uppe till höger i ett eget åtgärdsområde, neutrala normalläge, touchyta, hover, fokus och tillgängliga etikett.
- Radering av uppgifter i samtliga tre statusar.
- Initialt fokus på
Avbryt, inget stängningskryss samt avbrytande med knapp, Escape och bakgrundsklick före anrop. - Rätt titel och information om permanent radering.
- Titel nära maximal längd.
- Blockering av dubbla delete-anrop.
- Vänteläge för kort och dialog under fördröjt svar.
- Låsning av drag, status, tilldelning och ny radering för samma kort.
- Fortsatt interaktion med andra kort.
- Vanligt serverfel, visat felmeddelande och nytt försök.
404 TASK_NOT_FOUNDoch lokal borttagning av inaktuellt kort.- Desktop- och mobilbredd samt tangentbordsaktivering.
- Omladdning efter lyckad radering så att uppgiften inte återkommer.
Dokumentation
Feature 7 dokumenteras i:
docs/features/007-task-deletion.md
Vid implementation ska README.md, docs/architecture.md och
docs/roadmap.md uppdateras när det är relevant.
Roadmapen ska markera Feature 7 som Klar först efter implementation,
automatiska tester, manuell verifiering och merge.
Ett nytt ADR behövs inte för permanent radering. Beslutet gäller den nuvarande task-livscykeln och etablerar inte en generell raderingspolicy för framtida entiteter.
Acceptanskriterier
Feature 7 är klar när:
- en uppgift kan raderas permanent med
DELETE /api/tasks/{taskId}; - lyckad radering ger
204 No Content; - okänd eller redan raderad uppgift ger
404 TASK_NOT_FOUND; - ogiltigt UUID-format följer befintlig felhantering;
- alla tre statusar kan raderas oavsett ansvarig eller aktiv användare;
- radering kräver en egen bekräftelsedialog;
- dialogen visar rätt titel och anger att raderingen inte kan återställas;
Avbrytfår initialt fokus ochRaderafår inte initialt fokus;- modalen saknar stängningskryss och blockerar alla stängningsvägar under anropet;
- en diskret inline-SVG-sopkorg visas direkt på befintliga uppgiftskort;
- raderingskontrollen startar inte drag;
- kortet tas bort först efter serverbekräftelse;
- samma task-id låses för status, tilldelning, drag och ny radering;
- andra kort förblir interaktiva;
- vanliga fel behåller kort och dialog och kan återförsökas;
404 TASK_NOT_FOUNDtar bort det inaktuella lokala kortet;- ingen mjukradering, återställningsmodell eller onödig migrering införs;
- backend- och frontendtester täcker centrala flöden;
- manuell verifiering genomförs;
- relevant dokumentation uppdateras.
Implementerad lösning
Backendens task-controller och task-service har utökats med fysisk radering via
DELETE /api/tasks/{taskId}. Servicen hämtar först uppgiften för att
återanvända TaskNotFoundException och raderar därefter entiteten inom en
transaktion. Ingen entitet, exception handler eller Flyway-migrering behövde
ändras.
Frontendens TaskBoard använder samma per-task-lås som status- och
tilldelningsoperationerna. Radering är serverbekräftad: kortet och dialogen
ligger kvar medan anropet pågår, och kortet tas bort först efter 204 No Content. Endast ett svar med både status 404 och felkoden
TASK_NOT_FOUND tar bort ett känt inaktuellt kort. Övriga fel behåller kortet
och dialogen så att användaren kan försöka igen.
TaskCard har inget kompakt eller expanderat läge. En neutral
inline-SVG-knapp ligger direkt i kortets övre högra åtgärdsområde och stoppar
pointer-händelsen innan den når dragytan. Den separata delete-modalen följer
CreateTaskModal-mönstret utan en gemensam modalabstraktion. Avbryt får
initialt fokus, modalen saknar stängningskryss och samtliga stängningsvägar
blockeras under delete-anropet.
Frontendens generella ApiError innehåller nu ett valfritt code. Den
befintliga backendhanteringen av felaktigt UUID är oförändrad och returnerar
fortsatt 400 INVALID_TASK_ASSIGNMENT.
Tester och verifiering
Automatiskt verifierat:
- backendens fullständiga testsvit: 47 tester passerade;
- frontendens fullständiga testsvit: 49 tester passerade;
- frontendens produktionsbygge och TypeScript-kompilering passerade;
git diff --checkpasserade.
Backendtesterna ligger i den separata integrationstestklassen
TaskDeletionApiTest. Frontendens delete-flöden testas tillsammans med övriga
brädbeteenden i App.test.tsx.
Manuell browserverifiering genomfördes mot lokalt körande frontend och backend i Chrome. Följande verifierades:
- permanent radering och kvarstående borttagning efter omladdning för
WAITING,IN_PROGRESSochCOMPLETED; - lång titel, radbrytning och korrekt uppgiftstitel i dialogen;
- initialt fokus på
Avbryt, tabb-ordning tillRadera, Escape och bakgrundsklick före anrop samt avsaknad av stängningskryss; - fördröjd delete-respons med kvarvarande och nedtonat kort, öppen låst modal och inaktiverade stängningsvägar;
- gemensam låsning av drag, status, ansvarig och ny radering för samma kort, samtidigt som andra kort förblev interaktiva;
- snabbt dubbelklick på
Raderautan dubbla delete-anrop; - vanligt serverfel där kort och modal låg kvar, felet visades och ett nytt försök lyckades;
404 TASK_NOT_FOUND, där det inaktuella kortet togs bort lokalt;- neutral sopkorgsknapp med 40 × 40 pixlars klickyta, inline-SVG och pointer-hantering som inte startade drag;
- desktopbredd 1440 × 1000 och mobilbredd 390 × 844 utan horisontell scrollning.
Inga problem upptäcktes i Feature 7-flödena.
Relaterade commits
- Feature-commit:
f296d15 - Merge-commit:
5df0146
Implementationsprinciper
Före implementation ska Codex läsa:
AGENTS.md
README.md
docs/architecture.md
docs/development.md
docs/roadmap.md
docs/decisions/
docs/features/005-task-status.md
docs/features/006-task-drag-and-drop.md
Codex ska även läsa relevant backendkod, frontendkod och befintliga tester. Repositoryts faktiska kod, tester och dokumentation har företräde framför antaganden i detta dokument.
Implementation, tester och relevant dokumentation ska uppdateras tillsammans. Codex ska inte committa, pusha, skapa pull request eller merga utan uttrycklig instruktion.