toga-ai 1.0.516 → 1.0.517

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,6 @@
10
10
  | [Force Logout on Deployment (useDeploymentGuard)](features/force-logout-on-deployment.md) | On large deployments the backend bumps the Core parameter `META_LAST_REFRESH_DATETIME`. | toga25-supply/src/hooks/useDeploymentGuard.tsx, toga25-supply/src/App.tsx |
11
11
  | [Meta-Driven Page & Table Setup](features/meta-driven-table-data.md) | A page in this app is **meta-driven end to end**: the page view model fetches *page meta* (labels, sections, ACL) and *table meta* (the columns/fields + table s | toga25-supply/src/pages/SalesOrders/viewModel/useSalesOrdersPageViewModel.tsx, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrdersTableState.ts, toga25-supply/src/hooks/useTablePageMeta.ts, toga-blox-npm/dist/hooks/useFetchPageMeta.d.ts, toga-blox-npm/dist/hooks/useFetchTablePageMeta.d.ts, toga-blox-npm/dist/hooks/useAssignTableFieldLabels.d.ts, toga-blox-npm/dist/components/Table/hooks/useTableData.d.ts |
12
12
  | [Record Modals & Nested Tables](features/record-modals-and-nested-tables.md) | The repo's family of modal + nested-table patterns layered over toga-blox `TableRecordModal` and `PrimaryTable*Layout`. | toga25-supply/src/layout/ItemRecordModalLayout/, toga25-supply/src/layout/SalesOrderRecordModalLayout/, toga25-supply/src/layout/SalesOrderItemsTableLayout/, toga25-supply/src/layout/ItemFulfillmentModal/, toga25-supply/src/layout/GenericNestedTables/GenericNestedTables.tsx, toga25-supply/src/layout/GenericNestedTables/GenericTableLayout.tsx, toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx, toga25-supply/src/pages/Inventory/viewModel/FIELDS/DEFAULT/inventoryGroupings.json, toga25-supply/src/hooks/useTableCellInteractions.ts, toga25-supply/src/hooks/useServerTableUrlState.ts |
13
- | [Surface Frontend (DB-driven UI consumption, src/surface/)](features/surface-frontend.md) | The frontend consumer of the platform-wide Surface layer — DB-driven UI config fetched from `GET /v2/surfaces/meta?slug=<slug>` instead of statically-imported J | toga25-supply/src/surface/useFetchSurfaceMeta.ts, toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts, toga25-supply/src/pages/SalesOrders/helpers/buildPatchedTenantFields.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/SalesOrderView.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/SalesOrderSummaryGrid.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getDetailSections.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderNotesSection.tsx, toga25-supply/src/pages/SalesOrders/helpers/cleanOrder.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/index.ts, toga25-supply/src/surface/evaluateSurfaceRule.ts, toga25-supply/src/surface/resolveElementState.ts, toga25-supply/src/pages/SalesOrders/helpers/evaluateEnableRule.ts, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrderRowRecordState.ts, toga25-supply/src/surface/actionRegistry.ts, toga25-supply/src/surface/componentRegistry.tsx, toga25-supply/src/surface/SurfaceActionBar.tsx, toga25-supply/src/surface/SurfaceSection.tsx, toga25-supply/src/surface/resolve.ts, toga25-supply/src/surface/types.ts, toga25-supply/src/surface/index.ts, toga25-supply/src/pages/Login/LoginPage.tsx, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/view/SurfaceRowActions.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderTopBar.tsx, toga25-supply/src/pages/Items/ItemsPage.tsx, toga25-supply/src/pages/Items/viewModel/useItemsPageViewModel.tsx, toga25-supply/src/pages/VendorItems/VendorItemsPage.tsx, toga25-supply/src/pages/VendorItems/viewModel/useVendorItemsPageViewModel.tsx, toga25-supply/src/pages/Inventory/Inventory.tsx, toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx, toga25-supply/src/pages/Inventory/viewModel/FIELDS/index.ts, toga25-supply/src/fieldsConfig/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/surfaceBundleToItemFields.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/useItemRecordModalViewModel.tsx, toga25-supply/src/layout/ItemRecordModalLayout/ItemRecordModalLayout.tsx, toga25-supply/src/layout/ItemRecordModalLayout/components/ItemRecordView.tsx, toga25-supply/src/surface/useStatusColors.ts, toga25-supply/src/surface/SurfaceHeader.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderApprovalModalsLayout/helpers/surfaceBundlesToDecisionFields.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderApprovalModalsLayout/viewModel/useApprovalModalViewModel.tsx |
13
+ | [Surface Frontend (DB-driven UI consumption, src/surface/)](features/surface-frontend.md) | The frontend consumer of the platform-wide Surface layer — DB-driven UI config fetched from `GET /v2/surfaces/meta?slug=<slug>` instead of statically-imported J | toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/sectionRenderers.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getVisibleSections.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/SalesOrderApprovalSummaryGrid.tsx, toga25-supply/src/surface/useFetchSurfaceMeta.ts, toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts, toga25-supply/src/pages/SalesOrders/helpers/buildPatchedTenantFields.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/SalesOrderView.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/SalesOrderSummaryGrid.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getDetailSections.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderNotesSection.tsx, toga25-supply/src/pages/SalesOrders/helpers/cleanOrder.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/index.ts, toga25-supply/src/surface/evaluateSurfaceRule.ts, toga25-supply/src/surface/resolveElementState.ts, toga25-supply/src/pages/SalesOrders/helpers/evaluateEnableRule.ts, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrderRowRecordState.ts, toga25-supply/src/surface/actionRegistry.ts, toga25-supply/src/surface/componentRegistry.tsx, toga25-supply/src/surface/SurfaceActionBar.tsx, toga25-supply/src/surface/SurfaceSection.tsx, toga25-supply/src/surface/resolve.ts, toga25-supply/src/surface/types.ts, toga25-supply/src/surface/index.ts, toga25-supply/src/pages/Login/LoginPage.tsx, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/view/SurfaceRowActions.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderTopBar.tsx, toga25-supply/src/pages/Items/ItemsPage.tsx, toga25-supply/src/pages/Items/viewModel/useItemsPageViewModel.tsx, toga25-supply/src/pages/VendorItems/VendorItemsPage.tsx, toga25-supply/src/pages/VendorItems/viewModel/useVendorItemsPageViewModel.tsx, toga25-supply/src/pages/Inventory/Inventory.tsx, toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx, toga25-supply/src/pages/Inventory/viewModel/FIELDS/index.ts, toga25-supply/src/fieldsConfig/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/surfaceBundleToItemFields.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/useItemRecordModalViewModel.tsx, toga25-supply/src/layout/ItemRecordModalLayout/ItemRecordModalLayout.tsx, toga25-supply/src/layout/ItemRecordModalLayout/components/ItemRecordView.tsx, toga25-supply/src/surface/useStatusColors.ts, toga25-supply/src/surface/SurfaceHeader.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderApprovalModalsLayout/helpers/surfaceBundlesToDecisionFields.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderApprovalModalsLayout/viewModel/useApprovalModalViewModel.tsx |
14
14
  | [AWS Amplify Multi-Environment Deployment](workflows/amplify-deployment.md) | How `toga25-supply` deploys to **all** of its environments on AWS Amplify from a **single shared `amplify.yml`**. | toga25-supply/amplify.yml, toga25-supply/src/api/api.ts, toga25-supply/src/hooks/useAuthenticationFlow.ts, toga25-supply/vite.config.ts, toga25-supply/package.json |
15
15
  | [Cypress Testing Harness (component + e2e)](workflows/cypress-testing.md) | The Cypress test harness for the `toga25-supply` frontend, bootstrapped from scratch (`cypress` was already a dependency but there was no config, no `cypress/` | toga25-supply/cypress.config.ts, toga25-supply/cypress/tsconfig.json, toga25-supply/cypress/support/component.tsx, toga25-supply/cypress/support/component-index.html, toga25-supply/cypress/support/e2e.ts, toga25-supply/cypress/support/commands.ts, toga25-supply/cypress/support/fixtures.ts, toga25-supply/cypress/support/mocks/useApprovalModalViewModel.ts, toga25-supply/cypress/component/SalesOrderApprovalModalsLayout.cy.tsx, toga25-supply/cypress/component/RecordApprovalModalLayout.cy.tsx, toga25-supply/cypress/component/EnterPoNumberModal.cy.tsx, toga25-supply/cypress/e2e/salesOrderApproval.cy.ts |
@@ -6,9 +6,12 @@ project: TOGa 2.5 Supply
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-07-23
9
+ updated: 2026-08-04
10
10
  owners: [jcardinal, apeterson]
11
11
  files:
12
+ - toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/sectionRenderers.tsx
13
+ - toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getVisibleSections.ts
14
+ - toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/SalesOrderApprovalSummaryGrid.tsx
12
15
  - toga25-supply/src/surface/useFetchSurfaceMeta.ts
13
16
  - toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts
14
17
  - toga25-supply/src/pages/SalesOrders/helpers/buildPatchedTenantFields.ts
@@ -384,6 +387,50 @@ now carry it (2026-07-21):
384
387
  onto `record.order`, mirroring the record-modal view model. Both FE surfaces now carry
385
388
  `order.currentStage`/`order.stages`/`order.purchaseOrderDetails`.
386
389
 
390
+ ## SalesOrders record modal — conditional two-layout split (approval vs standard)
391
+
392
+ In approval stages the SO record modal needs a **materially different layout**, not just
393
+ different styling: the approval-details card leads and is wide, Order Details + Bill To
394
+ relocate *below* the Items table side-by-side, and Admin Notes moves to the top. This is a
395
+ placement difference **across the DOM tree**, so it is implemented as a **component split at
396
+ `SalesOrderView`** (branching on `isApprovalDetailsActive`), not prop-driven branching inside
397
+ one grid. Shared machinery was extracted so both layouts reuse it rather than duplicating:
398
+
399
+ - **`helpers/sectionRenderers.tsx`** (new) — `createSectionRenderers` factory exposes the
400
+ `detailSection`/`approvalDetails`/`locationCard`/`totalsCard` renderer map, extracted from the
401
+ grid so both the standard and approval grids share one renderer set.
402
+ - **`helpers/getVisibleSections.ts`** (new) — extracted the `isVisible` + `visibilityRule` +
403
+ approval-suppression filter into one place.
404
+ - **`layoutComponents/SalesOrderApprovalSummaryGrid.tsx`** (new, exported from the barrel) — the
405
+ approval-stage top grid: approval-details card spans 3 cols, order-summary totals 1 col
406
+ (`.approvalSummaryGrid` 4-col + `.approvalDetailsSpan` span-3, responsive).
407
+ - **`SalesOrderSummaryGrid.tsx`** slimmed to delegate to the two helpers; **`SalesOrderView.tsx`**
408
+ swaps grid + renders AdminNotes at top in the approval branch; **`getDetailSections.tsx`**
409
+ (approval-only) relocates Order Details + Bill To below the Items table and suppresses the
410
+ below-items adminNotes since it moves to top.
411
+
412
+ `isApprovalDetailsActive` drives **both** the grid swap and the section relocation, so the
413
+ approval condition lives in exactly one place.
414
+
415
+ ### Boundary rule: grid geometry is FE presentation, NOT surface metadata
416
+ **Surface owns content / visibility / order / ACL only. Column count and per-field colSpan are
417
+ FE presentation and stay in code/CSS.** The approval-details card renders into a **fixed 2-col**
418
+ `.approvalFieldsGrid` (`repeat(2, minmax(0,1fr))`) that reflows automatically as the surface
419
+ hides/shows fields — `BaseDetailField` already spans via `--field-col-span`. If per-field colSpan
420
+ is ever needed it becomes **deterministic FE logic keyed on `valueType`** (address / long-text =
421
+ wide), identical for every client — never a surface attribute.
422
+
423
+ A first attempt to surface-drive the 2-col layout via surface `config.columns` + element
424
+ `config.colSpan` was **reverted**. The reason is durable and verifiable: the resolver's **CONFIG
425
+ override REPLACES an element's whole `config` blob rather than merging it**
426
+ (`_underscore/Model/Core/Surface.php` ~L827: `$config = $value`; see
427
+ [surface-resolver](../../_underscore/features/surface-resolver.md)). Making per-client colSpan
428
+ work would have required promoting it to a first-class `COL_SPAN` in the
429
+ `SurfaceOverrides.attribute` ENUM + resolver + schema + a framework deploy — far too much
430
+ machinery for "this box is two columns wide", which is exactly the signal that it belongs in the
431
+ FE. Use this as the config/logic line for surface geometry questions: **presentation geometry →
432
+ FE/CSS; content/visibility/order/ACL → Surface.**
433
+
387
434
  ## Gotchas
388
435
 
389
436
  - **A named predicate that FAILS OPEN silently enables a button when its data isn't fetched.**
@@ -497,6 +544,21 @@ now carry it (2026-07-21):
497
544
  treat type-checking as pending. Runtime `GET /v2/surfaces/{slug}/meta` also not yet exercised.
498
545
 
499
546
  ## Change history
547
+ - 2026-08-04 — **Built** a conditional two-layout split for the SalesOrders record modal
548
+ (approval vs standard), driven by `isApprovalDetailsActive` at `SalesOrderView`. In approval
549
+ stages the approval-details card leads (wide), Order Details + Bill To move below the Items
550
+ table side-by-side, and Admin Notes moves to the top — a placement difference across the DOM
551
+ tree, so a component split over prop branching. Extracted shared machinery: `sectionRenderers.tsx`
552
+ (`createSectionRenderers` factory: detail/approvalDetails/location/totals renderers),
553
+ `getVisibleSections.ts` (visibility + approval-suppression filter), and new
554
+ `SalesOrderApprovalSummaryGrid.tsx` (4-col grid, approval-details span-3). **DECISION/DISCOVERED:**
555
+ grid geometry (column count, per-field colSpan) is FE presentation, NOT surface metadata —
556
+ surface owns content/visibility/order/ACL only. The 2-col approval-details grid is fixed FE/CSS
557
+ that reflows as the surface hides/shows fields. A first attempt to surface-drive it via
558
+ `config.columns`/`config.colSpan` was reverted after finding the resolver's **CONFIG override
559
+ wholesale-REPLACES an element's `config` blob** (`_underscore/Model/Core/Surface.php` ~L827
560
+ `$config = $value`), so a first-class `COL_SPAN` ENUM + resolver + schema + deploy would be
561
+ needed — too much machinery, the signal it belongs in the FE. (apeterson)
500
562
  - 2026-07-23 — **DECISION + FIX: surface on/off per client is now 100% backend-driven — removed the FE
501
563
  roster entirely.** Deleted `SALES_ORDER_SURFACE_MIGRATED_CLIENTS = [COMPASS,COMPASSCANADA,QUAD]` from
502
564
  `surfaceBundleToTenantFields.ts` + `helpers/index.ts`; `useSalesOrderRecordModalLayoutModel.tsx` now
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.516",
3
+ "version": "1.0.517",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",