Skip to content

Batches E and F: flows, gates and system cards

  • Route /admin/bulk-import · panels/BulkImport.tsx, BulkImportHelpers.ts.
  • Job: add or update many items from a spreadsheet, safely (preview first).
  • Reference: org3 (focused form), mgr2 (progress).
  • Layout: FlowLayout (page), steps:
    1. Upload — a big drop zone (org3 logo drop style): “Drop a CSV or Excel file here, or choose a file” + “or paste a table” (expands the textarea). Advanced JSON is behind “Use JSON instead” (disclosure).
    2. Match columns — the mapping grid (today’s modal becomes the step body): each field ← column select (“Don’t import”). Pre-filled by suggestMapping.
    3. Review — summary stat cards Create / Update / Warnings / Errors / Rows [loaded from preview], then the row table with status pills; error rows first. The footer primary is disabled while errors exist (“Fix {n} errors to continue”).
    4. Import — progress bar with “{processed} of {total} rows”, then a result summary and “View inventory →”.
    • footer: Back · primary “Preview” (step 2) / “Import {n} rows” (step 3). The file-job path (“Apply file job”) is chosen automatically for large files, so the user never picks between “Apply rows” and “Apply file job”.
  • States: unreadable file: “We couldn’t read that file. Save it as CSV or .xlsx and try again.” · no rows: “That file has no rows.” · job failed: “The import stopped. Nothing after row {n} was saved.” (only if the API reports it; otherwise the job error text).

E2. QR tools (print batch builder) — tab qr

Section titled “E2. QR tools (print batch builder) — tab qr”
  • Route /admin/qr-tools · panels/QrTools.tsx, QrImage.tsx. Module qr_print_batches.
  • Job: build a sheet of QR labels for items, units and boxes, then download them to print.
  • Reference: mgr4 (date cards → batch cards), mgr3 (columns + dashed add).
  • Layout: ListLayout (batches) → DetailLayout (a batch) as the working surface. It is not a strict wizard, because users add labels in any order.
    • Index: title “QR labels”, subtitle “Print labels for items, units and boxes.” · primary “New batch” · batch cards (title, “{n} labels”, created date). Today’s “Select a print batch” dropdown goes away.
    • Batch detail: back “← All batches”, title batch title, meta “{n} labels”.
      • actions: primary “Download all (ZIP)” (disabled at 0).
      • body left: “Add labels” card with a segmented control Item · Units · Reprint a unit (replaces three stacked forms), then fields + “Add to batch”.
      • body right/below: label grid (QR image + label text), dashed “+ Add labels” tile when empty.
  • States: no batches: “No label batches yet. Start one to print QR labels.” · empty batch: “This batch is empty. Add an item, units or a box.” · item with no units: “This item has no individual units yet.”

E3. Create makerspace — inside Users (core page), superadmin

Section titled “E3. Create makerspace — inside Users (core page), superadmin”
  • Route /admin/users (opened from the core Users page) · usersModals/CreateMakerspaceModal.tsx, CreationWizardSteps.tsx.
  • Reference: org3 (form + live preview).
  • Layout: FlowLayout, page presentation via ?create=makerspace (no route change). Today it is a modal with “Step 1 of 5” text.
    • stepper: Identity · Profile & hours · Modules · First staff · Review.
    • aside: live preview card (org3) showing space avatar tile, name, /m/{slug}, public code, and “Your catalogue will appear here”.
    • Identity: Name, Public code (4 chars, helper “Shown on labels and receipts”), Slug (prefix …/m/), Location.
    • Profile & hours: Timezone, Country, Currency, hours editor. Helper “Leave as is to use the pack or deployment defaults.”
    • Modules: Space pack picker, or “Choose modules myself” (switch) → module check-cards.
    • First staff: Email (optional), Role.
    • Review: key-value summary with “Edit” links per step.
    • footer: Cancel (text) · Back · Next / “Create makerspace”.
  • States: validation inline per field (not one sentence for all of step 1).

E4. Tenant migration — tab migration (superadmin)

