toga-ai 1.0.592 → 1.0.594

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.
@@ -18,7 +18,7 @@
18
18
  | [TOGa IQ Sprint Dashboard API (Record Scripts)](features/sprint-dashboard-api.md) | The internal **TOGa IQ sprint dashboard** is served in production by **six api2 Record Scripts** on `_Model_Team_Sprint` (`_underscore/Model/Team/Sprint.php`), | _underscore/Model/Team/Sprint.php, api2/Component/Api/V2/V2.php, dbchanges2/Core/2026-07-24a - SprintDashboardRecordScripts.sql, dbchanges2/Client_True/2026-07-24b - SprintDashboardScriptAcl.sql |
19
19
  | [Surface action-state via the surface=<slug> request option (M2M-safe)](features/surface-meta-option.md) | An opt-in V2 engine request option, `surface=<slug>`, that attaches per-record UI action state (`isVisible`/`isEnabled`) to a GET response **under `meta.surface | api2/Component/Api/V2/V2.php, _underscore/Model/Core/Surface.php |
20
20
  | [TableView row-filtering via apiWhereClause (options.where grammar, end to end)](features/tableview-apiwhereclause-row-filtering.md) | `TableViews.apiWhereClause` (TEXT, nullable) is the sanctioned, code-free way to restrict or exclude rows from a 2.0 table view. | api2/Component/Api/V2/V2.php, _underscore/Model/Client/TableView.php, toga2-supply/src/api/toga.ts |
21
- | [TableView field/column metadata (TableViewFields, hidden projected columns)](features/tableview-field-metadata.md) | The columns of a 2.0 table view are defined by DB metadata, not code. | _underscore/Model/Client/TableView.php, api2/Component/Api/V2/V2.php, dbchanges2/Client/2026-07-20 - ItemsUuidForPurchaseOrderItemsTableView.sql |
21
+ | [TableView field/column metadata (TableViewFields, hidden projected columns)](features/tableview-field-metadata.md) | The columns of a 2.0 table view are defined by DB metadata, not code. | _underscore/Model/Client/TableView.php, api2/Component/Api/V2/V2.php, dbchanges2/Client/2026-07-20 - ItemsUuidForPurchaseOrderItemsTableView.sql, dbchanges2/Core/2026-08-17a - ItemFulfillmentQuantityFieldTypeNumber.sql, dbchanges2/Client/2026-08-17a - ItemFulfillmentColumnsCopyable.sql |
22
22
  | [Tickets API (/v2/tickets)](features/tickets-api.md) | The generic ticket endpoint of the 2.0 REST API. | Component/Api/V2/V2.php |
23
23
  | [V2 API error/message codes (EV/EZ troubleshooting map)](features/v2-api-error-codes.md) | The V2 JSON engine (`Component/Api/V2/V2.php`) returns short **message codes** in the response `error` field, grouped by family: `EN-*` authentication, `EZ-*` a | api2/Component/Api/V2/V2.php, api2/Component/Api/V2/Response/Response.php, api2/Component/Api/V2/Response/Oauth/Oauth.php, api2/Controller/Index.php, toga2-supply/src/globalTypes.ts, toga2-supply/src/pages/Orders/api/OrdersApi.ts, toga2-supply/src/api/toga.ts, _underscore/Model/Client/TrackingNumber.php |
24
24
  | [V2 request deadlock-retry — route-scoped in-process replay](features/v2-deadlock-retry.md) | api2's front controller can **detect a MySQL deadlock (1213) / lock-wait timeout (1205) and replay the whole request in-process**, so a transient lock collision | api2/Controller/Index.php, _underscore/Database.php, _underscore/Query.php |
@@ -12,6 +12,8 @@ files:
12
12
  - _underscore/Model/Client/TableView.php
13
13
  - api2/Component/Api/V2/V2.php
14
14
  - dbchanges2/Client/2026-07-20 - ItemsUuidForPurchaseOrderItemsTableView.sql
15
+ - dbchanges2/Core/2026-08-17a - ItemFulfillmentQuantityFieldTypeNumber.sql
16
+ - dbchanges2/Client/2026-08-17a - ItemFulfillmentColumnsCopyable.sql
15
17
  related:
16
18
  - tableview-apiwhereclause-row-filtering.md
17
19
  - ../../toga25-supply/features/meta-driven-table-data.md
@@ -33,7 +35,20 @@ it.
33
35
  - **`Client_*.TableViews`** — one row per view (per client DB, e.g. `Client_Nychh`).
34
36
  - **`Client_*.TableViewFields`** — one row per **column** of a view. Key columns: `recordFieldId`
35
37
  (which field this column shows), `tableViewJoinId` (which join in the view the field is reached
36
- through), `slug` (the frontend/tanstack column id), `isVisible` (0 = projected-but-hidden).
38
+ through), `slug` (the frontend/tanstack column id), `isVisible` (0 = projected-but-hidden),
39
+ and the per-view **presentation flags** `isCopyable` / `isSortable` / `isFilterable`. These
40
+ four flags **are** per-view — the same underlying field can be copyable in one view and not in
41
+ another.
42
+
43
+ ### A column's `type` / `precision` are NOT per-view — they come from `Core.RecordFields`
44
+
45
+ A field's rendered **type and precision are canonical**, read from the shared
46
+ `Core.RecordFields.type` / `Core.RecordFields.precision` — there is **no per-view type/precision
47
+ override** on `TableViewFields`. Changing `Core.RecordFields.type`/`precision` therefore changes
48
+ the column's type/format **everywhere that field appears, for every client**. That is the
49
+ intended canonical behavior — if you only want the change in one view, this mechanism cannot do
50
+ it. (Reference: `Core.RecordFields` id 369 = `ItemFulfillmentItems.quantity` set to
51
+ `type=NUMBER`, `precision=0`, which normalizes that column across all fulfillment views/clients.)
37
52
  - **`Client_*.TableViewJoins`** — the view's joins; also drive `options.join`/`ojoin` on the data
38
53
  request (see [tableview-apiwhereclause-row-filtering](tableview-apiwhereclause-row-filtering.md)).
39
54
 
@@ -87,9 +102,17 @@ per-client folder — the reference migration
87
102
  - **Make column migrations idempotent** (`NOT EXISTS` guard) — they run per client DB.
88
103
  - **`isVisible=0` still costs a fetch** — the field is selected into the projection; only the render
89
104
  is suppressed.
105
+ - **`type`/`precision` are canonical (Core-wide), not per-view.** Editing `Core.RecordFields`
106
+ changes every view/client that shows the field; there is no per-view type override. `isCopyable`,
107
+ `isSortable`, `isFilterable`, `isVisible` are the per-view knobs (on `TableViewFields`).
90
108
 
91
109
  ## Change history
92
110
 
111
+ - 2026-08-17 — Documented that a column's `type`/`precision` are canonical from `Core.RecordFields`
112
+ (no per-view override — a change hits every view/client) while `isCopyable`/`isSortable`/
113
+ `isFilterable`/`isVisible` are per-view `TableViewFields` flags. Confirmed setting
114
+ `Core.RecordFields` id 369 (`ItemFulfillmentItems.quantity`) to `type=NUMBER precision=0` and
115
+ toggling `isCopyable` per-view on the shared item-fulfillment table views. (apeterson)
93
116
  - 2026-07-20 — Documented the backend TableView column-metadata model (per-client
94
117
  `TableViews`/`TableViewFields`/`TableViewJoins`, `recordFieldId` → shared `Core.RecordFields`
95
118
  cross-DB ref, `isVisible=0` projected-but-hidden columns) and the dbchanges2 recipe for adding a
@@ -6,7 +6,7 @@ project: TOGa Blox
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-23
9
+ updated: 2026-08-17
10
10
  owners: [apeterson]
11
11
  files:
12
12
  - toga-blox/src/templates/PrimaryTable/PrimaryTable.tsx
@@ -80,7 +80,13 @@ Sticky columns use a `--sticky-offset` CSS variable summed from neighboring colu
80
80
  - Frozen widths measure only **mounted** rows; virtualized tables size from the first paint set.
81
81
  - `headerSpan` adds a separate top row (`colSpan`); only the leaf header row maps to colgroup.
82
82
  - Resize is non-persistent (local state, resets when columns change).
83
+ - **A visible column can look "missing" under `shrinkColumns`.** `shrinkColumns` (modal tables)
84
+ freezes each column to its measured header+body content width, so a column whose content is
85
+ minimal collapses to a sliver and appears absent even though it built. If a column seems gone,
86
+ confirm `isVisible=1` first (that is the only real gate), then look at its shrink/freeze width —
87
+ not the column set.
83
88
 
84
89
  ## Change history
90
+ - 2026-08-17 — Noted that under `shrinkColumns` a genuinely visible column can render at a sliver width and look "missing" — check `isVisible` and the measured/frozen width, not the column set (apeterson).
85
91
  - 2026-06-23 — Documented the three Primary Table entry points, measure-and-freeze sizing, virtualization, and sticky columns (apeterson).
86
92
  - 2026-06-22 — Added `shrinkColumns` / `minColumnWidth` shrink-to-fit for modal tables; freeze logic uses natural content width (apeterson).
@@ -6,7 +6,7 @@ project: TOGa Blox
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-23
9
+ updated: 2026-08-17
10
10
  owners: [apeterson]
11
11
  files:
12
12
  - toga-blox/src/components/Table/index.ts
@@ -96,7 +96,10 @@ Per-column header controls, each a popover trigger with `data-active` / `data-op
96
96
  is hidden while the input is focused; both the trigger button and the icon span carry
