From b4cb4970669594758e114ebfef8c6fe25a4e9e43 Mon Sep 17 00:00:00 2001 From: arena-agent Date: Wed, 29 Jul 2026 04:21:13 +0000 Subject: [PATCH 1/2] fix(ui): remove stray closing braces after CategoryDropdown definition Three orphan closers left over from the CategoryDropdown/AddRoomModal restructure broke the script_mod block and with it the nigig-build build at HEAD; AddRoomModal now follows CategoryDropdown at DSL top level. --- .../pages/workspace/cost_estimator/cost_estimate_screen.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/apps/nigig-build/src/construction_frame/pages/workspace/cost_estimator/cost_estimate_screen.rs b/crates/apps/nigig-build/src/construction_frame/pages/workspace/cost_estimator/cost_estimate_screen.rs index 00f4a0b..c5e48cc 100644 --- a/crates/apps/nigig-build/src/construction_frame/pages/workspace/cost_estimator/cost_estimate_screen.rs +++ b/crates/apps/nigig-build/src/construction_frame/pages/workspace/cost_estimator/cost_estimate_screen.rs @@ -225,9 +225,6 @@ script_mod! { } } } - } - } - } mod.widgets.AddRoomModal = Modal { width: 400.0 From 496bc1c29e5adbb2211e7119f0a11e4205082073 Mon Sep 17 00:00:00 2001 From: arena-agent Date: Wed, 29 Jul 2026 04:21:13 +0000 Subject: [PATCH 2/2] feat(doc): wire application navigation to CrdtDocWorkspace Consolidate navigation onto a single CRDT docs destination now that the DSL switch made the runtime-test tab an exact duplicate: drop the 'Docs CRDT' dock tab, its crdt_docs_content view, the sidebar's 'Documents CRDT Test' button and its select_tab handler. The desktop 'Docs' tab and 'Documents' sidebar button land on CrdtDocWorkspace, and mobile's workspace drawer resolves 'Documents' to the CrdtDocWorkspace doc_page through the new pure workspace_page_id function, pinned by unit tests (destination, label table, page distinctness, CAD fallback). --- .../pages/workspace/doc/README.md | 30 ++++- .../construction_frame/pages/workspace/mod.rs | 2 +- .../pages/workspace/project/mod.rs | 104 +++++++++--------- 3 files changed, 82 insertions(+), 54 deletions(-) diff --git a/crates/apps/nigig-build/src/construction_frame/pages/workspace/doc/README.md b/crates/apps/nigig-build/src/construction_frame/pages/workspace/doc/README.md index 11fb421..76987a6 100644 --- a/crates/apps/nigig-build/src/construction_frame/pages/workspace/doc/README.md +++ b/crates/apps/nigig-build/src/construction_frame/pages/workspace/doc/README.md @@ -530,7 +530,7 @@ collaboration-safe acknowledged frontier. - [ ] CrdtDocEditor widget runtime integration test - [x] Separate CrdtDocWorkspace runtime-test view -- [ ] Wire application navigation switch to CrdtDocWorkspace +- [x] Wire application navigation switch to CrdtDocWorkspace ## CRDT-native table rendering @@ -687,6 +687,28 @@ toolbar with CRDT engine routing: Deliberate gaps, matching documented limitations: the mobile Edit/Done IME toggle is absent from the CRDT toolbar (the native widget has no IME interaction mode yet), and in-cell table editing remains future work. -The former `crdt_docs` runtime-test tab still instantiates the same -full workspace view; consolidating the duplicated docs tabs and pointing -navigation at the CRDT view is the next roadmap item. + +## Application navigation switch to CrdtDocWorkspace + +With the DSL switch complete, the temporary "Docs CRDT" runtime-test tab +was an exact duplicate of the real "Docs" tab, so navigation has been +consolidated onto a single CRDT destination: + +- The desktop dock's `workspace_tabs` keeps one "Docs" tab + (`docs_content` containing `CrdtDocWorkspace`); the `crdt_docs_tab` + definition, its `crdt_docs_content` view, the sidebar's + "Documents CRDT Test" button and its `select_tab` handler are removed. + "Documents" in the sidebar and the dock tab bar both land on the CRDT + editor. +- Mobile's workspace drawer resolves "Documents" to `doc_page` (whose + `m_doc_content` is `CrdtDocWorkspace`). That mapping is now the pure + function `workspace_page_id` in `pages/workspace/project/mod.rs`, + pinned by unit tests that assert the Documents destination, the + label-to-page table, page distinctness, and the CAD fallback for + unknown labels. + +The legacy fallback posture is unchanged: `mod.widgets.DocWorkspace` +remains registered, so reverting any navigation node to the classic +editor is again a one-line DSL change. The standalone runtime-test view +roadmap item stays checked historically — it served as the pre-switch +verification surface and was removed only after becoming a duplicate. diff --git a/crates/apps/nigig-build/src/construction_frame/pages/workspace/mod.rs b/crates/apps/nigig-build/src/construction_frame/pages/workspace/mod.rs index 0fb85f6..c0a1caa 100644 --- a/crates/apps/nigig-build/src/construction_frame/pages/workspace/mod.rs +++ b/crates/apps/nigig-build/src/construction_frame/pages/workspace/mod.rs @@ -18,7 +18,7 @@ pub fn script_mod(vm: &mut ScriptVm) { // 2. cad — CadWorkspace + CAD script bindings // 3. spreadsheet — SpreadsheetGrid widget prototype // 4. invoice — InvoiceWorkspace widget prototype - // 5. doc — DocWorkspace widget prototype + // 5. doc — CrdtDocWorkspace (active) + DocWorkspace (fallback) // 6. project_management — ProjectManagementWorkspace widget prototype // 7. project — BuildProjectsPage (references all above) cost_estimator::script_mod(vm); diff --git a/crates/apps/nigig-build/src/construction_frame/pages/workspace/project/mod.rs b/crates/apps/nigig-build/src/construction_frame/pages/workspace/project/mod.rs index dd375dd..aa307bc 100644 --- a/crates/apps/nigig-build/src/construction_frame/pages/workspace/project/mod.rs +++ b/crates/apps/nigig-build/src/construction_frame/pages/workspace/project/mod.rs @@ -69,7 +69,7 @@ script_mod! { // ---- Right dock: CAD, Docs, Spreadsheet, Invoice, Schedule, Solar (tabbed) ---- workspace_tabs := DockTabs { - tabs: [@cad_tab, @docs_tab, @crdt_docs_tab, @spreadsheet_tab, @invoice_tab, @pm_tab, @solar_tab] + tabs: [@cad_tab, @docs_tab, @spreadsheet_tab, @invoice_tab, @pm_tab, @solar_tab] selected: 0 } @@ -79,12 +79,6 @@ script_mod! { template: @PermanentTab } - crdt_docs_tab := DockTab { - name: "Docs CRDT" - kind: @crdt_docs_content - template: @PermanentTab - } - docs_tab := DockTab { name: "Docs" kind: @docs_content @@ -290,23 +284,6 @@ script_mod! { draw_bg +: { color: #x2a333c, color_hover: #x3f4b56, color_down: #x4a5b66, border_radius: 10.0 } draw_text +: { color: #xe6edf3, text_style: theme.font_bold { font_size: 13.0 } } } - desktop_open_crdt_docs_btn := Button { - width: Fill - height: 44 - text: "Documents CRDT Test" - - draw_bg +: { - color: #x4C1D95 - color_hover: #x5B21B6 - color_down: #6D28D9 - border_radius: 10 - } - - draw_text +: { - color: #xFFFFFF - text_style: theme.font_bold { font_size: 13 } - } - } desktop_open_excel_btn := Button { width: Fill, height: 44 text: "Spreadsheet" @@ -347,13 +324,6 @@ script_mod! { docs_workspace := mod.widgets.CrdtDocWorkspace {} } - crdt_docs_content := View { - width: Fill - height: Fill - - crdt_docs_workspace := mod.widgets.CrdtDocWorkspace {} - } - // Right dock: Spreadsheet workspace content spreadsheet_content := View { width: Fill, height: Fill @@ -959,15 +929,6 @@ impl BuildProjectsPage { dock.select_tab(cx, id!(docs_tab)); self.view.redraw(cx); } - if self - .view - .button(cx, ids!(desktop_open_crdt_docs_btn)) - .clicked(actions) - { - let dock = self.view.dock(cx, ids!(dock)); - dock.select_tab(cx, id!(crdt_docs_tab)); - self.view.redraw(cx); - } if self .view .button(cx, ids!(desktop_open_excel_btn)) @@ -1514,15 +1475,7 @@ impl BuildProjectsPage { .label(cx, ids!(m_workspace_title)) .set_text(cx, workspace_type); - let page = match workspace_type { - "CAD Workspace" => id!(cad_page), - "Spreadsheet" => id!(spreadsheet_page), - "Documents" => id!(doc_page), - "Invoice Builder" => id!(invoice_page), - "Project Management" => id!(project_management_page), - "Solar Calculator" => id!(solar_calculator_page), - _ => id!(cad_page), - }; + let page = workspace_page_id(workspace_type); self.view .page_flip(cx, ids!(m_workspace_flip)) .set_active_page(cx, page); @@ -1679,3 +1632,56 @@ impl BuildProjectsPage { self.view.redraw(cx); } } + +/// Maps a mobile workspace-drawer label to its overlay page. "Documents" +/// resolves to `doc_page`, whose `m_doc_content` is the CRDT-native +/// `CrdtDocWorkspace` — the mobile half of the navigation switch, kept as +/// a pure function so the destination stays pinned by tests. +fn workspace_page_id(workspace_type: &str) -> LiveId { + match workspace_type { + "CAD Workspace" => id!(cad_page), + "Spreadsheet" => id!(spreadsheet_page), + "Documents" => id!(doc_page), + "Invoice Builder" => id!(invoice_page), + "Project Management" => id!(project_management_page), + "Solar Calculator" => id!(solar_calculator_page), + _ => id!(cad_page), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn documents_navigation_targets_the_crdt_doc_page() { + assert_eq!(workspace_page_id("Documents"), id!(doc_page)); + } + + #[test] + fn every_workspace_label_maps_to_a_distinct_page() { + let labels = [ + ("CAD Workspace", id!(cad_page)), + ("Spreadsheet", id!(spreadsheet_page)), + ("Documents", id!(doc_page)), + ("Invoice Builder", id!(invoice_page)), + ("Project Management", id!(project_management_page)), + ("Solar Calculator", id!(solar_calculator_page)), + ]; + for &(label, expected) in &labels { + assert_eq!(workspace_page_id(label), expected, "label {label}"); + } + let pages: Vec = labels.iter().map(|&(label, _)| workspace_page_id(label)).collect(); + for (i, page) in pages.iter().enumerate() { + for other in pages.iter().skip(i + 1) { + assert_ne!(page, other, "workspace pages must not alias"); + } + } + } + + #[test] + fn unknown_workspace_falls_back_to_cad_page() { + assert_eq!(workspace_page_id(""), id!(cad_page)); + assert_eq!(workspace_page_id("Does Not Exist"), id!(cad_page)); + } +}