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>
155 lines
4.5 KiB
TypeScript
155 lines
4.5 KiB
TypeScript
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: [] },
|
|
};
|