97
97
  `data-active`. The clear button must not widen the input row (fixed-width menu).
98
98
  - **`HeaderFilterRange`** — numeric, modes exactly/moreThan/lessThan + a range toggle
99
- (min/max); emits `{ key, value }[]` (`eq`/`min`/`max`/`between`).
99
+ (min/max); emits `{ key, value }[]` (`eq`/`min`/`max`/`between`). Reads its persisted
100
+ operator/values back from a `filterParams` prop (not `filterValue`, which collapses to the
101
+ literal `"active"` when a range filter is set); `PrimaryTableHeaderCell` must pass
102
+ `filterParams` through.
100
103
  - **`HeaderFilterMultiselect`** — checkbox list with "Select All"; emits comma-joined slugs.
101
104
  - **`HeaderFilterDate`** — calendar picker, modes exactly/before/after + range; converts
102
105
  `MM/DD/YYYY` ↔ URL `YYYY-MM-DD`; calendar + mode dropdown both portalled.
@@ -134,8 +137,50 @@ Per-column header controls, each a popover trigger with `data-active` / `data-op
134
137
  - The filter `includes` mode treats comma-separated values as OR.
135
138
  - `EditableCell` currency formats **on blur**, phone formats **on keystroke**.
136
139
  - Cell type config (`columnTypeConfig` prop) overrides the hardcoded `COLUMN_TYPE_CONFIG`.
140
+ - **Field `type`/`precision` come from the backend `Core.RecordFields`, not from the table-view
141
+ field.** `resolveCellType` keys off `tableViewField.type` but that value is populated upstream
142
+ from the shared Core RecordField — there is no per-view type override. Changing a column's type
143
+ or precision is a `Core.RecordFields` DB change (see
144
+ [api2 tableview-field-metadata](../../api2/features/tableview-field-metadata.md)), not a blox
145
+ change. `isCopyable`/`isVisible`/`isSortable`/`isFilterable` *are* per-view flags.
146
+ - **The only column-visibility gate is `field.isVisible`.** `buildTanstackColumns` builds a column
147
+ for every visible field. The `accessorFn` walks the `tableViewField` dot-path
148
+ (`SalesOrderItems.lineNumber` → `row.SalesOrderItems.lineNumber`), so a joined/context field is
149
+ blank unless `tableViewMeta.joins` actually provides the join. `settings.contextTable`/
150
+ `contextField` are used **only** to resolve the column *label* (`useAssignTableFieldLabels`),
151
+ never for data fetching. A visible column can still *look* missing when `shrinkColumns` freezes
152
+ it to a tiny width because its measured header+body content is minimal (see
153
+ [primary-table-templates](primary-table-templates.md)).
154
+ - **Filter presentational components must seed their internal mode/value state from props.**
155
+ The filter mode/operator survives the URL round-trip — it is persisted as a URL key suffix
156
+ (`_starts`/`_ends`/`_eq`/`_excludes` for text; `_min`/`_max`/`_eq`/`_between` for range),
157
+ rehydrated into TanStack `columnFilters` by toga25-supply `useServerTableUrlState`, and
158
+ carried through `PrimaryTableHeaderCell`. But `HeaderFilterSearch`/`HeaderFilterRange` are
159
+ remounted fresh each time a filter popover opens, so if they don't seed local state from
160
+ their props (`filterMode` / `filterParams`) they hard-default (`includes` for text,
161
+ `exactly` for range) and reopening a filter *shows the wrong mode* even though the applied
162
+ filter is correct. Fixed via a `useEffect` seeding `filterMode` from `filterModeProp` in
163
+ `HeaderFilterSearch`, and a rehydration effect keyed on `JSON.stringify(filterParams)` in
164
+ `HeaderFilterRange` that reconstructs mode + value(s) from the operator keys
165
+ (`eq`→Exactly, `min`→MoreThan, `max`→LessThan, `between`→range min/max).
166
+ - **Table/surface meta is cached with `Infinity` staleTime/gcTime** (`useFetchTablePageMeta`), so
167
+ after a DB metadata change (`TableViewFields`, `Core.RecordFields`) a **hard reload** is required
168
+ to see it. And the app consumes toga-blox's built **`dist/`**, not `src/` — editing blox source
169
+ requires `npm run build` before it takes effect at runtime.
137
170
 
138
171
  ## Change history
172
+ - 2026-08-17 — Fixed: column filter **mode** was not restored when a filter popover was reopened
173
+ (text reverted to `includes`, range to `exactly`). Root cause: the URL round-trip and
174
+ `PrimaryTableHeaderCell` preserved the mode, but `HeaderFilterSearch` (destructured
175
+ `filterMode` as `filterModeProp` and never used it) and `HeaderFilterRange` (received no
176
+ operator info) never seeded internal state from props. Seeded both from props; added a
177
+ `filterParams` prop to `HeaderFilterRange` and passed it through `PrimaryTableHeaderCell`.
178
+ (apeterson)
179
+ - 2026-08-17 — Added gotchas on meta→column mapping: field `type`/`precision` come from
180
+ `Core.RecordFields` (not per-view) while `isCopyable`/`isVisible`/`isSortable`/`isFilterable` are
181
+ per-view; `isVisible` is the only column gate; `accessorFn` dot-walks and needs the join;
182
+ `contextTable`/`contextField` drive labels only; meta is cached `Infinity` (hard reload after DB
183
+ meta change) and the app runs `dist/` (rebuild required). (apeterson)
139
184
  - 2026-06-23 — Documented the Table component layers, cell types, filters/sorts, hooks, and theming (apeterson).
140
185
  - 2026-06-23 — `HeaderFilterSearch`: search icon hidden on input focus; `data-active` added to the icon span; clear button no longer widens the input (fixed-width menu); mode dropdown excludes the selected mode (apeterson).
141
186
  - 2026-06-22 — Column sizing reworked to measure-and-freeze using natural content width; `MIN_COLUMN_WIDTH` floor (120px) applies only when no explicit width is set (apeterson).
@@ -9,7 +9,7 @@
9
9
  | [Column Visibility (URL-driven show/hide columns)](features/column-visibility.md) | A "Columns" header button that opens a modal listing every column from the table meta, lets the user show/hide columns, adjusts the table live, and persists the | toga25-supply/src/components/ColumnVisibilityModal/, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/viewModel/useSalesOrdersPageViewModel.tsx, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrdersTableData.tsx |
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
- | [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, toga25-supply/src/layout/RecordApprovalModal/helpers/handleFormatApprovalWorkflowPayload.ts, toga25-supply/src/layout/RecordApprovalModal/api/approvalDecisionsApi.ts |
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/PrimaryTableServerLayout/PrimaryTableServerLayout.tsx, toga25-supply/src/layout/PrimaryTableServerLayout/types.ts, 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, toga25-supply/src/layout/RecordApprovalModal/helpers/handleFormatApprovalWorkflowPayload.ts, toga25-supply/src/layout/RecordApprovalModal/api/approvalDecisionsApi.ts |
13
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/applyColSpan.ts, 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/view/sections/AdminNotesSection.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getAdminNotes.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,11 @@ project: TOGa 2.5 Supply
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-08-14
9
+ updated: 2026-08-17
10
10
  owners: [apeterson]
11
11
  files:
12
+ - toga25-supply/src/layout/PrimaryTableServerLayout/PrimaryTableServerLayout.tsx
13
+ - toga25-supply/src/layout/PrimaryTableServerLayout/types.ts
12
14
  - toga25-supply/src/layout/ItemRecordModalLayout/
13
15
  - toga25-supply/src/layout/SalesOrderRecordModalLayout/
14
16
  - toga25-supply/src/layout/SalesOrderItemsTableLayout/
@@ -92,6 +94,13 @@ caches the unfiltered first render (uuid null) and never refetches. Guard with `
92
94
  when uuid is null, `additionalData` returns `{}`. Typically `isPaginationEnabled: false` +
