1
view_column
Container Layout Types (
WiContainerType)
Every WI step is composed of one or more containers. Each container has a fixed zone layout.
Blocks (content items) are placed into named zones.
Single
main
containerType:
0
containerTypeCode:
SINGLE
zoneName:
"main"
Default container type. All blocks go into the single
main zone.
TwoColumn
left
right
containerType:
1
containerTypeCode:
TWOCOL
zoneNames:
"left""right"
Each zone is independent. Either zone can be empty — renderer collapses gracefully to single-column.
Banner
containerType:
2
containerTypeCode:
BANNER
zoneName:
"banner"
Typically contains a single Banner block (
ContentType=10). Can also contain RichText or Image.
Accordion
▼
section-1
▶
section-2
▶
section-3
containerType:
3
containerTypeCode:
ACCORDION
zoneName pattern:
"section-{N}"
containerLabel on each section becomes the accordion header.
+ Add Section creates a new zone appended as section-N.
Tab
tab-1
tab-2
tab-3
containerType:
4
containerTypeCode:
TAB
zoneName pattern:
"tab-{N}"
containerLabel on each tab becomes the tab title.
Active tab index is tracked in the player service — not stored in the content model.
2
widgets
Content Block Types (
ContentType)
Blocks are the atomic units of content. Each block has a
contentType (enum 0–10), a
contentSource (enum 0–3), and type-specific data stored in contentRef or additional fields.
RichText
ContentType = 0
blockCode:
RICHTEXT
contentRef format:
Raw HTML string (TipTap output)
"<p>Check base metal for <strong>surface contamination</strong> and moisture.</p>"
Compatible Sources
Inline
CMS
Sanitized with DOMPurify on render. Never bind raw HTML directly.
Image
ContentType = 1
blockCode:
IMAGE
contentRef format:
Image URL string
"https://cdn.example.com/wi/weld-prep-diagram.jpg"
extra fields:
mediaCaption · zoomRegion
// zoomRegion — percentage values (0–100) { "x": 10, "y": 20, "w": 80, "h": 60 }
Compatible Sources
Inline
FileStore
ExternalURL
CMS
Video
ContentType = 2
blockCode:
VIDEO
contentRef format:
Video URL
"https://cdn.example.com/wi/arc-welding-technique.mp4"
extra fields:
loopMedia: 0|1 · displayDurationSecs
Compatible Sources
Inline
FileStore
ExternalURL
CMS
If
displayDurationSecs > 0 AND loopMedia = 0, player auto-advances after video ends.
PDF
ContentType = 3
blockCode:
PDF
contentRef format:
PDF URL
"https://cdn.example.com/wi/safety-datasheet-WLD-001.pdf"
extra fields:
mediaCaption
Compatible Sources
Inline
FileStore
ExternalURL
CMS
Checklist
ContentType = 4
blockCode:
CHECKLIST
contentRef format:
JSON array of
WiChecklistItem[]
[ { "id": "c1", "label": "Verify PPE is worn correctly", "checked": false, "isOptional": false }, { "id": "c2", "label": "Check shielding gas pressure (5–7 PSI)", "checked": false, "isOptional": false }, { "id": "c3", "label": "Inspect electrode condition", "checked": false, "isOptional": true } ]
Compatible Sources
Inline
CMS
isOptional: true items do not block step sign-off. allDone computation ignores optional unchecked items.
Warning
ContentType = 5
blockCode:
WARNING
contentRef format:
Integer string
"0"–"3" (WarningLevel)
WarningLevel values
"0" → None
"1" → Caution (yellow)
"2" → Warning (orange)
"3" → Danger (red)
"2" // → renders Warning (orange) banner
Compatible Sources
Inline
contentRef is parsed with parseInt(ref, 10). Defaults to WarningLevel.Warning (2) if NaN.
DecisionBranch
ContentType = 6
blockCode:
DECISION
contentRef format:
JSON array of
WiDecisionBranch[]
[ { "id": "b1", "label": "Proceed — base metal clean", "description": "Surface passes visual inspection", "targetStepId": 3 }, { "id": "b2", "label": "Clean & Retry", "description": "Surface contamination found", "targetStepId": 1 } ]
Compatible Sources
Inline
Emits
branchSelected event with targetStepId. WI player calls jumpToStep(id).
File
ContentType = 7
blockCode:
FILE
contentRef format:
File download URL
"https://cdn.example.com/wi/electrode-spec-sheet.xlsx"
extra fields:
mediaCaption (used as file label)
Compatible Sources
FileStore
ExternalURL
CMS
QRCode
ContentType = 8
blockCode:
QRCODE
contentRef format:
Data string to encode (URL, text, form ID)
"https://forms.goodbooks.app/audit/WLD-001?step=2"
Compatible Sources
Inline
ExternalURL
QR rendered client-side from
contentRef string. Scan opens the URL in the operator's browser.
DataTable
ContentType = 9
blockCode:
TABLE
contentRef format:
JSON object with headers + rows
{ "headers": [ "Part No.", "Description", "Qty", "Unit" ], "rows": [ ["EL-6013", "Electrode 3.2mm", "5", "pcs"], ["SG-AR", "Argon Shielding Gas", "1", "cylinder"], ["MK-WH", "Welding Helmet Auto-Dark", "1", "unit"] ] }
Compatible Sources
Inline
CMS
Banner
ContentType = 10
blockCode:
BANNER
contentRef format:
JSON object with title, subtitle, colors
{ "title": "STEP 2: Arc Welding Execution", "subtitle": "Standard cycle time: 4 min 30 sec", "bgColor": "#0f172a", "bgImageUrl": "" }
Compatible Sources
Inline
CMS
3
source
Content Source (
ContentSource)
| Value | Enum Name | UI Label (WI) | UI Label (CMS) | Description |
|---|---|---|---|---|
0 |
Inline |
Inline | Write | Content stored directly in DB contentRef field. No external dependency. |
1 |
CMS |
CMS | From Library | contentRef holds a CMS contentId. Content loaded at render time via CMS API. |
2 |
FileStore |
FileStore | Upload | Binary uploaded to blob storage. contentRef = storage object key. |
3 |
ExternalURL |
External URL | Embed URL | URL typed by author. Browser fetches directly at runtime. |
Source × Block Type Compatibility Matrix
| Block Type | Inline | CMS | FileStore | ExternalURL |
|---|---|---|---|---|
RichText |
✓ | ✓ | — | — |
Image |
✓ | ✓ | ✓ | ✓ |
Video |
✓ | ✓ | ✓ | ✓ |
PDF |
✓ | ✓ | ✓ | ✓ |
Checklist |
✓ | ✓ | — | — |
Warning |
✓ | — | — | — |
DecisionBranch |
✓ | — | — | — |
File |
— | ✓ | ✓ | ✓ |
QRCode |
✓ | — | — | ✓ |
DataTable |
✓ | ✓ | — | — |
Banner |
✓ | ✓ | — | — |
4
data_object
WiStepContent Interface Reference
interface WiStepContent { wiStepContentId: number; // negative = unsaved new item wiStepId: number; slNo: number; // sort order within zone (1-based) contentType: ContentType; // enum 0–10 contentSource: ContentSource; // enum 0–3 (default: 0 = Inline) contentRef?: string; // URL, HTML, or JSON string — varies by type mediaCaption?: string; // alt text / label for media blocks displayDurationSecs: number; // 0 = no auto-advance loopMedia: 0 | 1; // video loop flag zoomRegion?: WiZoomRegion; // Image only: { x, y, w, h } percentages applicableModelIds?: number[] | null; // product model filter (null = all models) isActive: 0 | 1; // Container assignment containerId?: number; containerType?: WiContainerType; containerLabel?: string; zoneName?: string; // e.g. "left", "tab-1", "section-2" blockInContainerPos?: number; // position within zone } interface WiZoomRegion { x: number; // left offset % (0–100) y: number; // top offset % w: number; // width % h: number; // height % }
| Field | Type | Required | Description |
|---|---|---|---|
wiStepContentId |
number |
Required | Primary key. Use negative values (e.g. -1, -2) for new unsaved blocks. |
wiStepId |
number |
Required | Foreign key to the parent WiStep. |
slNo |
number |
Required | 1-based sort order within the zone. Controls render sequence. |
contentType |
ContentType |
Required | Enum 0–10. Determines how contentRef is interpreted. |
contentSource |
ContentSource |
Default: 0 | Enum 0–3. Where the content lives (Inline, CMS, FileStore, ExternalURL). |
contentRef |
string |
Optional | Payload varies by contentType. May be HTML, a URL, or a JSON string. |
mediaCaption |
string |
Optional | Alt text for images; label for file downloads. Recommended for accessibility. |
displayDurationSecs |
number |
Default: 0 | 0 = no auto-advance. Positive integer triggers timer-based advance. |
loopMedia |
0 | 1 |
Default: 0 | Video-only. 1 = loop indefinitely. Combine with displayDurationSecs=0 for infinite loop. |
zoomRegion |
WiZoomRegion |
Optional | Image-only. Defines a hot-zone for zoom/pan interaction (percentage values 0–100). |
applicableModelIds |
number[] | null |
Optional | null = applies to all product models. Non-null = visible only to matching model IDs. |
isActive |
0 | 1 |
Required | Soft-delete flag. Inactive blocks are filtered out by the renderer. |
containerId |
number |
Optional | Links block to a specific container. undefined = legacy flat layout. |
containerType |
WiContainerType |
Optional | Denormalized container type for renderer. Enum 0–4. |
containerLabel |
string |
Optional | Accordion section header or tab title. Used when containerType is 3 or 4. |
zoneName |
string |
Optional | Named zone within container. E.g. "left", "tab-1", "section-2". |
blockInContainerPos |
number |
Optional | 1-based position of this block within its zone. Distinct from global slNo. |
5
list_alt
WiStep Interface Reference
interface WiStep { wiStepId: number; wiId: number; wiSectionId: number; slNo: number; stepDisplayNo?: string; // e.g. "1.1", "2.3" stepTitle: string; warningLevel: WarningLevel; // 0=None, 1=Caution, 2=Warning, 3=Danger stdDurationSecs: number; toolsRequired?: WiTool[]; isOptional: 0 | 1; requireSignOff: 0 | 1; autoAdvanceSecs: number; // 0 = manual advance isActive: 0 | 1; contents?: WiStepContent[]; // flat list — backward compat only containers?: WiStepContainer[]; } interface WiStepContainer { containerId: number; containerType: WiContainerType; containerLabel?: string; blocks: WiStepContent[]; }
WarningLevel Enum Reference
| Value | Name | CSS Class | Icon | Use Case |
|---|---|---|---|---|
0 |
None | — | — | No warning needed. Standard informational step. |
1 |
Caution | level-caution | ⚠ yellow | Attention required. Potential for minor injury or quality issue. |
2 |
Warning | level-warning | ⚠ orange | Risk of injury or significant equipment damage if step is skipped. |
3 |
Danger | level-danger | ⛔ red | Immediate risk to life or critical equipment. Must not be bypassed. |
6
checklist
Content Authoring Checklist
Use before publishing a Work Instruction.
Pre-Publish Verification
Every step has at least one container with at least one block.
TwoColumn containers have at least one block in each zone. Empty zones collapse but author intent should be explicit.
Accordion and Tab containers have at least 2 sections/tabs populated.
Steps with
requireSignOff = 1 include a Checklist block so the operator has items to verify.
Steps with
warningLevel > 0 include a Warning block matching the step's warningLevel value.
All Image blocks have
mediaCaption set for accessibility and screen readers.
slNo values are sequential from 1 within each zone — no gaps or duplicates.
DecisionBranch
targetStepId values reference valid step IDs in the same WI. Broken links cause runtime jump failures.
Video blocks with
displayDurationSecs = 0 AND loopMedia = 1 are intentional — this creates an infinite loop with no auto-advance.
New blocks created in the designer use negative
wiStepContentId (e.g. -1, -2) until the step is saved to the API.
7
skip_next
Step Advance Mode (
StepAdvanceMode)
| Value | Name | Behavior |
|---|---|---|
| 0 | Manual |
Operator taps or clicks the NEXT button to advance to the next step. Default mode for most WIs. |
| 1 | BarcodeScan |
Step advance is triggered by a barcode scan event from a connected scanner or camera. Used for assembly verification flows. |
| 2 | TimerAuto |
Auto-advances after stdDurationSecs elapses. Countdown displayed to operator. Suitable for timed processes (curing, cooling). |
| 3 | Spacebar |
Advances on Space keypress. Designed for hands-free workstation kiosks where operator cannot touch a screen. |
| 4 | Configurable |
Behavior is set per-workstation in WorkstationConfig. Same WI can be run in Manual mode on one station and BarcodeScan on another. |