Index of Annexures, one click
The Annexure Register subtab (Story-1886) already lists a
filing's child documents — label, description, pages, copy type —
ordered by annexurePosition. This story adds a single
Export index control that turns that exact live list into a
court-ready Index of Annexures as both a
PDF (browser print) and a real
.docx (Word). Generated on demand from the current query
data, so the export is live with the filing, never a stored
snapshot (RFD-DOC-003 D8).
What shipped
An outline Export index button (shared
Button + DropdownMenu primitives) sits in the
AnnexureRegisterTable header with two items: Download
PDF and Download Word (.docx). Copy is in
Filings.annexures.* for both en and
hi.
The export mirrors the on-screen rows one-for-one: Sr.
(annexurePosition → falls back to index), Annexure
(filingLabel), Description
(description → displayName → filename), Pages
(pageCount), Copy type (filingCopyType). No
second source of truth.
No PDF/DOCX library added (AGENTS.md). PDF is a print-styled HTML
document printed from a hidden iframe (→ the browser's
Save as PDF). The .docx is a hand-rolled minimal
STORED ZIP of three OOXML parts
([Content_Types].xml, _rels/.rels,
word/document.xml) — a real WordprocessingML file,
not an HTML-as-Word fake.
buildAnnexureIndexDocx and
buildAnnexureIndexHtml take no browser APIs and are
unit-tested (CRC32 + ZIP structure, row mapping, XML escaping, empty
state). The thin download*/print* wrappers do
the browser-only side effects on click.
Files
| File | Change |
|---|---|
src/components/matters/filings/annexure-index-export.ts |
New. Pure builders (print HTML + .docx bytes via a tiny
stored-ZIP/OOXML writer) plus the click-time browser wrappers. |
src/components/matters/filings/annexure-register-table.tsx |
Added the Export index dropdown to the panel header; the
register table itself is unchanged. |
src/components/matters/filings/annexure-index-export.test.ts |
New. Builder unit tests (DOCX magic + parts, row mapping, escaping, empty state; HTML fallbacks + positions). |
messages/en.json, messages/hi.json |
Filings.annexures.exportLabel / exportPdf / exportDocx in
both locales. |
Scope
- Only the export. The register tables' core (Story-1886) is untouched; Hearings (#1887) and Blake review (#1889) are out of scope.
-
Live, not a snapshot. The index is computed from the
current
useAppListDocumentAnnexuresdata each time the user exports — no persisted artifact, no backend export endpoint. - Empty state handled. Both builders render an explicit "No annexures" row, so an export never crashes or produces a blank table. (In the tab, the register only renders with data, but the generator is safe regardless.)
Token note (justified exception)
The PDF print HTML and the .docx carry plain CSS/OOXML colors
(e.g. #1a1a1a) rather than var(--token) design
tokens. These are standalone generated documents —
the PDF renders in an isolated print iframe and the
.docx opens in Word, neither of which can resolve the app's CSS
custom properties. No app UI surface uses a color literal; the register
header uses only token-backed utilities.
Verify
pnpm lint (0 errors),
tsc --noEmit (clean),
pnpm test (955 passing, incl. the new builder
tests), and pnpm build all green. The generated
.docx was round-tripped through unzip -t (no
errors) and xmllint (well-formed document.xml and
[Content_Types].xml). i18n added to both en and
hi.
Files changed
5 file(s), +454 / -7 lines
| Path | Role | + | - |
|---|---|---|---|
| messages/en.json | Config | +4 | -1 |
| messages/hi.json | Config | +4 | -1 |
| src/components/matters/filings/annexure-index-export.test.ts | Component | +81 | -0 |
| src/components/matters/filings/annexure-index-export.ts | Component | +317 | -0 |
| src/components/matters/filings/annexure-register-table.tsx | Component | +48 | -5 |