Section titled “E4. Tenant migration — tab migration (superadmin)”
  • Route /admin/tenant-migration · TenantMigrationPanel.tsx, TenantMigrationDisclosure.tsx, TenantMigrationExports.tsx, TenantMigrationPairings.tsx, TenantMigrationImports.tsx, TenantMigrationIdentityDecisions.tsx.
  • Job: move one space from a managed deployment to a self-hosted one, irreversibly, in a safe order.
  • Reference: mgr2’s door-station card (strong, staged controls) + org5 danger zone.
  • Layout: FlowLayout (page) with a visible, persistent stepper, because the order is the safety model. Steps (with the side each one runs on):
    1. Review disclosure (source) — closure summary, identity list, acknowledgement checkbox, “Approve disclosure” / revoke.
    2. Pin deployments (both) — the pairing JSON fields, “Use this deployment’s identity”, “Pin pairing”.
    3. Encrypt export (source) — recipient key, “Create encrypted export”, job rows with “Download one-use archive”.
    4. Import & resolve (target) — archive + digest, “Start import”, per-person identity decisions.
    5. Verify & materialise (target) — verification stat cards (imported / resolved / dropped), “Materialise”.
    6. Cut over (both) — a danger zone card holding “Quiesce source”, “Archive source”, “Activate target”, “Abort target”, “Recover source”. Each one confirms by typing the space name.
    • aside: a status card per step (Not started / Done ✓ / Blocked: “needs step 2”).
    • Top callout (danger tint, replaces the red box): “This is one-way. Cut-over archives the source space; it isn’t deleted, and archives sit outside the purge guarantee.”
  • States: pairings loading as skeleton; each step’s error stays inside its step.
  • Route features/staff/ResetPasswordPage.tsx → auth/PasswordRecoveryFlow.tsx (code flow), auth/LegacyPasswordResetForm.tsx (uid/token link), auth/NewPasswordFields.tsx.
  • Reference: auth2 (set new password), auth3 (confirm card).
  • Layout: CenteredCardLayout per step (a 3-step flow rendered as a sequence of centred cards, not as FlowLayout):
    1. Request: icon tile (key) · “Reset your password” · “We’ll email you a code.” · Email · primary “Send code” · “Back to sign in”.
    2. Confirm: icon tile (mail) · “Check your email” · “We sent a code to {email}.” · Code · New password with strength meter + rule checks (auth2: “✓ At least 12 characters”) · Confirm · primary “Save new password” · secondary “Use a different email”.
    3. Success: icon tile (check) · “Password updated” · “You’ve been signed out on other devices.” · primary “Go to sign in”.
    • Unavailable: icon tile (warn) · “Password reset isn’t available” · body from the server · “Back to sign in”.
    • Legacy link: same as step 2 without the code field.
  • Copy: never confirm whether an email exists (“If that address has an account, a code is on its way.”) — keep whatever the current flow guarantees.

7. Batch F — Gates and system cards (CenteredCardLayout)

Section titled “7. Batch F — Gates and system cards (CenteredCardLayout)”

All of these use the same card: logo top-left, icon tile, title, body, one primary, one secondary.

# Screen Component · trigger Icon · title · body Primary / secondary
F1 Change-password gate staff/ChangePasswordGate.tsx · must_change_password lock · “Set a new password” · “{username} is using a temporary password. Choose your own to continue.” · fields Current / New (meter + rules) / Confirm Save new password / “Sign out” (text)
F2 MFA challenge / enrol auth/MfaFlow.tsx · login returns a challenge shield · Enrol: “Set up two-step sign-in” + QR (white tile) + “Can’t scan? Enter this key” (mono, Copy) · Verify: “Enter your 6-digit code” + “Use a recovery code instead” link · Codes: grid + Copy all / Download Verify / “Back to sign in”; codes: I’ve saved my codes · footnote “This sign-in expires in {n} minutes.”
F3 Access denied (single-tenant) staff/StaffAccessDenied.tsx lock · “You don’t have access to {space}” · “This console is only for {space}’s team. Sign in with an account that’s a member here.” Sign out / theme toggle moves to footer
F4 Recovery quarantine (superadmin) staff/RecoveryQuarantinePanel.tsx danger tile · eyebrow “Recovery quarantine” · “Staff access is paused” · reason · residual risk in a bordered danger box · confirm checkbox Lift quarantine (danger pill, disabled until ticked)
F5 Org invitation redeem organizations/OrganizationInvitationRedeemPage.tsx · /organization-invitations/redeem/:token auth4: overlapping avatar tiles (org + you) · “You’ve been invited to join” · org name (if known) · scope pill · “This link works once.” · Not signed in: Username or email + Password + Sign in and continue · Redeemed: success state “You’re in” + Open organizations footnote “Signed in as {user} · Switch account”. Owner decision: today redemption fires automatically once signed in. The UX spec asks for an explicit Accept invite click. Recommended (frontend-only: call the mutation on click), but it is a behaviour change.
F6 404 AppRoutes.NotFoundPage compass · eyebrow “404” · “We couldn’t find that page” · “The link may be old, or the page moved.” Go to home (/ or tenant home) / “Staff sign-in” (only on /admin*-like paths)
F7 Session / route loading StaffApp.StaffLoading, AppRoutes.RouteFallback logo + spinner · “Restoring your session…” / “Opening {space}…” none. Keep these messages in a role=status region
F8 No makerspace assigned StaffTabContent Panel title="No makerspace" empty tile · “No space assigned yet” · “Ask a space manager to add you to their team.” Sign out
F9 Panel crashed StaffPanelErrorBoundary in-page (not full-screen) danger-tinted empty card inside the current layout’s body · “This page couldn’t load” · “Something went wrong on our side. Reloading usually fixes it.” Reload / “Report details” (copies the error id if one exists)
F10 Tenant home unavailable AppRoutes.FamilyHome error / no public programme public variant inside PublicLayout: “We couldn’t load this space” + Try again · “{Space} hasn’t published anything yet. Check back soon.” —