-
Notifications
You must be signed in to change notification settings - Fork 3
Add workspace components architecture documentation for #108 #502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a8662fd
0862d2c
4a445d8
fd89b44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,378 @@ | ||||||||||||||
| # Workspace Components Architecture | ||||||||||||||
|
|
||||||||||||||
| Issue: #108 | ||||||||||||||
|
|
||||||||||||||
| This document explains the workspace region components used for line-by-line manuscript transcription in TPEN interfaces. | ||||||||||||||
|
|
||||||||||||||
| ## Purpose | ||||||||||||||
|
|
||||||||||||||
| Provide specialized components that work together to display manuscript lines, capture transcriptions, and maintain context during the annotation workflow. | ||||||||||||||
|
|
||||||||||||||
| ## Scope | ||||||||||||||
|
|
||||||||||||||
| In scope: | ||||||||||||||
|
|
||||||||||||||
| 1. Core workspace components and their responsibilities | ||||||||||||||
| 2. Line-by-line navigation and focus behavior | ||||||||||||||
| 3. Transcription input, autosave, and draft persistence | ||||||||||||||
| 4. Image display and region coordination | ||||||||||||||
| 5. Component communication via events and attributes | ||||||||||||||
| 6. Data flow between workspace and interface shell | ||||||||||||||
|
|
||||||||||||||
| Out of scope: | ||||||||||||||
|
|
||||||||||||||
| 1. Header/navigation components (covered in main architecture doc) | ||||||||||||||
| 2. Split-screen tools (covered in splitscreen tools architecture) | ||||||||||||||
| 3. Backend storage implementation | ||||||||||||||
| 4. IIIF manifest structure details | ||||||||||||||
|
|
||||||||||||||
| ## Component Inventory | ||||||||||||||
|
|
||||||||||||||
| ### 1. tpen-transcription-block | ||||||||||||||
|
|
||||||||||||||
| **Purpose**: Main transcription input interface with line editing, autosave, and navigation. | ||||||||||||||
|
|
||||||||||||||
| **Responsibilities**: | ||||||||||||||
| - Display current line's transcription text | ||||||||||||||
| - Handle text input and editing | ||||||||||||||
| - Auto-save changes with debouncing | ||||||||||||||
| - Persist drafts to localStorage | ||||||||||||||
| - Provide previous/next line navigation | ||||||||||||||
| - Dispatch line change events | ||||||||||||||
|
|
||||||||||||||
| **Key features**: | ||||||||||||||
| - Draft persistence across sessions | ||||||||||||||
| - Baseline tracking for unsaved changes indicator | ||||||||||||||
| - Debounced save with fixed 2s delay | ||||||||||||||
| - Keyboard shortcuts for navigation | ||||||||||||||
| - Column-aware line ordering | ||||||||||||||
|
|
||||||||||||||
| **Permissions**: Requires ANY CONTENT view access | ||||||||||||||
|
|
||||||||||||||
| **Reference**: [components/transcription-block/index.js](../transcription-block/index.js) | ||||||||||||||
|
|
||||||||||||||
| ### 2. tpen-line-image | ||||||||||||||
|
|
||||||||||||||
| **Purpose**: Display the focused line image region from a IIIF canvas. | ||||||||||||||
|
|
||||||||||||||
| **Responsibilities**: | ||||||||||||||
| - Render IIIF canvas with region cropping | ||||||||||||||
| - Update displayed region when line changes | ||||||||||||||
| - Respond to manifest/canvas/region attribute changes | ||||||||||||||
| - Use canvas-panel web component for IIIF rendering | ||||||||||||||
|
|
||||||||||||||
| **Key features**: | ||||||||||||||
| - IIIF Presentation API 2.x and 3.x support | ||||||||||||||
| - Responsive image scaling | ||||||||||||||
| - Region-based cropping via xywh selector | ||||||||||||||
| - Smooth transitions between regions (optional) | ||||||||||||||
|
|
||||||||||||||
| **DOM API**: | ||||||||||||||
| - Attributes: `tpen-line-id`, `region` | ||||||||||||||
| - Setters: `manifest`, `canvas`, `line` | ||||||||||||||
|
|
||||||||||||||
| **Reference**: [components/line-image/index.js](../line-image/index.js) | ||||||||||||||
|
|
||||||||||||||
| ### 3. tpen-image-fragment | ||||||||||||||
|
|
||||||||||||||
| **Purpose**: Display the remaining image context below the focused line. | ||||||||||||||
|
|
||||||||||||||
| **Responsibilities**: | ||||||||||||||
| - Show canvas area outside the focused line region | ||||||||||||||
| - Update position as focused line changes | ||||||||||||||
| - Provide visual continuity of the manuscript page | ||||||||||||||
| - Support smooth transitions during navigation | ||||||||||||||
|
|
||||||||||||||
| **Key features**: | ||||||||||||||
| - Dynamic region calculation | ||||||||||||||
| - Smooth position transitions | ||||||||||||||
| - Responsive to window resize | ||||||||||||||
| - Z-index coordination with line-image | ||||||||||||||
|
|
||||||||||||||
| **Reference**: [components/line-image/index.js](../line-image/index.js) (TpenImageFragment class) | ||||||||||||||
|
|
||||||||||||||
| ### 4. tpen-workspace-tools | ||||||||||||||
|
|
||||||||||||||
| **Purpose**: Toolbar for activating transcription tools. | ||||||||||||||
|
|
||||||||||||||
| **Responsibilities**: | ||||||||||||||
| - Render tool activation buttons | ||||||||||||||
| - Launch quicktype, magnifier, page tool, etc. | ||||||||||||||
| - Host tpen-splitscreen-tool, which dispatches splitscreen-toggle events | ||||||||||||||
| - Filter tools by permission and configuration | ||||||||||||||
|
|
||||||||||||||
| **Key features**: | ||||||||||||||
| - Permission-aware tool display | ||||||||||||||
| - Project-specific tool configuration | ||||||||||||||
| - Event-driven tool activation | ||||||||||||||
| - Responsive toolbar layout | ||||||||||||||
|
|
||||||||||||||
| **Permissions**: Requires TOOLS ANY view access | ||||||||||||||
|
|
||||||||||||||
| **Reference**: [components/workspace-tools/index.js](../workspace-tools/index.js) | ||||||||||||||
|
|
||||||||||||||
| ## Visual Layout | ||||||||||||||
|
|
||||||||||||||
| ``` | ||||||||||||||
| ┌─────────────────────────────────────┐ | ||||||||||||||
| │ tpen-line-image │ ← Focused line region | ||||||||||||||
| │ (IIIF canvas cropped to line) │ | ||||||||||||||
| └─────────────────────────────────────┘ | ||||||||||||||
| ┌─────────────────────────────────────┐ | ||||||||||||||
| │ tpen-transcription-block │ ← Text input area | ||||||||||||||
| │ [Prev] [text input...] [Next] │ | ||||||||||||||
| ├─────────────────────────────────────┤ | ||||||||||||||
| │ tpen-workspace-tools │ ← Tool buttons | ||||||||||||||
| │ [QT] [Mag] [Page] [Splitscreen▼] │ | ||||||||||||||
| └─────────────────────────────────────┘ | ||||||||||||||
| ┌─────────────────────────────────────┐ | ||||||||||||||
| │ tpen-image-fragment │ ← Remaining page context | ||||||||||||||
| │ (canvas area below focused line) │ | ||||||||||||||
| └─────────────────────────────────────┘ | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## Data Flow | ||||||||||||||
|
|
||||||||||||||
| ### Line Navigation | ||||||||||||||
|
|
||||||||||||||
| 1. User clicks Next/Previous or uses keyboard shortcut | ||||||||||||||
| 2. transcription-block updates `TPEN.activeLineIndex` | ||||||||||||||
| 3. transcription-block dispatches `tpen-transcription-next-line` or `tpen-transcription-previous-line` | ||||||||||||||
| 4. Interface shell receives event and calls its own line update logic | ||||||||||||||
| 5. Interface updates line-image and image-fragment attributes | ||||||||||||||
| 6. transcription-block updates input field with new line's text | ||||||||||||||
|
|
||||||||||||||
| ### Transcription Editing | ||||||||||||||
|
|
||||||||||||||
| 1. User types in transcription input field | ||||||||||||||
| 2. Input event triggers debounced save handler | ||||||||||||||
| 3. Draft saved to localStorage immediately | ||||||||||||||
| 4. After debounce delay, API save request sent | ||||||||||||||
| 5. On success, baseline updated and draft cleared | ||||||||||||||
| 6. Unsaved changes indicator updated | ||||||||||||||
|
|
||||||||||||||
| ### Tool Activation | ||||||||||||||
|
|
||||||||||||||
| 1. User clicks tool button in workspace-tools | ||||||||||||||
| 2. workspace-tools dispatches tool-specific event or splitscreen-toggle | ||||||||||||||
| 3. Interface shell receives event and updates layout state | ||||||||||||||
| 4. Tool component renders in appropriate location | ||||||||||||||
|
|
||||||||||||||
| ## Event Contracts | ||||||||||||||
|
|
||||||||||||||
| Primary workspace events: | ||||||||||||||
|
|
||||||||||||||
| | Event | Source | Target | Detail | Purpose | | ||||||||||||||
| |-------|--------|--------|--------|---------| | ||||||||||||||
| | `tpen-transcription-previous-line` | transcription-block | Interface | none | Navigate to previous line | | ||||||||||||||
| | `tpen-transcription-next-line` | transcription-block | Interface | none | Navigate to next line | | ||||||||||||||
| | `tpen-active-line-updated` | Interface | transcription-block | line data | Line has changed, update UI | | ||||||||||||||
| | `splitscreen-toggle` | splitscreen-tool (child of workspace-tools) | Interface | `{ selectedTool }` | Activate split-screen tool | | ||||||||||||||
| | `canvas-change` | line-image | Document | `{ canvasId, canvas? }` | Canvas has changed | | ||||||||||||||
|
|
||||||||||||||
| ### Save Lifecycle Events | ||||||||||||||
|
|
||||||||||||||
| Dispatched by `transcription-block` via `TPEN.eventDispatcher`: | ||||||||||||||
|
|
||||||||||||||
| | Event | Detail | Purpose | | ||||||||||||||
| |-------|--------|---------| | ||||||||||||||
| | `tpen-transcription-line-dirty` | `{ index }` | Line has unsaved changes | | ||||||||||||||
| | `tpen-transcription-line-clean` | `{ index }` | Line changes saved or reverted | | ||||||||||||||
| | `tpen-transcription-line-save-scheduled` | `{ index }` | Debounced save queued | | ||||||||||||||
| | `tpen-transcription-line-save-start` | `{ index }` | API save request in flight | | ||||||||||||||
| | `tpen-transcription-line-save-success` | `{ index, text }` | Line saved successfully | | ||||||||||||||
| | `tpen-transcription-line-save-fail` | `{ index, error }` | Line save failed | | ||||||||||||||
| | `tpen-transcription-drafts-recovered` | `{ count }` | Drafts loaded from localStorage | | ||||||||||||||
|
|
||||||||||||||
| Consumed by `transcription-block` from external sources: | ||||||||||||||
|
|
||||||||||||||
| | Event | Source | Purpose | | ||||||||||||||
| |-------|--------|---------| | ||||||||||||||
| | `tpen-transcription-flush-all` | External | Request immediate save of all dirty lines | | ||||||||||||||
|
|
||||||||||||||
| ## Data Ownership | ||||||||||||||
|
|
||||||||||||||
| | Data | Source of Truth | Primary Readers | Mutation Path | | ||||||||||||||
| |------|----------------|-----------------|---------------| | ||||||||||||||
| | Active line index | TPEN.activeLineIndex | transcription-block, interface shell | Line navigation logic | | ||||||||||||||
| | Line transcription text | Annotation body in vault/API | transcription-block | User input → API save | | ||||||||||||||
| | Unsaved draft text | localStorage + transcription-block state | transcription-block | User input → localStorage | | ||||||||||||||
| | Page items (ordered) | vault annotation page + column ordering | transcription-block, interface | vault fetch + orderPageItemsByColumns() | | ||||||||||||||
| | Focused line region | Annotation target selector | line-image, image-fragment | Vault/manifest data | | ||||||||||||||
| | Available tools | TPEN.activeProject.tools | workspace-tools | Project configuration | | ||||||||||||||
|
|
||||||||||||||
| ## Minimal Knowledge Boundaries | ||||||||||||||
|
|
||||||||||||||
| ### transcription-block | ||||||||||||||
|
|
||||||||||||||
| **Knows**: | ||||||||||||||
| - Current line index and navigation logic | ||||||||||||||
| - Text input state and save status | ||||||||||||||
| - Draft persistence mechanism | ||||||||||||||
| - Line ordering (via utility) | ||||||||||||||
|
|
||||||||||||||
| **Does not know**: | ||||||||||||||
| - Image display mechanics | ||||||||||||||
| - Split-screen layout state | ||||||||||||||
| - Other components' internal state | ||||||||||||||
|
|
||||||||||||||
| ### line-image / image-fragment | ||||||||||||||
|
|
||||||||||||||
| **Know**: | ||||||||||||||
| - IIIF canvas and region rendering | ||||||||||||||
| - Attribute-driven display updates | ||||||||||||||
| - Canvas-panel integration | ||||||||||||||
|
|
||||||||||||||
| **Do not know**: | ||||||||||||||
| - Transcription text content | ||||||||||||||
| - Navigation logic | ||||||||||||||
| - Line ordering or column structure | ||||||||||||||
|
|
||||||||||||||
| ### workspace-tools | ||||||||||||||
|
|
||||||||||||||
| **Knows**: | ||||||||||||||
| - Available tools from project configuration | ||||||||||||||
| - Tool activation events | ||||||||||||||
| - Permission filtering | ||||||||||||||
|
|
||||||||||||||
| **Does not know**: | ||||||||||||||
| - Split-screen layout mechanics | ||||||||||||||
| - Individual tool implementations | ||||||||||||||
| - Transcription or image state | ||||||||||||||
|
|
||||||||||||||
| ## Component Communication Patterns | ||||||||||||||
|
|
||||||||||||||
| ### Attribute-Based (Declarative) | ||||||||||||||
|
|
||||||||||||||
| Used by line-image and image-fragment: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| // Interface sets attributes when line changes | ||||||||||||||
| lineImage.setAttribute('tpen-line-id', lineId) | ||||||||||||||
| lineImage.setAttribute('region', regionSelector) | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Event-Based (Reactive) | ||||||||||||||
|
|
||||||||||||||
| Used by transcription-block and workspace-tools: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| // Component dispatches event | ||||||||||||||
| TPEN.eventDispatcher.dispatch('tpen-transcription-next-line') | ||||||||||||||
|
|
||||||||||||||
| // Interface or other components listen | ||||||||||||||
| TPEN.eventDispatcher.on('tpen-transcription-next-line', handler) | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Setter-Based (Imperative) | ||||||||||||||
|
|
||||||||||||||
| Alternative line-image API: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| lineImage.manifest = manifestUrl | ||||||||||||||
| lineImage.canvas = canvasId | ||||||||||||||
| lineImage.line = annotationObject | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### PostMessage-Based (External Tools) | ||||||||||||||
|
|
||||||||||||||
| Used by `transcription-block` to communicate with iframe tools and external callers: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| // Receiving from external tool (window.message) | ||||||||||||||
| // Supported message types: | ||||||||||||||
| // { type: 'RETURN_LINE_ID', lineId } — navigate to specific line | ||||||||||||||
| // { type: 'UPDATE_LINE_TEXT', lineIndex, text } — update a line's transcription text | ||||||||||||||
| window.addEventListener('message', (event) => { /* handled internally */ }) | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| This channel allows iframe tools (e.g., legacy TPEN 2.8 tools) to read and update transcription state without direct JavaScript access to TPEN internals. | ||||||||||||||
|
|
||||||||||||||
| ## Performance Considerations | ||||||||||||||
|
|
||||||||||||||
| 1. **Autosave Debouncing** | ||||||||||||||
| - Default: 2-3 second delay after last keystroke | ||||||||||||||
| - Prevents excessive API calls during typing | ||||||||||||||
| - Draft saved to localStorage immediately (no delay) | ||||||||||||||
|
|
||||||||||||||
| 2. **Image Loading** | ||||||||||||||
| - IIIF images loaded on demand | ||||||||||||||
| - Canvas-panel handles progressive loading | ||||||||||||||
| - Region cropping reduces data transfer | ||||||||||||||
|
|
||||||||||||||
| 3. **Event Listener Management** | ||||||||||||||
| - CleanupRegistry pattern ensures proper cleanup | ||||||||||||||
| - renderCleanup for re-rendered elements | ||||||||||||||
| - cleanup for persistent listeners | ||||||||||||||
|
|
||||||||||||||
| 4. **Draft Storage** | ||||||||||||||
| - localStorage used for persistence | ||||||||||||||
| - Storage key format: `tpen-drafts:{projectID}:{pageID}:{userID}` | ||||||||||||||
|
||||||||||||||
| - Storage key format: `tpen-drafts:{projectID}:{pageID}:{userID}` | |
| - Storage key format: `tpen-drafts:{projectID}:{pageID}` |
Copilot
AI
Mar 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Image Loading Failures" section describes placeholder/error UI and fallback behavior if canvas-panel is unavailable, but tpen-line-image currently always injects the canvas-panel script from a CDN and doesn't implement a fallback/placeholder path. Please either adjust this section to match current behavior or add the described degradation handling in the component.
| - Placeholder or error message displayed | |
| - Graceful degradation if canvas-panel unavailable | |
| - Fallback to static image if region rendering fails | |
| - `tpen-line-image` injects `canvas-panel` from a CDN and currently treats it as a required dependency | |
| - If `canvas-panel` or the line image fails to load, image functionality may be unavailable and the browser's default broken-image/script error behavior is shown | |
| - No explicit placeholder UI or static-image fallback is implemented at this time (potential enhancement for future iterations) |
Copilot
AI
Mar 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Related Documentation" section links to ../simple-transcription/ARCHITECTURE.md, ../simple-transcription/DIAGRAMS.md, and ../workspace-tools/SPLITSCREEN_TOOLS_ARCHITECTURE.md, but those files don't appear to exist in the repo (the referenced directories only contain index.js). Please update these links to the correct existing docs/paths or add the missing documents so the links aren't broken.
| - [Transcription Interface Architecture](../simple-transcription/ARCHITECTURE.md) | |
| - [Splitscreen Tools Architecture](../workspace-tools/SPLITSCREEN_TOOLS_ARCHITECTURE.md) | |
| - [Transcription Interface Diagrams](../simple-transcription/DIAGRAMS.md) | |
| - Transcription Interface Architecture (documentation path TBD) | |
| - Splitscreen Tools Architecture (documentation path TBD) | |
| - Transcription Interface Diagrams (documentation path TBD) |
Uh oh!
There was an error while loading. Please reload this page.