← Back to Import module
UX Specification

Import module

UX Specification AzDO #4101

Bulk Content Importer — UX Specification

0552026-05-29
Contents
  1. 1. Feature Placement in the Information Architecture
  2. 2. Page Wireframes
  3. 3. User Flows
  4. 4. Interaction Patterns & Component Reuse
  5. 5. State Management & Persistence
  6. 6. Status Bar Integration
  7. 7. Responsive Behaviour
  8. 8. Error Handling & Edge Cases
  9. 9. Capability & Access Model
  10. 10. Admin Portal Integration
  11. 11. Notifications Summary
  12. 12. New Page Checklist

Bulk Content Importer — UX Specification

Feature: 055 — Bulk Content Importer

Created: 2026-05-29

Status: Draft

Reference spec: spec.md

IA Foundation: Platform Authoring App + Admin Portal patterns


1. Feature Placement in the Information Architecture

Primary Surface: Authoring App (Author View)

The Bulk Content Importer is an authoring workflow action — Authors use it from the same context where they create individual Objects. It belongs in the Author View as an elevated action, not as a separate sidebar destination or AI Tool card.

Rationale:

Entry Points

| Entry Point | Location | Trigger |
|---|---|---|
| **Primary** | Author View page header | `[+ Create ▾]` dropdown → "Bulk Import..." |
| **Secondary** | Folder Explorer context menu | Right-click folder → "Import files here..." (pre-selects folder) |
| **Tertiary** | Object List empty state | "Import files" CTA link |
| **API** | REST endpoint | `POST /api/workspaces/{id}/import-jobs` |

Route Structure


/ws/:workspaceId/authoring

 └── import/ → Import Jobs list

 ├── new → New Import Wizard

 ├── :jobId → Import Job detail / progress

 │ └── report → Import Report view

 └── configurations → Saved configurations

Note: The import wizard opens as a full-page flow (not a modal dialog) because it is a multi-step process with file uploads, validation, duplicate resolution, and configuration that would be cramped in a dialog.


2. Page Wireframes

2.1 Import Trigger — Author View Create Menu

The existing [+ Create] button in the Author View page header becomes a split button / dropdown:


┌────────────────────────────────────────────────────────────────────────┐

│ [Page header: "Authoring" Perspectives ▾ [+ Create ▾] ] │

│ │ │

│ ┌─────┴───────────────┐ │

│ │ New Object │ │

│ │ ───────────────── │ │

│ │ Bulk Import... │ │

│ │ From Configuration…│ │

│ └─────────────────────┘ │

└────────────────────────────────────────────────────────────────────────┘

2.2 Import Wizard — Multi-Step Flow

Route: /ws/:workspaceId/authoring/import/new

A full-page stepper with 5 steps. The user can navigate back to previous steps. The progress indicator shows completed / current / upcoming steps.


┌─────────────────────────────────────────────────────────────────────────────┐

│ [← Back to Authoring] │

│ │

│ ┌─────────────────────────────────────────────────────────────────────┐ │

│ │ ① Upload ── ② Configure ── ③ Validate ── ④ Resolve ── ⑤ Submit│

│ │ ● ○ ○ ○ ○ │

│ └─────────────────────────────────────────────────────────────────────┘ │

│ │

│ ┌─────────────────────────────────────────────────────────────────────┐ │

│ │ │ │

│ │ [Step Content Area] │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────────────┘ │

│ │

│ ┌─────────────────────────────────────────────────────────────────────┐ │

│ │ [Cancel] [← Previous] [Next →] │ │

│ └─────────────────────────────────────────────────────────────────────┘ │

└─────────────────────────────────────────────────────────────────────────────┘

#### Step 1: Upload


┌─────────────────────────────────────────────────────────────────────┐

│ Upload Files │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌─────────────────────────────────────────────────────────────┐ │

│ │ │ │

│ │ ┌───────────────────────────────────┐ │ │

│ │ │ 📂 │ │ │

│ │ │ Drag & drop a .zip archive here │ │ │

│ │ │ or click to browse │ │ │

│ │ │ │ │ │

│ │ │ Accepted: .zip │ │ │

│ │ │ Max batch: 2 GB · Max files: 1000│ │ │

│ │ └───────────────────────────────────┘ │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ── Manifest (optional) ── │