93
95
  `isInfiniteScrollingEnabled: true` (but see [meta-driven-table-data](meta-driven-table-data.md)).
94
96
 
97
+ **Read-only (non-clickable) modal tables — `disableRowClick`.** `PrimaryTableServerLayout` takes
98
+ an optional `disableRowClick?: boolean` (its `types.ts`); when set it passes `onRowClick={undefined}`
99
+ to `PrimaryTableServerTemplate` so rows render non-interactive (no cursor/hover affordance, no
100
+ navigation). `ItemFulfillmentModal` sets it because the fulfillment table is read-only. It is
101
+ scoped so all other `PrimaryTableServerLayout` consumers keep normal row-click behavior — pass it
102
+ only for genuinely read-only tables.
103
+
95
104
  ## Pattern 5 — `GenericNestedTables` (config-driven multi-level / swap tables)
96
105
 
97
106
  A config-driven renderer: declare an array of `TableLevel` objects instead of hand-wiring each
@@ -204,6 +213,9 @@ Scaffold per the `ItemRecordModalLayout` pattern (`src/layout/ItemRecordModalLay
204
213
  calling `apiDelete(route)`.
205
214
 
206
215
  ## Change history
216
+ - 2026-08-17 — Added `disableRowClick?: boolean` to `PrimaryTableServerLayout` (passes
217
+ `onRowClick={undefined}` to the template) for read-only modal tables; `ItemFulfillmentModal` uses
218
+ it. Scoped so other consumers keep normal row-click behavior. (apeterson)
207
219
  - 2026-08-14 — Fixed unassigning an approval-workflow stage: clearing the assignee now emits a
208
220
  DELETE `/approval-decisions/{uuid}` (the assignment lives on the `ApprovalDecisions` record)
209
221
  instead of silently dropping the field. Gated to fire only for a still-undecided stage
@@ -6,6 +6,7 @@ apps:
6
6
  - api2
7
7
  - toga2-supply
8
8
  - toga25-supply
9
+ - toga-blox
9
10
  - toga2-commerce
10
11
  - worker
11
12
  - worker2
@@ -15,7 +16,7 @@ project: _Underscore
15
16
  client: compass-canada
16
17
  type: profile
17
18
  status: active
18
- updated: 2026-08-12
19
+ updated: 2026-08-17
19
20
  owners: [jcardinal, bala, tcox, apeterson]
20
21
  files: []
21
22
  related:
@@ -6,6 +6,7 @@ apps:
6
6
  - api2
7
7
  - toga2-supply
8
8
  - toga25-supply
9
+ - toga-blox
9
10
  - toga2-commerce
10
11
  - worker
11
12
  - worker1.5
@@ -17,7 +18,7 @@ project: _Underscore
17
18
  client: compass-usa
18
19
  type: profile
19
20
  status: active
20
- updated: 2026-08-13
21
+ updated: 2026-08-17
21
22
  owners: [jcardinal, bala, tcox, apeterson, dfranks]
22
23
  files: []
23
24
  related:
@@ -6,6 +6,7 @@ apps:
6
6
  - api2
7
7
  - toga2-supply
8
8
  - toga25-supply
9
+ - toga-blox
9
10
  - dbchanges2
10
11
  - worker2
11
12
  - worker
@@ -14,7 +15,7 @@ project: _Underscore
14
15
  client: nychh
15
16
  type: profile
16
17
  status: active
17
- updated: 2026-08-05
18
+ updated: 2026-08-17
18
19
  owners: ["jcardinal", "apeterson", "bala"]
19
20
  files: []
20
21
  related:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.592",
3
+ "version": "1.0.594",
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",