Scrum4Me/docs/old/story-dialog.md
Janpeter Visser b39c3ec2e1
docs(cleanup): archief verouderde plannen, backlog en root-duplicaten (#191)
* docs(cleanup): archief verouderde plannen, backlog en root-duplicaten

- 6 plans naar docs/old/plans/ (PBI-11/75/78, user-settings-store, Local github setup, lees-de-readme — laatste was verkeerde repo)
- docs/backlog/ naar docs/old/backlog/ (pre-MCP statische registry; live werk loopt via Scrum4Me-MCP)
- 6 root-level duplicaten naar docs/old/ (functional, {pbi,story,task}-dialog, product-backlog, backlog)
- 2 landing plans (niet uitgevoerd) krijgen archived: true frontmatter — blijven op plek maar uit INDEX
- scripts/generate-docs-index.mjs: skip docs/old/** + skip archived: true
- CLAUDE.md: rijen docs/backlog/, docs/plans/<key>-*.md, docs/manual/ weg; Track B-sectie verwijderd
- README.md / CHANGELOG.md / docs/plans/v1-readiness.md: link-fixes naar nieuwe locaties

Verify groen (lint + typecheck + 718 tests). docs/INDEX.md geregenereerd.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(cleanup): registreer handmatige verplaatsingen en fix referenties

- 4 plans verplaatst naar docs/old/plans/ (M10-qr-pairing-login, auto-pr-deploy-sync, docs-restructure-ai-lookup, v1-readiness)
- 3 archive-plans verplaatst naar docs/old/plans/ (archive-map nu leeg)
- ST-1114-copilot-reviews + 3 research-docs naar nieuwe docs/Ideas/ map
- Duplicaat docs/old/2026-04-27-m8-realtime-solo.md verwijderd (origineel zit in docs/old/plans/)
- Link-fixes naar nieuwe locaties:
  - CHANGELOG.md → docs/old/plans/v1-readiness.md
  - docs/runbooks/deploy-control.md → docs/old/plans/auto-pr-deploy-sync.md (2x)
  - docs/runbooks/worker-idempotency.md → docs/old/plans/auto-pr-deploy-sync.md
  - docs/plans/docs-restructure-pbi-spec.md → docs/old/plans/docs-restructure-ai-lookup.md (4x text + 2x href)
- docs/INDEX.md geregenereerd (96 docs, was 100)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 19:46:00 +02:00

8.8 KiB

title status audience language last_updated
StoryDialog Profiel active
maintainer
contributor
nl 2026-05-03

StoryDialog Profiel

Volgt docs/patterns/dialog.md (de generieke spec voor élke entity-dialog in Scrum4Me). Dit document beschrijft alleen de Story-specifieke afwijkingen en keuzes — alle gedeelde regels (layout, motion, demo-policy, foutcodes, validatie, theming, dialog-gedrag) staan in de generieke spec en worden hier niet herhaald.

Belangrijk: als een regel in dit profiel botst met de generieke spec, wint de generieke spec. Documenteer hier de afwijking + reden, of pas de generieke spec aan.


Velden

Veld Type Mode Validatie
code string | null beide optional, max 30 chars, mono-font, placeholder auto op create
title string (required) beide trim, 1-200 chars
priority int (1-4, P1 = hoogste) beide int 1-4, default 2 (overschrijfbaar via defaultPriority-prop bij create)
description string | null beide optional, plain textarea, placeholder Als… wil ik… zodat… (user-story-template)
acceptance_criteria string | null beide optional, plain textarea, placeholder - Gegeven… Als… Dan… (Gherkin-template)
status StoryStatus enum alleen edit read-only badge in header, niet bewerkbaar in deze dialog

StoryStatus enum: OPEN | IN_SPRINT | DONE (uppercase in DB).

Veld-specifiek gedrag

  • Code + Titel in één rij (grid-cols-[6rem_1fr])
  • Prioriteit via <PrioritySelect> (gedeelde primitive)
  • Description als <Textarea rows={3} resize-none> — géén auto-grow, géén markdown-hint binnen de dialog (afwijking van generieke spec; rationale: stories zijn meestal één zin)
  • Acceptatiecriteria idem — géén auto-grow, géén char-counter
  • Status wordt niet bewerkt vanuit deze dialog. Status verandert via lijst-acties (sleep naar sprint = IN_SPRINT, taak-completion = DONE). Read-only badge in dialog-header.

URL- of state-pattern

  • Gekozen: state-based (state: StoryDialogState | null prop, gerendeerd binnen StoryPanel)
  • Reden: StoryDialog leeft binnen StoryPanel met live-store-data (geselecteerde PBI bepaalt zichtbare stories); deep-linking zou parallelle data-fetch-paden vereisen.
  • State-shape:
    type StoryDialogState =
      | { mode: 'create'; pbiId: string; productId: string; defaultPriority?: number }
      | { mode: 'edit'; story: Story; productId: string }
    
  • Sluiten: onClose() callback uit de parent — setState(null) in StoryPanel.

Status-veld

  • Niet bewerkbaar in deze dialog — alleen weergegeven als badge in de header (edit-mode)
  • Default bij create: OPEN (server-default, niet expliciet gezet vanuit form)
  • Status-overgangen lopen via:
    • OPEN → IN_SPRINT — drag-and-drop naar een sprint of sprint-id zetten via story-actions
    • IN_SPRINT → DONE — alle taken op DONE zetten triggert auto-promotion (zie story-status-logic in actions/stories.ts)

Server actions

Actie Locatie Form-binding Revalidatie
createStoryAction actions/stories.ts via useActionState + <form action> (FormData) server-side revalidatePath op product-backlog
updateStoryAction actions/stories.ts idem idem
deleteStoryAction actions/stories.ts aangeroepen vanuit useTransition (geen form) server-side revalidatePath
getStoryLogsAction actions/stories.ts aangeroepen on-mount in edit-mode n.v.t. (read-only)

Alle write-acties zijn drielaags afgedekt (proxy-guard + server-action-check + DemoTooltip op submit-knop).


Speciale gedragingen

Header-presentatie (afwijking van generieke spec)

In edit-mode toont de dialog-header drie elementen boven op de standaard titel:

  1. Story-titel als dialog-title (groot)
  2. Story-code als monospace-badge rechtsboven (klein)
  3. Twee badges direct onder de titel: priority-badge (kleur via PRIORITY_COLORS) en status-badge (kleur via STATUS_COLORS)

Generieke spec gaat uit van een sobere header met alleen headline-small titel + optioneel een created_at-meta-string. StoryDialog wijkt hier bewust van af omdat status + priority belangrijke context zijn voor de gebruiker bij het openen van een story (vaak wisselt iemand vlot tussen meerdere stories).

Demo-modus = read-only weergave

Wanneer isDemo === true én isEdit === true, wordt het form vervangen door een read-only weergave:

  • description via gedeelde <Markdown>-wrapper (react-markdown + remark-gfm)
  • acceptance_criteria als plain whitespace-pre-line tekst

In create-mode is er voor demo-users niets te tonen — de dialog wordt alsnog geopend maar de submit-knop is disabled met <DemoTooltip>.

Dit "read-only-fallback"-patroon is uniek voor StoryDialog tot nu toe. Het zou geadopteerd kunnen worden door andere edit-dialogs zodra demo-flow-vereisten dat rechtvaardigen.

Activity-log (StoryLog) inline

In edit-mode wordt onder het form een <StoryLog>-paneel getoond met de chronologische logs van deze story (commit-hashes, status-transitions, etc.). Logs worden lazy-fetched via getStoryLogsAction(story.id) zodra de dialog opent.

Dit is een read-only side-panel en valt binnen de uitzondering die de generieke spec § 13 maakt voor <StoryLog>-style activity-rendering.

Delete-flow (afwijking van generieke spec)

Generieke spec § 10.4 vereist een AlertDialog voor delete-confirmatie. StoryDialog gebruikt in plaats daarvan een inline-confirm in dezelfde footer-rij:

[ Weet je het zeker? Taken worden ook verwijderd.   [Verwijderen]  [Annuleren] ]

Een AlertDialog zou een tweede modale laag toevoegen die in deze context onhandig voelt (de dialog zelf is al een interruptive overlay). De inline-confirm is een bewuste afwijking van de generieke spec.

Form-state via useActionState

Net als PbiDialog gebruikt StoryDialog useActionState + useFormStatus, niet react-hook-form. Dit is een toegestaan alternatief volgens de generieke spec § 2.

key-prop op <form>

Het <form> heeft key={isEdit ? story!.id : 'create'} — reset native form-state bij record-wissel of mode-switch.


Triggers

  • Create-trigger: + Story-knop in PanelNavBar van StoryPanelsetStoryDialogState({ mode: 'create', pbiId, productId, defaultPriority: 2 })
  • Edit-trigger: edit-icoon op een story-card in StoryPanelsetStoryDialogState({ mode: 'edit', story, productId })
  • Empty-state-trigger: Maak je eerste story aan-knop in EmptyPanel (zelfde state als create-trigger)

Bekende gaps t.o.v. generieke spec

Deze items wijken af van docs/patterns/dialog.md en horen in een vervolg-PR rechtgezet (niet onderdeel van de huidige docs-introductie).

  • Geen dirty-close-guard — Esc / backdrop / Cancel sluiten direct, ook met onopgeslagen wijzigingen. Generieke spec § 8.1 vereist een AlertDialog bij isDirty.
  • Geen Cmd/Ctrl+Enter shortcut — alleen klik op submit-knop.
  • Geen char-counter / markdown-hint op description / acceptance_criteria — bewust weggelaten, maar verdient expliciete bevestiging als design-keuze.
  • ⚠️ Inline-delete-confirm in plaats van AlertDialog (zie § Speciale gedragingen). Bewuste afwijking; de generieke spec mag deze variant expliciet toestaan, of dit profile moet als precedent gelden voor toekomstige dialogen.
  • ⚠️ Header-layout met meerdere badges wijkt af van de sobere header in § 4. Bewuste afwijking — context-zwaar bij story-wisselen.
  • ⚠️ Layout wijkt af van de generieke responsive-tabel: sm:max-w-lg met eigen max-h-[90vh] + flex flex-col i.p.v. de exacte max-w-[50vw] / 90vw / full-screen-progressie uit § 4.

Bewust NIET in v1

Specifiek voor StoryDialog (boven op de algemene out-of-scope-lijst in docs/patterns/dialog.md § 13):

  • Status bewerken vanuit de dialog (gebeurt via lijst-acties / drag-and-drop / auto-promotion)
  • Inline aanmaken van child-tasks (gebeurt via TaskDialog vanuit TaskPanel)
  • Bulk-edit over meerdere stories
  • Story-templates
  • Linking aan externe issues (GitHub / Linear) — staat op v1.1+ roadmap

Referenties

  • components/backlog/story-dialog.tsx — implementatie
  • actions/stories.ts — server actions (incl. getStoryLogsAction)
  • components/shared/priority-select.tsx — gedeelde priority-control
  • components/shared/story-log.tsx — activity-log paneel
  • components/shared/demo-tooltip.tsx — demo-policy laag 3
  • components/markdown.tsx — gedeelde markdown-wrapper
  • lib/task-status.ts — status-enum-mapper
  • docs/patterns/dialog.md — generieke spec (bron-of-truth)
  • docs/architecture.md — datamodel Story
  • docs/styling.md — MD3-tokens, status- en priority-kleuren