│ ┌─────────────────────────────────────────────────────────────┐ │

│ │ 📄 Upload manifest.json or manifest.csv │ │

│ │ [Browse...] │ │

│ │ ⓘ Manifests provide per-file metadata overrides │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ── Upload Progress (after file selected) ── │

│ ┌─────────────────────────────────────────────────────────────┐ │

│ │ content-batch.zip (148 MB) │ │

│ │ ████████████████████░░░░ 78% Uploading... │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ── Archive Contents Preview (after upload) ── │

│ ┌─────────────────────────────────────────────────────────────┐ │

│ │ 📁 content-batch.zip — 47 files detected │ │

│ │ ├── 📄 procedure-oil-change.dita (DITA Task) │ │

│ │ ├── 📄 concept-filters.dita (DITA Concept) │ │

│ │ ├── 📄 overview.md (Markdown) │ │

│ │ ├── 🖼 diagram.svg (Graphics) │ │

│ │ ├── 📄 parts-list.xlsx (Excel) │ │

│ │ └── ... 42 more files │ │

│ │ │ │

│ │ Summary: 32 DITA · 5 Markdown · 4 Graphics · 6 Other │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

└─────────────────────────────────────────────────────────────────────┘

States:


#### Step 2: Configure


┌─────────────────────────────────────────────────────────────────────┐

│ Configure Import │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Saved Configuration ──────────────────────────────────────┐ │

│ │ [Load from saved ▾] OR configure manually below │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Destination ──────────────────────────────────────────────┐ │

│ │ │ │

│ │ Target Workspace: [Current workspace — locked] │ │

│ │ │ │

│ │ Destination Folder: │ │

│ │ ┌────────────────────────────────────────────────────┐ │ │

│ │ │ [None (loose Objects)] ▾ │ │ │

│ │ │ ────────────────────── │ │ │

│ │ │ ▸ Folder A │ │ │

│ │ │ ▾ Folder B │ │ │

│ │ │ ▸ Folder B1 │ │ │

│ │ │ ▸ Folder C │ │ │

│ │ └────────────────────────────────────────────────────┘ │ │

│ │ │ │

│ │ ☐ Create subfolders from archive directory structure │ │

│ │ ⓘ Mirrors the .zip folder hierarchy under the │ │

│ │ selected destination folder │ │

│ │ (disabled when no destination folder is selected) │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Initial Status ──────────────────────────────────────────┐ │

│ │ │ │

│ │ ○ Pre-Draft (recommended) │ │

│ │ Objects require review before entering editorial workflow │ │

│ │ │ │

│ │ ○ Draft │ │

│ │ Objects enter editorial workflow immediately │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Work Package (optional) ──────────────────────────────────┐ │

│ │ │ │

│ │ Associate with Work Package: │ │

│ │ [🔍 Search work packages... ▾] │ │

│ │ │ │

│ │ ⓘ Improves AI metadata suggestion accuracy by providing │ │

│ │ product and release context │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── AI Metadata ──────────────────────────────────────────────┐ │

│ │ │ │

│ │ ☑ Enable AI metadata suggestion for files without │ │

│ │ manifest entries │ │

│ │ │ │

│ │ ⓘ The AI will suggest values from active MetadataDomain │ │

│ │ definitions. All suggestions are clearly marked in the │ │

│ │ import report. │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Save Configuration ───────────────────────────────────────┐ │

│ │ ☐ Save this configuration for reuse │ │

│ │ Name: [________________________________] │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

└─────────────────────────────────────────────────────────────────────┘

Interactions:


#### Step 3: Validate (Auto Dry-Run)

After clicking "Next" from Configure, the system automatically runs a dry-run validation. This step shows results.


┌─────────────────────────────────────────────────────────────────────┐

│ Validation Results │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Summary ─────────────────────────────────────────────────┐ │

│ │ ✅ 42 files ready to import │ │

│ │ ⚠️ 3 files with warnings │ │

│ │ ❌ 2 files will be skipped (errors) │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Issues ───────────────────────────────────────────────────┐ │

│ │ [Filter: All ▾ | Errors only | Warnings only] │ │

│ ├─────────────────────────────────────────────────────────────┤ │

│ │ │ │

│ │ ❌ legacy-proc.dita │ │

