feat(fp): WP-24 — letter canvas (edit on the letter)
Some checks failed
CI / frontend (push) Failing after 59s
CI / storybook-a11y (push) Successful in 4m22s
CI / backend (push) Successful in 1m18s
CI / codeql (csharp) (push) Failing after 1m47s
CI / codeql (javascript-typescript) (push) Failing after 1m20s
CI / api-client-drift (push) Successful in 1m42s
CI / e2e (push) Failing after 3h8m54s
Some checks failed
CI / frontend (push) Failing after 59s
CI / storybook-a11y (push) Successful in 4m22s
CI / backend (push) Successful in 1m18s
CI / codeql (csharp) (push) Failing after 1m47s
CI / codeql (javascript-typescript) (push) Failing after 1m20s
CI / api-client-drift (push) Successful in 1m42s
CI / e2e (push) Failing after 3h8m54s
One letter surface for every role: LetterCanvasComponent renders the org template's letterhead/signature/footer around the case-type sections, with editableRegions content|template|none. public/letter.css is the FE⇄BE rendering contract (WP-25 inlines it verbatim). letter-preview deleted — its read-only rendering absorbed into 'none' mode. brief.machine.ts byte-identical; orgTemplate parses at the adapter boundary and lives beside the machine in BriefStore. Also fixes passage-picker multi-select (checkboxes all shared id="undefined", so labels only toggled the first box) and keeps the ±page-break marks from drawing through canvas content. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
154
src/app/brief/ui/letter-canvas/letter-canvas.stories.ts
Normal file
154
src/app/brief/ui/letter-canvas/letter-canvas.stories.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import type { Meta, StoryObj } from '@storybook/angular';
|
||||
import { Brief, LibraryPassage, allDiagnostics } from '@brief/domain/brief';
|
||||
import { OrgTemplate } from '@brief/domain/org-template';
|
||||
import { LetterCanvasComponent } from './letter-canvas.component';
|
||||
|
||||
const orgTemplate: OrgTemplate = {
|
||||
subOrgId: 'cibg-registers',
|
||||
orgName: 'CIBG — Registers',
|
||||
returnAddress: 'BIG-register\nPostbus 00000\n2500 AA Den Haag',
|
||||
footerContact: 'www.bigregister.nl\ninfo@voorbeeld.example\n070 000 00 00',
|
||||
footerLegal: 'Ons kenmerk vermelden bij correspondentie.',
|
||||
signatureName: 'A. de Vries',
|
||||
signatureRole: 'Hoofd Registratie',
|
||||
signatureClosing: 'Met vriendelijke groet,',
|
||||
margins: { topMm: 25, rightMm: 25, bottomMm: 25, leftMm: 25 },
|
||||
version: 1,
|
||||
};
|
||||
|
||||
const passages: LibraryPassage[] = [
|
||||
{
|
||||
passageId: 'p1',
|
||||
scope: 'global',
|
||||
sectionKey: 'kern',
|
||||
label: 'Standaard toelichting',
|
||||
version: 1,
|
||||
content: { paragraphs: [{ nodes: [{ type: 'text', text: 'Standaardtekst.' }] }] },
|
||||
},
|
||||
];
|
||||
|
||||
const brief: Brief = {
|
||||
briefId: 'b1',
|
||||
beroep: 'arts',
|
||||
templateId: 't1',
|
||||
drafterId: 'demo-drafter',
|
||||
status: { tag: 'draft' },
|
||||
placeholders: [
|
||||
{ key: 'naam_zorgverlener', label: 'Naam zorgverlener', autoResolvable: true },
|
||||
{ key: 'reden_besluit', label: 'Reden besluit', autoResolvable: false },
|
||||
],
|
||||
sections: [
|
||||
{
|
||||
sectionKey: 'aanhef',
|
||||
title: 'Aanhef',
|
||||
required: true,
|
||||
locked: true,
|
||||
blocks: [
|
||||
{
|
||||
type: 'passage',
|
||||
blockId: 'local-1',
|
||||
sourcePassageId: 'p1',
|
||||
sourceVersion: 1,
|
||||
edited: false,
|
||||
content: {
|
||||
paragraphs: [
|
||||
{
|
||||
nodes: [
|
||||
{ type: 'text', text: 'Geachte heer/mevrouw ' },
|
||||
{ type: 'placeholder', key: 'naam_zorgverlener' },
|
||||
{ type: 'text', text: ',' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionKey: 'kern',
|
||||
title: 'Kern van het besluit',
|
||||
required: true,
|
||||
locked: false,
|
||||
blocks: [
|
||||
{
|
||||
type: 'freeText',
|
||||
blockId: 'local-2',
|
||||
content: {
|
||||
paragraphs: [
|
||||
{
|
||||
nodes: [
|
||||
{ type: 'text', text: 'Wij hebben besloten om reden ' },
|
||||
{ type: 'placeholder', key: 'reden_besluit' },
|
||||
{ type: 'text', text: '.' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/** Enough repeated body text to push the surface past one A4 page. */
|
||||
const longBrief: Brief = {
|
||||
...brief,
|
||||
sections: brief.sections.map((s) =>
|
||||
s.sectionKey === 'kern'
|
||||
? {
|
||||
...s,
|
||||
blocks: [
|
||||
{
|
||||
type: 'freeText',
|
||||
blockId: 'local-long',
|
||||
content: {
|
||||
paragraphs: Array.from({ length: 40 }, (_, i) => ({
|
||||
nodes: [
|
||||
{
|
||||
type: 'text' as const,
|
||||
text: `Alinea ${i + 1}: de beoordeling van uw aanvraag is uitgevoerd volgens de geldende regels voor herregistratie in het BIG-register.`,
|
||||
},
|
||||
],
|
||||
})),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: s,
|
||||
),
|
||||
};
|
||||
|
||||
const meta: Meta<LetterCanvasComponent> = {
|
||||
title: 'Domein/Brief/Letter Canvas',
|
||||
component: LetterCanvasComponent,
|
||||
args: {
|
||||
brief,
|
||||
orgTemplate,
|
||||
availablePassages: passages,
|
||||
placeholders: brief.placeholders,
|
||||
diagnostics: allDiagnostics(brief),
|
||||
},
|
||||
};
|
||||
export default meta;
|
||||
type Story = StoryObj<LetterCanvasComponent>;
|
||||
|
||||
/** Drafter: content blocks editable in place; org-identity regions tinted read-only. */
|
||||
export const ContentMode: Story = { args: { editableRegions: 'content' } };
|
||||
|
||||
/** Approver/locked: the identical surface fully read-only, with the sample-values
|
||||
toggle and diagnostic placeholder chips (absorbs the old Letter Preview). */
|
||||
export const ReadOnly: Story = { args: { editableRegions: 'none' } };
|
||||
|
||||
export const ReadOnlyZonderBevindingen: Story = {
|
||||
args: { editableRegions: 'none', diagnostics: [] },
|
||||
};
|
||||
|
||||
/** Admin editor focus (consumer arrives in WP-26): body read-only, no "not yours" tint. */
|
||||
export const TemplateMode: Story = { args: { editableRegions: 'template' } };
|
||||
|
||||
export const Zoomed: Story = { args: { editableRegions: 'none', zoom: 0.6 } };
|
||||
|
||||
/** Long letter: the approximate ±page-break marks appear per A4 interval. */
|
||||
export const PageBreak: Story = {
|
||||
args: { editableRegions: 'none', brief: longBrief, diagnostics: [] },
|
||||
};
|
||||
Reference in New Issue
Block a user