toga-ai 1.0.737 → 1.0.739
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.
- package/knowledge/2.0/apps/toga2-commerce/INDEX.md +1 -1
- package/knowledge/2.0/apps/toga2-commerce/features/client-fields.md +25 -1
- package/knowledge/2.0/apps/toga25-supply/INDEX.md +1 -1
- package/knowledge/2.0/apps/toga25-supply/features/record-modals-and-nested-tables.md +20 -2
- package/knowledge/2.0/apps/toga25-supply/features/surface-frontend.md +22 -9
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| [Cart Page — config-driven form architecture (current state + planned refactor)](features/cart-page-config-architecture.md) | The Cart page (`src/pages/Cart/`) is the most config-heavy page in `toga2-commerce`. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/pages/Cart/view/cartForm/CartFormSection.tsx, src/pages/Cart/view/cartForm/CartFormRenderer.tsx, src/pages/Cart/view/EditCart.tsx, src/pages/Cart/view/EditOrder.tsx, src/pages/Cart/viewModel/useEditOrderOrEditCartViewModel.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts, src/hooks/useAssignClientFields.ts |
|
|
11
11
|
| [Catalog cache freshness — the 24h persisted query cache, and how to opt a query out of it](features/catalog-cache-freshness.md) | TOGa Commerce runs a **single `QueryClient` with a 24-hour default `staleTime`**, and persists it to **`localStorage["commerce"]`** through `PersistQueryClientP | toga2-commerce/src/App.tsx, toga2-commerce/src/contexts/AuthContext.tsx, toga2-commerce/src/pages/ItemsView/viewModel/useItemDetailsViewModel.ts |
|
|
12
12
|
| [Category Tile Order (AssortmentItems.sortOrder) — merchandising a storefront category](features/category-tile-sort-order.md) | **"Move item X to the front of category Y" is a DATA change, not a code change.** The order of item tiles on a storefront category page is driven by exactly one | src/pages/Filter/api/FilterApi.ts, src/pages/Filter/viewModel/useFilterViewModel.ts, api2/Component/Api/V2/V2.php, toga2-supply/src/pages/Items/api/itemsApi.ts |
|
|
13
|
-
| [Client Fields — per-tenant / language / role content & config](features/client-fields.md) | Almost no user-facing text, field layout, or page config is hard-coded in `toga2-commerce`. | src/pages/Account/view/MySettingsView.tsx, src/contexts/helpers/getLoginSettings.ts, src/pages/Account/viewModel/useAccountViewModel.ts, src/fieldsConfig/index.ts, src/fieldsConfig/getClientLoginFields.ts, src/fieldsConfig/clientFields/COMPASS.json, src/fieldsConfig/clientFields/COMPASSCANADA.json, src/fieldsConfig/clientFields/QUAD.json, src/pages/Cart/api/CartApi.ts, src/hooks/useAuthenticationFlow.ts, src/contexts/AuthContext.tsx, src/pages/Login/viewModel/useLoginPageViewModel.ts, src/hooks/useAssignClientFields.ts, src/hooks/useDynamicConditionalFieldOptions.ts, src/stores/useFieldsStore.ts, src/components/BaseDetailField/BaseDetailField.tsx, src/components/NavIcons/NavIconItem.tsx, src/components/Submenus/AlertSubmenu.tsx, src/components/Submenus/types.ts, src/pages/Account/AccountPage.tsx, src/pages/Account/view/MyOrdersView.tsx, src/pages/GetSupport/GetSupportPage.tsx, src/pages/GetSupport/viewModel/useGetSupportViewModel.ts, src/queries/queries.ts, src/App.tsx, src/pages/Filter/FilterPage.tsx, src/pages/Filter/viewModel/FIELDS/COMPASS/ENGLISH/USER/FILTERPAGEFIELDS.json |
|
|
13
|
+
| [Client Fields — per-tenant / language / role content & config](features/client-fields.md) | Almost no user-facing text, field layout, or page config is hard-coded in `toga2-commerce`. | src/pages/Account/view/MySettingsView.tsx, src/contexts/helpers/getLoginSettings.ts, src/pages/Account/viewModel/useAccountViewModel.ts, src/fieldsConfig/index.ts, src/fieldsConfig/getClientLoginFields.ts, src/fieldsConfig/clientFields/COMPASS.json, src/fieldsConfig/clientFields/COMPASSCANADA.json, src/fieldsConfig/clientFields/QUAD.json, src/pages/Cart/api/CartApi.ts, src/hooks/useAuthenticationFlow.ts, src/contexts/AuthContext.tsx, src/pages/Login/viewModel/useLoginPageViewModel.ts, src/hooks/useAssignClientFields.ts, src/hooks/useDynamicConditionalFieldOptions.ts, src/stores/useFieldsStore.ts, src/components/BaseDetailField/BaseDetailField.tsx, src/components/NavIcons/NavIconItem.tsx, src/components/Submenus/AlertSubmenu.tsx, src/components/Submenus/types.ts, src/pages/Account/AccountPage.tsx, src/pages/Account/view/MyOrdersView.tsx, src/pages/GetSupport/GetSupportPage.tsx, src/pages/GetSupport/viewModel/useGetSupportViewModel.ts, src/queries/queries.ts, src/App.tsx, src/pages/Filter/FilterPage.tsx, src/pages/Filter/viewModel/FIELDS/COMPASS/ENGLISH/USER/FILTERPAGEFIELDS.json, src/pages/Home/viewModel/FIELDS/COMPASS/ENGLISH/USER/HEADERFIELDS.json, src/components/AuthLayout/AuthLayout.tsx |
|
|
14
14
|
| [Config-Driven Expedited Shipping Gating (Cart)](features/expedited-shipping-gating.md) | On the toga2-commerce **Cart** page, expedited shipping options (**"2nd Day EOB"** and **"Next Day Air"**) are only offered in the *Shipping Method* dropdown wh | toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx, toga2-commerce/src/pages/Cart/CartPage.tsx |
|
|
15
15
|
| [Filter / Search-Results Page & the Two Search Entry Points](features/filter-search-results-page.md) | The storefront has **two distinct search entry points that render the same card component through completely different code paths and different FIELDS files**. | src/pages/Filter/FilterPage.tsx, src/pages/Filter/viewModel/useFilterViewModel.ts, src/pages/Filter/viewModel/FIELDS/COMPASS/ENGLISH/USER/FILTERPAGEFIELDS.json, src/pages/Filter/viewModel/FIELDS/COMPASSCANADA/FRENCH/USER/FILTERPAGEFIELDS.json, src/pages/Filter/viewModel/FIELDS/QUAD/ENGLISH/BUYER/FILTERPAGEFIELDS.json, src/components/Header/Header.tsx, src/pages/Home/view/components/BundlesSection.tsx, src/pages/Home/viewModel/FIELDS/COMPASS/ENGLISH/USER/HOMEPAGEFIELDS.json, src/components/Cards/BundleViewCard.tsx, src/utils/renderBadge.tsx, src/hooks/useAssignClientFields.ts |
|
|
16
16
|
| [Inactive-item purchase gating (standalone lines only — kits are exempt by design)](features/inactive-item-purchase-gating.md) | An item with **`Items.isActive = 0`** must not be viewable, addable to a cart, or orderable **as a standalone line** on the storefront — but the **same flag is | toga2-commerce/src/utils/checkIsItemPurchasable.ts, toga2-commerce/src/api/fetchItemsActiveStatus.ts, toga2-commerce/src/hooks/useCartReconciliation.ts, toga2-commerce/src/stores/useCartStoreZu.ts, toga2-commerce/src/pages/ItemsView/api/ItemsApi.ts, toga2-commerce/src/pages/ItemsView/viewModel/useItemDetailsViewModel.ts, toga2-commerce/src/pages/ItemsView/ItemViewPage.tsx, toga2-commerce/src/components/AuthLayout/AuthLayout.tsx, toga2-commerce/src/pages/Cart/CartPage.tsx, toga2-commerce/src/pages/Cart/view/cartTable/CartTableBundleItem.tsx, toga2-commerce/src/api/syncSalesOrderFromApiToLocalStorage.ts, _underscore/Model/Compass/SalesOrder.php, dbchanges2/Client_Compass/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql, dbchanges2/Client_CompassCanada/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql |
|
|
@@ -6,7 +6,7 @@ project: TOGa Commerce
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-09-02
|
|
10
10
|
owners: ["apeterson", "tcox", "bala"]
|
|
11
11
|
files:
|
|
12
12
|
- src/pages/Account/view/MySettingsView.tsx
|
|
@@ -36,6 +36,8 @@ files:
|
|
|
36
36
|
- src/App.tsx
|
|
37
37
|
- src/pages/Filter/FilterPage.tsx
|
|
38
38
|
- src/pages/Filter/viewModel/FIELDS/COMPASS/ENGLISH/USER/FILTERPAGEFIELDS.json
|
|
39
|
+
- src/pages/Home/viewModel/FIELDS/COMPASS/ENGLISH/USER/HEADERFIELDS.json
|
|
40
|
+
- src/components/AuthLayout/AuthLayout.tsx
|
|
39
41
|
related:
|
|
40
42
|
- 2.0/apps/toga2-commerce/architecture.md
|
|
41
43
|
- 2.0/apps/toga2-commerce/features/multi-tenant-theming.md
|
|
@@ -217,6 +219,13 @@ and **not every page uses every dimension**:
|
|
|
217
219
|
TermsConditions, ResetPassword (resolved at tenant/language level, shared across roles).
|
|
218
220
|
- Language layer (`ENGLISH`/`FRENCH` folders) only exists for COMPASSCANADA; COMPASS and QUAD put
|
|
219
221
|
files directly under the tenant (their registry language is `en`).
|
|
222
|
+
- **Global chrome copy lives under `Home`.** `HEADERFIELDS` / `FOOTERFIELDS` are read by
|
|
223
|
+
`src/components/AuthLayout/AuthLayout.tsx` (mounted on every authenticated route), but the JSON
|
|
224
|
+
sits at `src/pages/Home/viewModel/FIELDS/<TENANT>/[<LANGUAGE>/]<ROLE>/HEADERFIELDS.json`. There is
|
|
225
|
+
no Header page folder — grep for the key, don't look for one. The header also owns the two
|
|
226
|
+
full-width banners: `viewAsBanner` and **`editOrderBanner`** (`text.label`, `loadingText.label`,
|
|
227
|
+
`button.label`). Editing any one of these keys is a **15-file** change: COMPASS/ENGLISH × 4 roles,
|
|
228
|
+
COMPASSCANADA/{ENGLISH,FRENCH} × 4 roles, QUAD/ENGLISH × 3 roles.
|
|
220
229
|
|
|
221
230
|
## The resolver — `useAssignClientFields`
|
|
222
231
|
|
|
@@ -391,6 +400,13 @@ on switch.
|
|
|
391
400
|
pages' JSON.** The kit badge is `bundleBadge` in `HOMEPAGEFIELDS` but `kitBadge` in
|
|
392
401
|
`FILTERPAGEFIELDS`. Never assume a label added for one page covers another; grep the consuming
|
|
393
402
|
component for the exact `fields?.<key>` it reads.
|
|
403
|
+
- **The edit-order banner's exit button throws the edits away — label it accordingly.** Its
|
|
404
|
+
`actionOnClick` is `cancelEditOrder()` in `AuthLayout.tsx`, which calls
|
|
405
|
+
`exitEditOrderModeGlobalSyncReset()` (drops the local edit state, saves nothing) and then
|
|
406
|
+
redirects to `getSupplyRedirectLink(orderUuid)`. Because that data loss is not obvious from the
|
|
407
|
+
banner, the copy reads **"Cancel (Return to Supply)"** (FR "Annuler (Retour aux
|
|
408
|
+
approvisionnements)") — changed 2026-09-02 from "Exit (…)" / "Quitter (…)". Copy-only; the
|
|
409
|
+
discard behavior was already correct, so do not "restore" the Exit wording.
|
|
394
410
|
- **A stale persisted cache masks FIELDS deploys** — see the persisted-cache section above; verify
|
|
395
411
|
copy changes after `localStorage.removeItem('commerce')` or a logout, never on a warm browser.
|
|
396
412
|
- Role is derived from string `"1"` flags on the user (`user?._isAdmin === "1"`), not booleans.
|
|
@@ -410,6 +426,14 @@ on switch.
|
|
|
410
426
|
slip. Do not "reconcile" the two lists.
|
|
411
427
|
|
|
412
428
|
## Change history
|
|
429
|
+
- 2026-09-02 — Recorded where **global chrome copy** lives: `HEADERFIELDS`/`FOOTERFIELDS` are
|
|
430
|
+
consumed by the always-mounted `AuthLayout.tsx` but stored under
|
|
431
|
+
`src/pages/Home/viewModel/FIELDS/...`, and the header owns the `viewAsBanner` /
|
|
432
|
+
`editOrderBanner` keys — one banner key = **15 files** (COMPASS 4 + COMPASSCANADA 8 + QUAD 3).
|
|
433
|
+
Added the edit-order banner gotcha: its button runs `cancelEditOrder()` →
|
|
434
|
+
`exitEditOrderModeGlobalSyncReset()`, which discards unsaved order edits before redirecting to
|
|
435
|
+
Supply, so the label was changed from "Exit (Return to Supply)" to **"Cancel (Return to
|
|
436
|
+
Supply)"** (FR "Annuler (Retour aux approvisionnements)") — copy-only, no code change. (tcox)
|
|
413
437
|
- 2026-08-06 — Added a **Login-settings branches** section for `getLoginSettings.ts`: branch 1 is
|
|
414
438
|
gated by `languageSwitcher.isEnabled` and is therefore **unreachable for COMPASS/QUAD**, and within
|
|
415
439
|
Canada only **69 of 4,655** active users have a stored language, so ~98% take the "no saved
|
|
@@ -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/surface/useColumnVisibilityModalConfig.ts, toga25-supply/src/surface/index.ts, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/viewModel/useSalesOrdersPageViewModel.tsx, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrdersTableData.tsx, dbchanges2/Core/2026-08-28b - TransferOrderListActionsSurfaceSeed.sql |
|
|
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/TransferOrders/viewModel/useTransferOrdersPageViewModel.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/pages/SalesOrders/view/SalesOrderRecordModalLayout/hooks/usePurchaseOrderDetails.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/FIELDS/apiFields.json, toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts, 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/pages/TransferOrders/view/TransferOrderRecordModalLayout/TransferOrderRecordModalLayout.tsx, 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/pages/SalesOrders/view/SalesOrderRecordModalLayout/hooks/usePurchaseOrderDetails.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/FIELDS/apiFields.json, toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts, 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/pages/TransferOrders/view/TransferOrderRecordModalLayout/TransferOrderRecordModalLayout.tsx, 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, toga25-supply/src/layout/RecordApprovalModal/ApprovalModal.module.css |
|
|
13
13
|
| [Side navigation & default route — an empty nav renders a BLANK PAGE and gets reported as "cannot log in"](features/side-navigation-and-default-route.md) | The 2.5 side nav is **100% backend-driven** by the `navigation` surface bundle, and the same list also decides **which routes exist** and **where `/` lands**. | toga25-supply/src/routes.tsx, toga25-supply/src/layout/AppLayout/viewModel/useAppLayoutViewModel.ts, api2/Component/Api/V2/V2.php, _underscore/Model/Core/Surface.php |
|
|
14
14
|
| [SSO redirect & public-vs-user session gating (useAuthenticationFlow)](features/sso-redirect-and-session-gating.md) | How 2.5 Supply decides, on every navigation, whether an anonymous visitor should be bounced to their client's SSO IdP instead of the local `/login` form. | toga25-supply/src/hooks/useAuthenticationFlow.ts, toga25-supply/src/routes.tsx, toga25-supply/src/contexts/AuthContext.tsx, toga25-supply/src/api/api.ts |
|
|
15
15
|
| [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/App.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/DenialBanner.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/SalesOrderRecordModal.module.css, toga25-supply/src/pages/SalesOrders/view/SalesOrderApprovalModalsLayout/SalesOrderApprovalModalsLayout.tsx, toga25-supply/src/layout/RecordApprovalModal/RecordApprovalModalLayout.tsx, toga25-supply/src/layout/RecordApprovalModal/view/ApprovalTimelineView.tsx, toga25-supply/src/layout/RecordApprovalModal/ApprovalModal.module.css, toga25-supply/src/utils/formatDateTime.ts, toga25-supply/src/utils/index.ts, toga25-supply/src/surface/evaluateSurfaceRule.ts, toga25-supply/src/layout/RecordApprovalModal/, toga25-supply/src/contexts/AuthContext.tsx, 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/ServiceRequests/view/ServiceRequestRecordModalLayout/ServiceRequestRecordModalLayout.tsx, toga25-supply/src/pages/ServiceRequests/view/ServiceRequestRecordModalLayout/view/ServiceRequestsView.tsx, toga25-supply/src/pages/ServiceRequests/view/ServiceRequestRecordModalLayout/viewModel/useServiceRequestRecordModalLayoutModel.tsx, toga25-supply/src/pages/ServiceRequests/view/ServiceRequestRecordModalLayout/viewModel/FIELDS/apiFields.json, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderTopBar.tsx, 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/hooks/useSalesOrderVip.ts, 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 |
|
|
@@ -6,8 +6,8 @@ project: TOGa 2.5 Supply
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [apeterson]
|
|
9
|
+
updated: 2026-09-02
|
|
10
|
+
owners: [apeterson, tcox]
|
|
11
11
|
files:
|
|
12
12
|
- toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/hooks/usePurchaseOrderDetails.ts
|
|
13
13
|
- toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx
|
|
@@ -28,6 +28,7 @@ files:
|
|
|
28
28
|
- toga25-supply/src/hooks/useServerTableUrlState.ts
|
|
29
29
|
- toga25-supply/src/layout/RecordApprovalModal/helpers/handleFormatApprovalWorkflowPayload.ts
|
|
30
30
|
- toga25-supply/src/layout/RecordApprovalModal/api/approvalDecisionsApi.ts
|
|
31
|
+
- toga25-supply/src/layout/RecordApprovalModal/ApprovalModal.module.css
|
|
31
32
|
related:
|
|
32
33
|
- ../architecture.md
|
|
33
34
|
- meta-driven-table-data.md
|
|
@@ -248,6 +249,17 @@ Scaffold per the `ItemRecordModalLayout` pattern (`src/layout/ItemRecordModalLay
|
|
|
248
249
|
`handleManagerReassignment` run and revoke a VIP auto-approval for a non-VIP / over-limit new
|
|
249
250
|
manager. Adding `isApproved` "for completeness" would silently disable that backend rule.
|
|
250
251
|
|
|
252
|
+
- **The single approve/deny dialog's buttons live INSIDE the scroll region — they must be sticky.**
|
|
253
|
+
In `ApprovalModal.module.css`, `.approvalFormActions` (Submit / Cancel) sits inside
|
|
254
|
+
`.approvalDialogScroll` next to the DetailSection and the reason textarea, so a long **"Reason for
|
|
255
|
+
Request"** pushed the button row below the scroll fold and the user could not reach it. Fix (CSS
|
|
256
|
+
only): `.approvalDialog` uses `min-height: min(596px, calc(100vh - 48px))` and
|
|
257
|
+
`max-height: min(760px, calc(100vh - 48px))` — taller than the old flat 646px cap, but still capped
|
|
258
|
+
to the viewport; and `.approvalDialogScroll .approvalFormActions` is `position: sticky; bottom: 0`
|
|
259
|
+
with `background: #ffffff`, `margin-top: 0`, `padding-top: 20px`. Use **padding**, not margin — a
|
|
260
|
+
transparent margin lets scrolled content show through above the buttons. The **descendant** selector
|
|
261
|
+
is deliberate: the workflow modal's buttons live in `.approvalFlowFooter`, **outside**
|
|
262
|
+
`.approvalDialogScroll`, so the workflow modal is untouched.
|
|
251
263
|
- **ONE `TableRecordModal` must own every state — loading, error and loaded.** Rendering a second
|
|
252
264
|
`TableRecordModal` for the loaded state puts a **different element type at the same position in the
|
|
253
265
|
tree**, so React unmounts the first and mounts the second: the CSS keyframe restarts and the user
|
|
@@ -262,6 +274,12 @@ Scaffold per the `ItemRecordModalLayout` pattern (`src/layout/ItemRecordModalLay
|
|
|
262
274
|
[Transfer Orders page](transfer-orders-page.md).
|
|
263
275
|
|
|
264
276
|
## Change history
|
|
277
|
+
- 2026-09-02 — Fixed the approve/deny modal's Submit/Cancel row being cut off by a long "Reason for
|
|
278
|
+
Request" (found in testing by Skyler; approach agreed with David — grow the height a little, scroll
|
|
279
|
+
when it is very long). The single-action dialog is now taller but viewport-capped, and its action row
|
|
280
|
+
is sticky to the bottom of the scrollport with a solid background. CSS only
|
|
281
|
+
(`ApprovalModal.module.css`, commit `1a12962`); the workflow modal's footer is outside the scroll
|
|
282
|
+
region and is unchanged. (tcox)
|
|
265
283
|
- 2026-08-31 — Recorded the **selectively-unlocked `assignedTo` on a decided approval stage** and
|
|
266
284
|
the rule that its PUT must remain assignee-only (`isApproved` present makes
|
|
267
285
|
`_evaluateManagerVip` early-return, killing the reassignment revoke path). (apeterson)
|
|
@@ -6,7 +6,7 @@ project: TOGa 2.5 Supply
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-09-02
|
|
10
10
|
owners: [jcardinal, apeterson, tcox]
|
|
11
11
|
files:
|
|
12
12
|
- toga25-supply/src/App.tsx
|
|
@@ -753,14 +753,22 @@ here is a cross-screen change. Re-check Sales Orders, Items and Vendor Items aft
|
|
|
753
753
|
intentionally gated in `getDetailSections`: `shipments` is **permanently hidden** (the view-model
|
|
754
754
|
hardcodes `shipmentsData: []` and `useShipments` is commented out; the section gates on
|
|
755
755
|
`shipmentsData.length > 0`), and `invoices` is data-gated on `invoiceData.length > 0`.
|
|
756
|
-
- **`cleanOrder.ts` flattens notes by the
|
|
757
|
-
`cleanOrder` builds the legacy flat `order.reasonForRequest` /
|
|
758
|
-
`getNoteBySlug(notes, "
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
`SalesOrderNotesSection`.
|
|
756
|
+
- **`cleanOrder.ts` now flattens notes by the CORRECT slugs — `request` / `shipping`. Do not "fix" it
|
|
757
|
+
again.** Verified 2026-09-02: `cleanOrder` builds the legacy flat `order.reasonForRequest` /
|
|
758
|
+
`order.shippingInstructions` via `getNoteBySlug(notes, "request")` / `("shipping")`. This **reverses**
|
|
759
|
+
the earlier note here that it used `reasonForRequest` / `shippingInstructions` and left the legacy
|
|
760
|
+
notes blank — that latent bug was fixed in `ce47dbd` ("Refactor order notes to come from blox and
|
|
761
|
+
surface layer completely"). The field-driven notes path is unchanged: it resolves by the element's
|
|
762
|
+
`config.noteTypeSlug`; the flat path only survives as the non-migrated-client fallback in
|
|
763
|
+
`SalesOrderNotesSection`.
|
|
764
|
+
- **"Reason for Request" is NOT a column on `SalesOrders`.** It is a `SalesOrderNotes` row whose
|
|
765
|
+
`SalesOrderNoteTypes` slug is **`request`** (id `1`, name "Request Reason"); shipping instructions are
|
|
766
|
+
the same shape under slug `shipping`. To find test data: join `SalesOrderNotes`
|
|
767
|
+
(`salesOrderNoteTypeId = 1`) to `SalesOrders`; orders still awaiting approval are those with an
|
|
768
|
+
`Approvals` row (`primaryKeyId = SalesOrders.id`) whose `ApprovalDecisions.isApproved IS NULL`.
|
|
769
|
+
Confirmed on `client-sandbox` / `Client_Compass`. Note this is a different field from the **denial**
|
|
770
|
+
reason, which lives on `ApprovalDecisions.note` — see
|
|
771
|
+
[sales-order-denial-reason](../../_underscore/features/sales-order-denial-reason.md).
|
|
764
772
|
- **The surface `record` shape must match the rule field namespace — wrap as `{ order }`.** Seeded
|
|
765
773
|
Tier-1 rules namespace their field as `order._status`, so `getByPath(record, "order._status")` only
|
|
766
774
|
resolves if the host passes `record={{ order }}`. Passing the bare order object resolves to
|
|
@@ -892,6 +900,11 @@ button except **View Log** renders and does nothing on click. Whether the SR mod
|
|
|
892
900
|
actions surface is **still an open decision**, not an oversight.
|
|
893
901
|
|
|
894
902
|
## Change history
|
|
903
|
+
- 2026-09-02 — Corrected the `cleanOrder.ts` note-slug gotcha: it flattens by the **real** slugs
|
|
904
|
+
`request` / `shipping` (fixed in `ce47dbd`), so the "latent blank-notes bug" recorded earlier no
|
|
905
|
+
longer exists. Added where "Reason for Request" actually lives (`SalesOrderNotes` +
|
|
906
|
+
`SalesOrderNoteTypes.slug = 'request'`, id 1 "Request Reason") and the query for finding
|
|
907
|
+
pending-approval test orders. (tcox)
|
|
895
908
|
- 2026-08-31 — **Built** the sales-order **denial banner** + read-only **approval timeline**
|
|
896
909
|
(`toga25-supply@TRUE-80850` `ca6678f`, pushed, no PR; verified rendering on `client-sandbox`).
|
|
897
910
|
Two durable FE patterns. (1) **A surface section can drive a BANNER, not a grid card**:
|
package/package.json
CHANGED