Endpoint
GET /wi/WI/GetWIFullDetail
Returns full nested structureResponse nesting
3
sections → steps → containers → blocksPayload field
contentRef
JSON string — parse before useContents
Single Column
containerType: 0 WI Step 201 · ContainerId 301 | CMS Container 601API Request
GET /wi/WI/GetWIFullDetail ?WiId=1001
Response — Step 201 containers[ ] (abbreviated)
{ "wiId": 1001, "wiCode": "WI-BKT-001", "sections": [{ "wiSectionId": 101, "sectionTitle": "Preparation & Safety", "steps": [{ "wiStepId": 201, "stepTitle": "Tool & PPE Pre-check", "containers": [{ "containerId": 301, "containerType": 0, // Single "containerLabel": "Tool Check", "blocks": [ { "wiStepContentId": 3001, "contentType": 0, // RichText "contentSource": 0, // Inline "zoneName": "main", "blockInContainerPos": 1, "contentRef": "{\"html\":\"<p>Verify all required tools...</p>\",\"plainText\":\"...\"}" }, { "wiStepContentId": 3002, "contentType": 4, // Checklist "zoneName": "main", "blockInContainerPos": 2, "contentRef": "{\"title\":\"Pre-start Checklist\",\"items\":[...]}" } ] }] }] }] }
Rendered Output — how ContentContainerRenderer produces this
Live visual projection
Verify all required tools and PPE are present before starting.
Pre-start Checklist
Torque wrench (range 10–50 Nm)
Safety glasses
Anti-static wrist strap
Alignment jig (BKT-JIG-01)
M6 hex bolts ×6 (pre-torqued bag)
Banner
WI Step 202 · ContainerId 302 | CMS Container 602API Request
GET /wi/WI/GetWIFullDetail ?WiId=1001 // Step 202 in sections[0].steps[1]
Response — Step 202 containers[ ] (abbreviated)
"containers": [{ "containerId": 302, "containerType": 2, // Banner "containerLabel": "Danger Notice", "blocks": [ { "wiStepContentId": 3010, "contentType": 10, // Banner block "zoneName": "main", "blockInContainerPos": 1, "contentRef": "{ \"title\": \"DANGER\", \"message\": \"Ensure main power isolator is in OFF position and locked...\", \"imageUrl\": \"/assets/wi/banners/electrical-danger.jpg\", \"ctaLabel\": \"View LOTO Procedure\", \"ctaUrl\": \"/wi/1002\" }" }, { "wiStepContentId": 3011, "contentType": 5, // Warning "zoneName": "main", "blockInContainerPos": 2, "contentRef": "{ \"message\": \"Confirm isolation with voltage tester.\", \"warningLevel\": 3 }" } ] }]
Rendered Output
Live visual projection
Confirm isolation with approved voltage tester. Do not rely on visual switch position alone.
Two Column
containerType: 1 WI Step 203 · ContainerId 303 | CMS Container 603API Request
GET /wi/WI/GetWIFullDetail ?WiId=1001 // Step 203 in sections[1].steps[0]
Response — Step 203 containers[ ] (abbreviated)
"containers": [{ "containerId": 303, "containerType": 1, // TwoColumn "blocks": [ { "wiStepContentId": 3020, "contentType": 1, // Image "contentSource": 2, // FileStore "zoneName": "left", // ← LEFT column "blockInContainerPos": 1, "contentRef": "{\"imageUrl\":\"/assets/...\",\"caption\":\"Fig 1\"}" }, { "wiStepContentId": 3021, "contentType": 0, // RichText "zoneName": "right", // ← RIGHT column "blockInContainerPos": 1 }, { "wiStepContentId": 3022, "contentType": 5, // Warning "zoneName": "right", // ← same RIGHT column "blockInContainerPos": 2 // stacked below RichText } ] }]
How the renderer reads TwoColumn blocks: it groups all blocks by
zoneName, then renders the "left" group in column 1 and the "right" group in column 2. Within each zone, blocks are sorted by blockInContainerPos. There is no separate "left zone API" — it is all one flat blocks[] array, differentiated only by zoneName.
Rendered Output
Live visual projection
bracket-alignment.png
Fig 1 — Alignment mark positions
- Position bracket so all 4 alignment marks are visible.
- Insert M6 bolts finger-tight into all 6 holes.
- Verify bracket is flush with the datum face (±0.5 mm).
- Confirm no cable routing is pinched behind bracket.
Brackets must be flush. A gap >0.5 mm requires shimming — see Engineering Note EN-BKT-03.
Tab Panel
containerType: 4 WI Step 204 · ContainerId 304 | CMS Container 605API Request
GET /wi/WI/GetWIFullDetail ?WiId=1001 // Step 204 in sections[1].steps[1]
Response — Step 204 containers[ ] (abbreviated)
"containers": [{ "containerId": 304, "containerType": 4, // Tab "containerLabel": "Model Variant Torque", "blocks": [ // TAB 1: "Model A (2023+)" { "wiStepContentId": 3030, "contentType": 0, // RichText "zoneName": "Model A (2023+)", "blockInContainerPos": 1 }, { "wiStepContentId": 3031, "contentType": 9, // DataTable "zoneName": "Model A (2023+)", "blockInContainerPos": 2 }, // TAB 2: "Model B (2021-2022)" { "wiStepContentId": 3032, "contentType": 0, "zoneName": "Model B (2021-2022)", "blockInContainerPos": 1 }, { "wiStepContentId": 3033, "contentType": 9, "zoneName": "Model B (2021-2022)", "blockInContainerPos": 2 }, // TAB 3: "Legacy (pre-2021)" { "wiStepContentId": 3034, "contentType": 5, "zoneName": "Legacy (pre-2021)", "blockInContainerPos": 1 }, { "wiStepContentId": 3035, "contentType": 0, "zoneName": "Legacy (pre-2021)", "blockInContainerPos": 2 } ] }]
How the renderer reads Tab blocks: it extracts the unique set of
zoneName values in insertion order — these become the tab labels. Each tab's content is the blocks where zoneName === tabLabel, sorted by blockInContainerPos. To add a new tab: insert a block with a new zone name. To reorder tabs: the renderer preserves the DB insertion order of the first occurrence of each zone name.
Rendered Output — "Model A (2023+)" tab active
Live visual projection
Model A uses the revised torque sequence. Apply bolts in the cross-pattern shown on the jig label.
| Fastener | Torque (Nm) | Pass | Tool |
|---|---|---|---|
| M6 outer ×4 | 10 | 1st pass | T-10 |
| M6 outer ×4 | 18 | Final | T-10 |
| M6 centre ×2 | 22 | Single pass | T-20 |
— "Model B (2021-2022)" tab (when clicked) —
Model B uses an older bracket profile. Torque in sequential order (1→6) not cross-pattern.
| Fastener | Torque (Nm) | Tool |
|---|---|---|
| M6 ×6 | 15 | T-10 |
| M8 centre | 30 | T-20 |
Accordion
containerType: 3 WI Step 205 · ContainerIds 305 + 306 | CMS Container 604API Request
GET /wi/WI/GetWIFullDetail ?WiId=1001 // Step 205 in sections[1].steps[2] // This step has TWO containers: // containers[0] = Accordion (3 panels) // containers[1] = Single (QR code)
Response — Step 205 containers[ ] (abbreviated)
"containers": [ { "containerId": 305, "containerType": 3, // Accordion "containerLabel": "Reference & Checklist", "blocks": [ { "wiStepContentId": 3040, "contentType": 9, // DataTable "zoneName": "Fastener Specifications", "blockInContainerPos": 1 }, { "wiStepContentId": 3041, "contentType": 4, // Checklist "zoneName": "Completion Checklist", "blockInContainerPos": 1 }, { "wiStepContentId": 3042, "contentType": 7, // File "contentSource": 2, // FileStore "zoneName": "Safety Data Sheet", "blockInContainerPos": 1 } ] }, { "containerId": 306, "containerType": 0, // Single (second container on same step) "containerLabel": "Final Action", "blocks": [{ "wiStepContentId": 3043, "contentType": 8, // QRCode "zoneName": "main", "blockInContainerPos": 1, "contentRef": "{\"targetUrl\":\"/wi/signoff?...\",\"label\":\"Scan to sign-off\"}" }] } ]
How the renderer reads Accordion blocks: exactly like Tab — the unique
zoneName values become accordion panel headers. Each panel contains the blocks matching that zone, sorted by blockInContainerPos. Step 205 also shows that a single step can have multiple containers: the Accordion is positionNo=1 and the Single (QR code) is positionNo=2. The renderer iterates step.containers[] in order, rendering each container independently below the previous one.
Rendered Output — Accordion expanded, Single below
Live visual projection
Fastener Specifications
▲
| Part No | Description | Qty | Torque Nm | Class |
|---|---|---|---|---|
| M6-HEX-SS | M6 Hex Bolt Stainless | 6 | 18 | Grade 8 |
| M6-WSH-SS | M6 Flat Washer | 6 | N/A | 316 SS |
| LOCTITE-243 | Thread Lock Medium | 1 drop | N/A | Blue |
Completion Checklist
▲
Final Inspection Checklist
All 6 bolts torqued to spec
Bracket flush with datum (checked with gauge)
Cable routing clear of bracket edges
Loctite 243 applied and cured (min 10 min)
Work area cleaned of metal swarf
Safety Data Sheet
▼
Loctite 243 Safety Data Sheet.pdf
200 KB
↓ Download
Scan to record digital sign-off
CMS Equivalents — same request pattern, same rendering logic
CMS API Requests (for ContentId 5001)
// Get all containers for a CMS document GET /cms/ContentContainer/GetContentContainersByContent ?ContentId=5001 // Get blocks for one container (e.g. the Banner container) GET /cms/ContentBlock/GetContentBlocksByContainer ?ContentContainerId=602 // Save/update block content (the CMS editor auto-save call) PUT /cms/ContentBlock/UpdateBlockProps { "blockId": 4010, "propsJson": "{\"title\":\"...\",\"message\":\"...\"}" }
| CMS Container | Type | Layout key | PropsJson field | Equivalent WI field |
|---|---|---|---|---|
| 601 | SINGLE | containerTypeCode="SINGLE" | PropsJson | contentRef |
| 602 | BANNER | containerTypeCode="BANNER" | PropsJson | contentRef |
| 603 | TWOCOL | containerTypeCode="TWOCOL" | PropsJson | contentRef |
| 604 | ACCORDION | containerTypeCode="ACCORDION" | PropsJson | contentRef |
| 605 | TAB | containerTypeCode="TAB" | PropsJson | contentRef |
API Field Reference
| Field | Source | Type | Notes |
|---|---|---|---|
containers[] |
WiStep | WiStepContainer[] | New field. If absent (legacy steps), renderer wraps contents[] into a synthetic Single container. |
containerType |
WiStepContainer | WiContainerType enum (int) | 0=Single, 1=TwoColumn, 2=Banner, 3=Accordion, 4=Tab. Drives which layout template is used. |
zoneName |
WiStepContent / ContentBlock | string | For Single: always "main". For TwoColumn: "left" or "right". For Tab/Accordion: becomes the tab label / panel header. Case-sensitive. |
blockInContainerPos |
WiStepContent | int | Ordering within a zone. Position 1 in "left" and position 1 in "right" are independent. Always starts at 1. |
contentRef |
WiStepContent | string (serialized JSON) | Raw JSON string — renderer calls JSON.parse(block.contentRef). Schema depends on contentType. |
propsJson |
ContentBlock (CMS) | string (serialized JSON) | Same pattern as contentRef — same JSON schemas, different field name. |
contentType |
WiStepContent | ContentType enum (int) | 0=RichText 1=Image 2=Video 3=PDF 4=Checklist 5=Warning 6=DecisionBranch 7=File 8=QRCode 9=DataTable 10=Banner |
positionNo (on container) |
WiStepContainer | int | Order of containers within a step. One step can have multiple containers (e.g. Step 205 has an Accordion at pos=1 and a Single at pos=2). |
GB5 · WI + CMS Layout Guide · Based on test dataset WiId=1001 / CMS ContentId=5001 · Test data file:
docs/test-data-inserts.sql