│ │ Error: Invalid DITA schema — missing <title> element │ │

│ │ │ │

│ │ ❌ broken.xml │ │

│ │ Error: Not valid XML — parse error at line 14 │ │

│ │ │ │

│ │ ⚠️ overview.md │ │

│ │ Warning: Missing required metadata "product-line" │ │

│ │ (will be AI-suggested or flagged as gap) │ │

│ │ │ │

│ │ ⚠️ readme.txt │ │

│ │ Warning: Template "plain-text" not enabled in │ │

│ │ workspace — file will be skipped │ │

│ │ │ │

│ │ ⚠️ manifest references "missing-file.dita" │ │

│ │ Warning: File not found in archive — entry ignored │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ [Download validation report (CSV)] │

│ │

│ ───────────────────────────────────────────────────────────────── │

│ ⓘ No Objects have been created. Review issues above. │

│ You can go back to fix your archive or proceed to duplicate │

│ detection. │

│ │

└─────────────────────────────────────────────────────────────────────┘

States:


#### Step 4: Resolve Duplicates

This step only appears if duplicates are detected. If none are found, the wizard skips from ③ directly to ⑤.


┌─────────────────────────────────────────────────────────────────────┐

│ Duplicate Detection │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ⚠️ 3 files match existing Objects in this workspace. │

│ You must resolve each match before the import can proceed. │

│ │

│ ┌── Match 1 of 3 ────────────────────────────────────────────┐ │

│ │ │ │

│ │ &#128196; procedure-oil-change.dita │ │

│ │ ──────────────────────────── │ │

│ │ Matches: "Oil Change Procedure" (Object ID: obj-abc123) │ │

│ │ Match type: Title + Content hash (98% similar) │ │

│ │ │ │

│ │ Resolution: │ │

│ │ ○ Skip — do not import this file │ │

│ │ ○ Create new Object — import as a separate Object │ │

│ │ ○ Create new Subversion — add as a new Subversion of │ │

│ │ the existing Object │ │

│ │ ⓘ Only available if no editable Subversion exists │ │

│ │ ✅ Available — Version 2 has no editable Subversion │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Match 2 of 3 ────────────────────────────────────────────┐ │

│ │ &#128196; concept-filters.dita │ │

│ │ Matches: "Filter Types Overview" (obj-def456) │ │

│ │ Match type: Title match (content differs) │ │

│ │ │ │

│ │ Resolution: │ │

│ │ ○ Skip │ │

│ │ ● Create new Object ← selected │ │

│ │ ○ Create new Subversion │ │

│ │ ⚠️ Unavailable — Version 1 has an editable Subversion │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Match 3 of 3 ────────────────────────────────────────────┐ │

│ │ ... (same pattern) │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ───────────────────────────────────────────────────────────────── │

│ Resolved: 2 / 3 [Next →] ← disabled until all resolved │

│ │

└─────────────────────────────────────────────────────────────────────┘

Key rule: "Next" is disabled until every detected match has a resolution selected. This enforces the blocking gate from FR-013.


#### Step 5: Submit (Confirmation)


┌─────────────────────────────────────────────────────────────────────┐

│ Review & Submit │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Import Summary ───────────────────────────────────────────┐ │

│ │ │ │

│ │ Files to import: 45 │ │

│ │ Files to skip: 2 (validation errors) │ │

│ │ Duplicates resolved: 3 (1 skip · 1 new · 1 subver.) │ │

│ │ │ │

│ │ Destination: Folder B / (subfolders enabled) │ │

│ │ Initial status: Pre-Draft │ │

│ │ Work Package: WP-Migration-Q3 │ │

│ │ AI metadata: Enabled │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Estimated Duration ───────────────────────────────────────┐ │

│ │ ⏱ Approximately 8–12 minutes for 45 files │ │

│ │ You will receive a notification when the import completes. │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ [Cancel] [← Back] [Start Import] │

│ │

└─────────────────────────────────────────────────────────────────────┘

Clicking [Start Import] triggers a Radix AlertDialog confirmation:


┌─────────────────────────────────────────────┐

│ Start bulk import? │

│ │

│ This will create up to 45 Objects in │

│ workspace "Production". │

│ │

│ You can monitor progress or navigate away. │

│ │

│ [Cancel] [Start Import] │

