Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (Bulk Module)

Every screen of the Bulk module, its intent, route, composition, states, permissions, platform behaviour and events. Authoritative components in 00-shared/03; this file enumerates which ones each screen uses with module specifics. Full detail in 06_Screen_Specifications.md.


Legend

States = idle / loading / success / empty / error(offline, rate, invalid) / disabled / permission. Analytics events follow {module}.{screen}.{action} (proposed); SDK open — 00-shared/10 §8. Routes are (forward-looking).


1. Bulk Home / Upload (/admin/bulk)

FieldDetail
PurposeChoose entity + pick a CSV file; the entry point of the import wizard
Entryadmin nav "Import / Export"; post-error return from SS4
Exitvalid file + headers → /admin/bulk/preview; help → expandable
Inputsentity selector (hard-coded studentsstudents-import.adapter.ts:15; others (planned)), file picker (.csv)
Primary CTANext (disabled until file parses + headers recognized)
Secondary"Download template" (client-generated (forward-looking)); "Export instead" → SS5
Statesidle; picking; parsing (isolate — 15 §4); error (unreadable file, wrong extension, encoding/BOM failure); permission (client gate, 02 §7)
Contentcolumn contract summary (08 §1); max size hint 1000 rows / ~2 MB (10 §6)
Analyticsbulk.upload.pick, bulk.upload.parse_fail(reason) (proposed)
Keyboardfile picker is the only interaction; entity selector keyboardable
Adaptivedesktop/web primary; phone: single-column with compact file card
a11yfile drop-zone as a real button with label; parse errors live-region
Motionm-fast file card confirmation; errors shake

2. CSV Preview (/admin/bulk/preview)

FieldDetail
PurposeShow header map, row count, sample rows, contract warnings — before anything hits the server
EntrySS1 valid file
ExitNext/admin/bulk/confirm; Back → SS1; blocked warnings → stays
Dataclient-parsed CSV (columns:true, trim mirror of bulk-import.service.ts:26-30)
WidgetsCSVPreviewTable (module-specific), AppChips (required/optional/unknown header tags), AppAlert
Primary CTAImport N rows (disabled when blocking warnings exist)
Statespreview; warnings (unknown header, missing required — 08 §1); empty (no data rows → block, mirrors 400 bulk-import.service.ts:34-35)
Warningsnon-blocking: unknown columns ignored; blocking: required column missing
Analyticsbulk.preview.view, bulk.preview.warnings(n) (proposed)
Adaptivewide table on desktop; on phone horizontal scroll + sticky header column
a11ytable semantics, header associations, warning announcements
Motionrows fade-in m-fast; warnings expand m-base

3. Confirm (/admin/bulk/confirm)

FieldDetail
PurposeFinal go/no-go with the risk summary
EntrySS2
ExitStart import → SS4 (in-flight); Back → SS2
Content"N rows → N users + N student records"; duplicates/reference mismatches will be skipped, not imported (students-import.adapter.ts:49-56); re-upload is safe (idempotent)
Primary CTAStart import (filled)
Statesidle; (in-flight happens on SS4)
Analyticsbulk.confirm.start(n) (proposed)
a11ysummary as a list, not an image

4. Result & Error Review (/admin/bulk/result)

FieldDetail
PurposeRender the ImportReport and drive fix/re-upload
Entryafter confirm in-flight; deep-link from report URL (forward-looking)
ExitFix errors → SS1 (pre-highlight failed row numbers); View students → students list; Download report (client-synthesized CSV)
Data200 envelope data = ImportReport {entity,totalRows,imported,failed,errors[{rowNumber,errors[]}]} (import-adapter.interface.ts:14-25)
WidgetsImportSummaryCard, ErrorReviewTable (module-specific), AppSnackbar, AppEmptyState
Primary CTAsuccess: View students; partial: Fix errors; full fail: Fix errors
Statesin-flight (sync request — indeterminate bar; no progress events exist, bulk-import.service.ts:22-65); success (all rows); partial; failed-before-rows (400 malformed/empty :31-35, 404 entity :17-20); offline/429 (00-shared/07 §4); permission
Error groupingduplicates / reference-not-found / format (04 §7)
Analyticsbulk.result.view(imported,failed), bulk.result.download_errors (proposed)
Adaptiveerror table dense on phone; paginated > 50 errors
a11yreport summary live-region; table rows announced with row number
Motionsummary count-up m-base; errors expand/collapse

5. Export (/admin/bulk/export)

FieldDetail
PurposeDownload entity CSV
EntrySS1 secondary CTA; admin nav
Exitfile download; back to SS1
DataGET /api/v1/bulk/export/:entitytext/csv attachment <entity>.csv (bulk.controller.ts:50-60)
Widgetsentity selector, AppButton, AppSnackbar
Primary CTADownload CSV
Statesidle; downloading; empty (no rows → still a header-only CSV — stringify(rows,{header:true}) with [], bulk-import.service.ts:67-71); 404 entity
Noteexport ≠ import template (04 §6) — copy must say "roster snapshot"
Analyticsbulk.export.download(entity) (proposed)
Keyboardsingle selector + button

Shared components used

AppButton, AppTextField (entity override search (forward-looking)), AppSnackbar, AppCard, AppAlert, AppChips, AppEmptyState, AppSkeleton, AppOfflineBanner, AppDialog, AppMenu, AppFAB (SS5 "Import instead"). Module-specific: FileDropZone, CSVPreviewTable, ImportSummaryCard, ErrorReviewTable, ErrorRowTile, ImportStepper — defined in 07_Component_Library.md.

Analytics events (proposed)

bulk.upload.{pick,parse_fail}, bulk.preview.{view,warnings}, bulk.confirm.{start} (with row count), bulk.result.{view,download_errors, reupload} (imported/failed counts), bulk.export.{download}.

Keyboard, landscape, tablet, desktop

  • Preview/result tables: desktop full width; tablet two-pane (summary left, errors right); phone horizontal scroll, sticky first column.
  • File picker: desktop native dialog; phone file_selector/document picker.
  • All screens scroll; resizeToAvoidBottomInset where inputs exist (SS1 search field (forward-looking)).