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 (Files Module)

Every screen of the Files module, its intent, route, composition, states, permissions, platform behavior and events. Authoritative components in 00-shared/03; this file enumerates which ones each screen uses with module specifics. Structure mirrors design-docs/auth/05_Screen_Inventory.md.


Legend

States = idle / loading / success / empty / error(offline, rate, invalid) / disabled / permission. Analytics follow {module}.{screen}.{action} (proposed). Auth guards are (planned) (RBAC decorators exist on every route, guards not yet implemented).


1. File List — In-Context Section (/files, embedded)

FieldDetail
PurposeList a context's files (student, fee, circular) newest-first
SourceGET /api/v1/files → array createdAt desc (files.service.ts:48-50); client filters by its context key
WidgetsAppListTile rows: FileTypeIcon + originalName, mimeType, size, date; trailing AppMenu
Entrycontext screen "Files" section; pull-to-refresh re-fetches
Statesloading skeleton; empty AppEmptyState; offline AppOfflineBanner; permission (403) → locked tile
Permissionsfile.read (files.controller.ts:44)
Row actionsDownload (GET /:id/download), Detail sheet, Delete (admin, file.delete)
Analyticsfiles.list.refresh, files.list.open_detail (proposed)
NoteNo server pagination/filter — large tenants get full lists; client-side filter only (proposed)

2. File Picker / Upload Sheet (bottom sheet)

FieldDetail
PurposePick a local file → upload via multipart
Routesheet on context screen; FAB or "Attach" affordance
SourcePOST /api/v1/files/upload, field file (files.controller.ts:29-41)
Permissionsfile.upload (files.controller.ts:30)
Contentpicker row (system picker / camera (forward-looking)), selected-file preview card, Upload CTA
Statesidle → picking (system) → selected (validate) → uploading (progress, cancelled) → success/error
Cancellationclient-side abort; no server cancel endpoint
Analyticsfiles.upload.pick, files.upload.start, files.upload.success, files.upload.failure(code) (proposed)

3. Upload Progress (inline card / dialog)

FieldDetail
PurposeShow multipart transfer progress (client-computed; no server progress API)
WidgetsAppProgress + filename + size + Cancel text button
Terminal statessuccess → tile appears; error → inline retry (POST re-send, idempotency not server-enforced — retry creates a new record)
NoteServer buffers whole file in RAM; UI should treat >25 MB as risky (no cap enforced)

4. Download Progress (system notification on mobile / inline on web)

FieldDetail
PurposeFetch GET /:id/download and deliver bytes to OS
Permissionsfile.read (files.controller.ts:56)
WidgetsAppProgress row/notification; cancel aborts transport, not server work
Terminal statesdone → open with system viewer (share intent (forward-looking)); fail → retry (no Range/resume)
NoteServer sets Content-Disposition: attachment (files.controller.ts:61) — the OS decides save vs open

5. File Detail Sheet (/files/:id)

FieldDetail
PurposeMetadata + actions for one file
SourceGET /api/v1/files/:id → 404 File not found (files.service.ts:54)
Rowsname, type, size, uploaded date, provider id (dev only)
ActionsDownload; Delete (if file.delete); Copy name
Statesloading, not-found (deleted elsewhere → leave list), permission

6. Delete Confirmation Dialog

FieldDetail
PurposeConfirm permanent object deletion
SourceDELETE /api/v1/files/:id{ message: 'File deleted' } (files.controller.ts:66-71)
Permissionsfile.delete (files.controller.ts:67)
Copydestructive: "Delete file? The stored copy is removed permanently."
Terminalsuccess → optimistic removal; 404 → already gone, remove row silently

7. Permission-Denied / Locked State

FieldDetail
PurposeSurfaced when a role lacks file.read / file.upload / file.delete
Trigger403 from guard (planned); role lookup client-side fallback
WidgetsAppEmptyState with lock icon + "Ask admin for access"

8. Image Lightbox (forward-looking)

  • Full-screen view for image mimeTypes after download (buffer → Image.file); no server thumbnails yet (schema fields thumbnailFileId etc. unpopulated, file.schema.ts:31-37).

Shared components used

AppListTile, AppMenu, AppSnackbar, AppDialog, AppEmptyState, AppSkeleton, AppOfflineBanner, AppButton, AppBottomSheet, AppProgress, AppAvatar (sender/uploader contexts). Module-specific: FileTypeIcon, UploadProgressCard, DownloadManagerSheet, FileTile — defined in 07_Component_Library.md.

Analytics events (proposed)

files.list.{refresh,open_detail}, files.detail.{open,download,delete}, files.upload.{pick,start,success,failure,cancel}, files.download.{start,success,failure,retry}, files.delete.{confirm,cancel,success}.

Keyboard, landscape, tablet, desktop

  • Upload sheet: portrait bottom sheet; landscape/tablet → centered dialog ≤ 480 dp.
  • File list on tablet: master-detail (list ↔ detail sheet); desktop hover row highlight.
  • All sheets keyboard-aware; no text fields except optional caption (planned).