└─────────────────────────────────────────────┘

2.3 Import Job Progress (Active Job View)

Route: /ws/:workspaceId/authoring/import/:jobId

After submission the user is navigated here automatically. They can also return at any time.


┌─────────────────────────────────────────────────────────────────────┐

│ [← Back to Authoring] [Cancel Import] │

│ │

│ Import Job: imp-789xyz │

│ Submitted: May 29, 2026 at 14:32 by John Doe │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Progress ─────────────────────────────────────────────────┐ │

│ │ │ │

│ │ Status: ⏳ Processing │ │

│ │ │ │

│ │ ████████████████████████░░░░░░░░░░ 62% │ │

│ │ 28 / 45 files processed │ │

│ │ │ │

│ │ Current file: maintenance-schedule.dita │ │

│ │ │ │

│ │ ✅ 26 created · ⚠️ 1 warning · ❌ 1 skipped │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ┌── Live Activity Feed ───────────────────────────────────────┐ │

│ │ │ │

│ │ 14:34:12 ✅ Created "Oil Change Procedure" (obj-abc...) │ │

│ │ 14:34:10 ✅ Created "Filter Concept" (obj-def...) │ │

│ │ 14:34:08 ⚠️ "overview.md" — metadata gap: product-line │ │

│ │ 14:34:05 ❌ "broken.xml" — skipped: parse error │ │

│ │ 14:34:02 ✅ Created "Parts List" (obj-ghi...) │ │

│ │ ... │ │

│ │ [Auto-scrolling ↓] │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

└─────────────────────────────────────────────────────────────────────┘

Real-time updates: Delivered via SignalR through PlatformHub. Progress bar, counters, and activity feed update without page refresh.

Job status states:

| Status | Visual |
|---|---|
| Pending | Grey, spinner, "Queued..." |
| Processing | Blue progress bar, live feed |
| Completed | Green checkmark, link to report |
| Completed with warnings | Amber checkmark, link to report |
| Failed | Red X, error summary, link to partial report |
| Cancelled | Grey X, "Cancelled by user" |

On completion:


┌─────────────────────────────────────────────────────────────────────┐

│ Import Job: imp-789xyz │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Result ───────────────────────────────────────────────────┐ │

│ │ │ │

│ │ ✅ Completed with warnings │ │

│ │ │ │

│ │ Duration: 9 minutes 42 seconds │ │

│ │ Objects created: 43 │ │

│ │ Files skipped: 2 │ │

│ │ Warnings: 4 │ │

│ │ │ │

│ │ [View Import Report] [Download Report (CSV)] │ │

│ │ [View Created Objects in Authoring] │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────┘ │

└─────────────────────────────────────────────────────────────────────┘

2.4 Import Report

Route: /ws/:workspaceId/authoring/import/:jobId/report


┌─────────────────────────────────────────────────────────────────────────────┐

│ [← Back to Job] [Download CSV] │

│ │

│ Import Report — imp-789xyz │

│ ───────────────────────────────────────────────────────────────────────── │

│ │

│ ┌── Summary Bar ─────────────────────────────────────────────────────┐ │

│ │ Total: 47 │ ✅ Created: 43 │ ⚠️ Warnings: 4 │ ❌ Skipped: 2 │ │

│ └────────────────────────────────────────────────────────────────────┘ │

│ │

│ [Filter: All ▾ | Created | Warnings | Skipped] [&#128269; Search filename...] │

│ │

│ ┌── Report Table ─────────────────────────────────────────────────────┐ │

│ │ Source File │ Outcome │ Object ID │ Title │ Status │ │

│ ├─────────────────────────────────────────────────────────────────────┤ │

│ │ procedure-oil.dita │ ✅ │ obj-abc123 │ Oil Change │ Pre-D │ │

│ │ concept-filters.dita │ ✅ │ obj-def456 │ Filter Types │ Pre-D │ │

│ │ overview.md │ ✅ ⚠️ │ obj-ghi789 │ Overview │ Pre-D │ │

│ │ broken.xml │ ❌ │ — │ — │ — │ │

│ │ ... │ │ │ │ │ │

│ └─────────────────────────────────────────────────────────────────────┘ │

│ │

│ ── Expanded Row Detail (click row to expand) ── │

│ ┌─────────────────────────────────────────────────────────────────────┐ │

│ │ &#128196; overview.md → Object "Overview" (obj-ghi789) │ │

│ │ │ │

│ │ Metadata Applied: │ │

│ │ ┌────────────────────────────────────────────────────────────┐ │ │

│ │ │ Field │ Value │ Source │ │ │

│ │ │ product-line │ Hydraulic Systems │ &#129302; AI-suggested │ │ │

│ │ │ language │ EN │ &#128203; Manifest │ │ │

│ │ │ department │ (gap) │ ⚠️ Unavailable │ │ │

│ │ └────────────────────────────────────────────────────────────┘ │ │

│ │ │ │

│ │ Warning: Required metadata "department" could not be suggested │ │

│ │ │ │

│ └─────────────────────────────────────────────────────────────────────┘ │

│ │

└─────────────────────────────────────────────────────────────────────────────┘

Key details:


2.5 Import Jobs List

Route: /ws/:workspaceId/authoring/import/

Accessible from a persistent Import Jobs link in the Author View page header (small badge shows active job count).


┌─────────────────────────────────────────────────────────────────────┐

│ [← Back to Authoring] [+ New Import] │

│ │

│ Import Jobs │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ [Filter: All ▾ | Active | Completed | Failed] │

│ │

│ ┌── Jobs Table ───────────────────────────────────────────────┐ │

│ │ Job ID │ Files │ Status │ Submitted │ │

│ ├─────────────────────────────────────────────────────────────┤ │

│ │ imp-789xyz │ 47 │ ⏳ Processing (62%) │ 14:32 today │ │

│ │ imp-456abc │ 120 │ ✅ Completed │ Yesterday │ │

│ │ imp-123def │ 8 │ ⚠️ Partial │ May 27 │ │

│ │ imp-999ghi │ 200 │ ❌ Failed │ May 25 │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ Click a row to view job details and report. │

│ │

└─────────────────────────────────────────────────────────────────────┘

2.6 Platform Notification (On Completion)

Delivered via PlatformHub SignalR push and shown in the existing notification tray:


┌────────────────────────────────────────────────────┐

│ &#128229; Bulk Import Complete │

│ ────────────────────────────────── │

│ Your import (47 files) completed with warnings. │

│ 43 Objects created · 2 skipped · 4 warnings │

│ │

│ [View Report] │

│ │

│ 2 minutes ago │

└────────────────────────────────────────────────────┘

2.7 Saved Configurations

Route: /ws/:workspaceId/authoring/import/configurations

Accessible from the Configure step "Load from saved" dropdown and from the Import Jobs list header.


┌─────────────────────────────────────────────────────────────────────┐

│ [← Back] │

│ │

│ Import Configurations │

│ ───────────────────────────────────────────────────────────────── │

│ │

│ ┌── Configurations Table ─────────────────────────────────────┐ │

│ │ Name │ Folder │ Status │ Actions │ │

│ ├─────────────────────────────────────────────────────────────┤ │

│ │ Migration Q3 │ /docs/manuals │ Pre-Draft │ ▶ ✏ &#128465; │ │

│ │ Weekly content drop │ /incoming │ Draft │ ▶ ✏ &#128465; │ │

│ └─────────────────────────────────────────────────────────────┘ │

│ │

│ ▶ = Start new import with this configuration │

│ ✏ = Edit configuration │

│ &#128465; = Delete (Radix AlertDialog confirmation required) │

│ │

└─────────────────────────────────────────────────────────────────────┘

3. User Flows

Flow 1: Standard Bulk Import (Happy Path)


Author is in /authoring

 → clicks [+ Create ▾] → "Bulk Import..."

 → navigates to /authoring/import/new

 Step 1: Upload

 → drags .zip onto drop zone → upload progress → archive preview shown

 → optionally uploads manifest.json

 → clicks [Next →]

 Step 2: Configure

 → selects destination folder from tree

 → enables subfolder mirroring

 → keeps Pre-Draft status (default)

 → optionally associates Work Package

 → clicks [Next →]

 Step 3: Validate (auto dry-run)

 → spinner: "Validating 47 files..."

 → results shown: 45 ready, 2 errors

 → reviews errors → acceptable, will be skipped

 → clicks [Next →]

 Step 4: Resolve Duplicates (3 found)

 → reviews each match → selects resolution

 → all 3 resolved → Next enabled

 → clicks [Next →]

 Step 5: Submit

 → reviews summary → clicks [Start Import]

 → AlertDialog confirmation → confirms

 → navigated to /authoring/import/{jobId}

 → progress bar + live feed updates via SignalR

 → Author navigates away to other work

 → platform notification arrives: "Import complete"

 → clicks [View Report] → import report page

 → clicks [View Created Objects in Authoring]

 → /authoring with destination folder selected

Flow 2: Import from Folder Context Menu


Author right-clicks "Manuals" folder in Folder Explorer

 → context menu → "Import files here..."

 → navigates to /authoring/import/new?folder={folderId}

 → Step 2: Configure — destination folder pre-selected to "Manuals"

 → (continues as Flow 1)

Flow 3: Import with Saved Configuration


Author clicks [+ Create ▾] → "From Configuration..."

 → config picker dialog opens

 → selects "Migration Q3"

 → navigates to /authoring/import/new?config={configId}

 → Step 1: Upload (normal — config doesn't include files)

 → Step 2: Configure — all settings pre-populated

 → (continues as Flow 1)

Flow 4: Dry-Run Only (No Import Submitted)


Author completes Steps 1–3 of the wizard

 → on Step 3 (Validate), reviews the report

 → decides too many errors to proceed

 → clicks [Download validation report (CSV)]

 → downloads offline report

 → clicks [Cancel] or [← Back to Authoring]

 → wizard state cleared

 → no Objects created

Flow 5: Return to Active Import Job


Author navigated away during import

 → sees orange badge "1" on Import Jobs indicator in Authoring page header

 → clicks badge → /authoring/import/

 → active job at top with live progress

 → clicks job row → /authoring/import/{jobId}

 → current progress shown (restored from server state)

 → SignalR reconnects for live updates

Flow 6: Cancel an Active Import


Author is on /authoring/import/{jobId}

 → clicks [Cancel Import]

 → AlertDialog: "Cancel this import? Objects already created will not be removed."

 → confirms

 → job status → Cancelled

 → partial results remain accessible in report

Flow 7: API-Triggered Import


External system:

 POST /api/workspaces/{id}/import-jobs

 Body: multipart archive + configuration JSON

 Headers: Authorization: Bearer {token}

 

 → API validates: auth, bulk-import capability, workspace exists

 → 202 Accepted + { jobId: "imp-xyz" }

 → integrator polls GET /api/import-jobs/{jobId}/status

 → on completion: GET /api/import-jobs/{jobId}/report

Flow 8: Insufficient Capability (Access Denied)


Author without bulk-import capability opens [+ Create ▾]

 → "Bulk Import..." shown disabled

 → tooltip: "You need the 'bulk-import' capability to import content"

 → no navigation occurs

4. Interaction Patterns & Component Reuse

| Pattern | Reused From | Notes |
|---|---|---|
| Folder tree picker | Folder Explorer (§5.1) | Same tree component, rendered inline in Step 2 |
| File drop zone | Staging Area upload | Same drag-drop component |
| Progress bar + live feed | — (new) | Backed by SignalR `PlatformHub` |
| Stepper / multi-step wizard | — (new) | Should become a shared component |
| Data table with expandable rows | Object List (§5.2) | Sortable, filterable, click-to-expand |
| Destructive confirmation | Shared pattern (§4.5) | Radix AlertDialog for Start, Cancel, Delete |
| Context menu | Shared pattern (§4.6) | Folder right-click reuses existing pattern |
| Toast notifications | Admin patterns (§A4.10) | Non-blocking success feedback |
| Platform notification | Existing notification system | SignalR push + notification tray |
| Empty state | Shared pattern (§4.2) | "No imports yet" + CTA |
| Error state | Shared pattern (§4.3) | `<ErrorState>` with retry |
| Loading skeleton | Shared pattern (§4.4) | Per wizard step, job page, report table |

5. State Management & Persistence

Wizard State

| Concern | Approach |
|---|---|
| File upload | Uploaded to blob storage immediately in Step 1; server-side reference retained 24h |
| Configuration | Client state during wizard; saved to server on submit |
| Validation results | Server-side; returned as response body and displayed in Step 3 |
| Duplicate resolutions | Client state through Step 4; sent with final submission payload |

If the user navigates away mid-wizard the upload is retained in blob storage for 24h but wizard state is not restored — the user must restart the wizard.

Job Progress State

| Concern | Approach |
|---|---|
| Real-time progress | SignalR push through `PlatformHub` workspace group (FR-008) |
| Progress persistence | Server persists file counters in `ImportJob` entity |
| Reconnection | On page load, client fetches current state via REST then subscribes to SignalR for live updates |
| Activity feed | Last N entries stored server-side; real-time additions via SignalR |

6. Status Bar Integration

Phase 1 (before Action Tray ships)

Until the Action Tray (batch operations Phase 2) is available, import job progress surfaces in the existing Status Bar background task slot:


┌──────────────────────────────────────────────────────────────────────┐

│ [workflow state] [Import: 28/45 ████████░░ 62%] [other tasks] │

└──────────────────────────────────────────────────────────────────────┘

Phase 2+ (after Action Tray ships)

Once the Action Tray is available (see batch-operations-and-agent-interaction-ux-research.md §5.2), import job progress moves to the collapsed Tray strip — the canonical location for all background task progress — rather than the Status Bar directly. This avoids the two surfaces competing for the same vertical slot.


├──────────────────────────────────────────────────────────────────────┤

│ ▲ Tray [Import: 28/45 ██████████░░ 62%] [View ▶] [✕] │

├──────────────────────────────────────────────────────────────────────┤

│ [Status bar] │

└──────────────────────────────────────────────────────────────────────┘

7. Responsive Behaviour

| Breakpoint | Wizard Layout |
|---|---|
| Desktop (≥ 1024px) | Full-width stepper, side-by-side summary panels |
| Tablet (768–1024px) | Same stepper, stacked panels |
| Mobile (< 768px) | Stepper collapses to step number only; single column; no drag-drop zone (file picker only) |

The wizard is a desktop-primary experience. Mobile use is supported at a reduced fidelity.


8. Error Handling & Edge Cases

| Scenario | UX Response |
|---|---|
| Upload fails (network) | Retry button in drop zone; already-uploaded bytes retained |
| Archive exceeds size limit | Immediate inline error: "Batch exceeds 2 GB limit" — Next disabled |
| File count exceeds limit | Inline error in archive preview: "1,200 files exceeds the 1,000 file limit" |
| Manifest syntax error | Blocking error in Step 1, highlighted details; Next disabled |
| Workspace deleted mid-import | Job fails; notification: "Workspace not found — import aborted" |
| Capability revoked mid-import | Job aborted; notification: "Import cancelled — access revoked" |
| AI service unavailable | Import continues; report notes "AI suggestion unavailable"; gaps flagged as warnings (per clarification) |
| SignalR disconnects | "Connection lost — reconnecting..." banner above progress bar; auto-retry |
| Max folder nesting depth exceeded | Subfolders flattened to deepest permitted level; warning in import report |

9. Capability & Access Model

| Capability Required | Action |
|---|---|
| `bulk-import` | Submit import jobs; cancel own jobs |
| `object.read` | View and download import reports (any workspace member) |
| `folder.write` | Required when a destination folder is specified |
| Admin role | Cancel or delete any user's jobs |

UI visibility rules:


10. Admin Portal Integration

The Admin Portal has no dedicated Bulk Import page, but is affected in two places:

Workspace Settings — Import Limits section

Added under /c/:customerId/ws/:workspaceId/settings:


┌── Import Limits ──────────────────────────────────────────────┐

│ Max file size (MB): [50] │

│ Max batch size (MB): [2048] │

│ Max file count: [1000] │

│ [Save] │

└────────────────────────────────────────────────────────────────┘

Roles Page — new capability

The bulk-import capability appears in the capability list when creating or editing a custom role.


11. Notifications Summary

| Event | Channel | Recipient |
|---|---|---|
| Job submitted | Toast | Submitter |
| Job progress | SignalR live (PlatformHub) | Submitter (on page) |
| Job completed | Platform notification | Submitter |
| Job failed | Platform notification | Submitter |
| Job cancelled | Platform notification | Submitter |
| Object created / file skipped | Audit log | System |

12. New Page Checklist

Per IA convention (§11 and §A8):