@open-mercato/core 0.6.8-develop.7029.1.a1bb3363af → 0.6.8-develop.7031.1.005201cd70
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/dist/modules/api_keys/backend/api-keys/page.js +3 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/business_rules/backend/logs/page.js +3 -1
- package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +3 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -1
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/catalog/ai-agents.js +1 -1
- package/dist/modules/catalog/ai-agents.js.map +1 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +9 -0
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
- package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deals-pack.js +4 -1
- package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/people-pack.js +4 -1
- package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +2 -1
- package/dist/modules/customers/api/deals/map/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +3 -1
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +5 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +3 -1
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/page.js +3 -1
- package/dist/modules/devices/backend/devices/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -2
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +4 -1
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +108 -48
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +3 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -0
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +3 -0
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +3 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +4 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +3 -1
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/page.js +3 -1
- package/dist/modules/workflows/backend/events/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -1
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
- package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
- package/src/modules/auth/backend/roles/page.tsx +4 -2
- package/src/modules/auth/backend/users/page.tsx +3 -2
- package/src/modules/business_rules/backend/logs/page.tsx +4 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -1
- package/src/modules/business_rules/backend/sets/page.tsx +4 -1
- package/src/modules/catalog/ai-agents.ts +1 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
- package/src/modules/configs/i18n/de.json +2 -0
- package/src/modules/configs/i18n/en.json +2 -0
- package/src/modules/configs/i18n/es.json +2 -0
- package/src/modules/configs/i18n/ko.json +2 -0
- package/src/modules/configs/i18n/pl.json +2 -0
- package/src/modules/configs/lib/system-status.ts +9 -0
- package/src/modules/currencies/backend/currencies/page.tsx +4 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -1
- package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
- package/src/modules/customers/ai-tools/deals-pack.ts +4 -1
- package/src/modules/customers/ai-tools/people-pack.ts +4 -1
- package/src/modules/customers/api/deals/map/route.ts +1 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +4 -1
- package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
- package/src/modules/customers/backend/customers/people/page.tsx +4 -1
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
- package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
- package/src/modules/devices/backend/devices/page.tsx +4 -1
- package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
- package/src/modules/entities/api/records.ts +2 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
- package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
- package/src/modules/query_index/lib/engine.ts +156 -53
- package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +5 -0
- package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
- package/src/modules/wms/commands/inventory-actions.ts +3 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +5 -0
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
- package/src/modules/workflows/backend/definitions/page.tsx +4 -1
- package/src/modules/workflows/backend/events/page.tsx +4 -1
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
|
@@ -39,6 +39,7 @@ type CategoriesResponse = {
|
|
|
39
39
|
page: number
|
|
40
40
|
pageSize: number
|
|
41
41
|
totalPages: number
|
|
42
|
+
totalIsCapped?: boolean
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
const PAGE_SIZE = 50
|
|
@@ -114,6 +115,7 @@ export default function CategoriesDataTable() {
|
|
|
114
115
|
const rows = data?.items ?? []
|
|
115
116
|
const total = data?.total ?? 0
|
|
116
117
|
const totalPages = data?.totalPages ?? 0
|
|
118
|
+
const totalIsCapped = data?.totalIsCapped === true
|
|
117
119
|
|
|
118
120
|
const columns = React.useMemo<ColumnDef<CategoryRow>[]>(() => [
|
|
119
121
|
{
|
|
@@ -249,6 +251,7 @@ export default function CategoriesDataTable() {
|
|
|
249
251
|
pageSize: PAGE_SIZE,
|
|
250
252
|
total,
|
|
251
253
|
totalPages,
|
|
254
|
+
totalIsCapped,
|
|
252
255
|
onPageChange: setPage,
|
|
253
256
|
}}
|
|
254
257
|
isLoading={isLoading}
|
|
@@ -86,6 +86,7 @@ type ProductsResponse = {
|
|
|
86
86
|
items?: ProductRow[]
|
|
87
87
|
total?: number
|
|
88
88
|
totalPages?: number
|
|
89
|
+
totalIsCapped?: boolean
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
const PAGE_SIZE = 25
|
|
@@ -177,6 +178,7 @@ export default function ProductsDataTable({
|
|
|
177
178
|
const [page, setPage] = React.useState(1)
|
|
178
179
|
const [total, setTotal] = React.useState(0)
|
|
179
180
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
181
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
180
182
|
const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)
|
|
181
183
|
const [sorting, setSorting] = React.useState<SortingState>([{ id: 'title', desc: false }])
|
|
182
184
|
const [search, setSearch] = React.useState('')
|
|
@@ -598,6 +600,7 @@ export default function ProductsDataTable({
|
|
|
598
600
|
setRows(normalized)
|
|
599
601
|
setTotal(typeof payload.total === 'number' ? payload.total : normalized.length)
|
|
600
602
|
setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)
|
|
603
|
+
setTotalIsCapped(payload.totalIsCapped === true)
|
|
601
604
|
} catch (error) {
|
|
602
605
|
if (!cancelled) {
|
|
603
606
|
setCacheStatus(null)
|
|
@@ -712,12 +715,16 @@ export default function ProductsDataTable({
|
|
|
712
715
|
// dependency on the host page.
|
|
713
716
|
total,
|
|
714
717
|
totalMatching: total,
|
|
718
|
+
// `total` is a floor when the server capped the count, so the
|
|
719
|
+
// merchandising widget must not present it as an exact match count.
|
|
720
|
+
totalIsCapped,
|
|
715
721
|
}}
|
|
716
722
|
pagination={{
|
|
717
723
|
page,
|
|
718
724
|
pageSize: PAGE_SIZE,
|
|
719
725
|
total,
|
|
720
726
|
totalPages,
|
|
727
|
+
totalIsCapped,
|
|
721
728
|
onPageChange: setPage,
|
|
722
729
|
cacheStatus,
|
|
723
730
|
}}
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Merchandising-Assistent",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} Produkte in der Ansicht",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ Produkte in der Ansicht",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} Produkte ausgewählt",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Merchandising Assistant",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} products in view",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ products in view",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} products selected",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Asistente de Merchandising",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} productos en la vista",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ productos en la vista",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} productos seleccionados",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "머천다이징 어시스턴트",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "카테고리로 필터링됨",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} 제품 보기",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "조회 중 {count}+개 제품",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} 제품 선택됨",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "태그 {count}개",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "카탈로그",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Asystent merchandisingu",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtrowane po kategorii",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} produktów w widoku",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ produktów w widoku",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "Wybrano {count} produktów",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "Tagi: {count}",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Katalog",
|
package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx
CHANGED
|
@@ -31,6 +31,8 @@ interface HostInjectionContext {
|
|
|
31
31
|
scopeVersion?: unknown
|
|
32
32
|
total?: number | string
|
|
33
33
|
totalMatching?: number | string
|
|
34
|
+
/** `totalMatching` is a floor, not an exact count (server-capped list count). */
|
|
35
|
+
totalIsCapped?: boolean
|
|
34
36
|
/** Selected row IDs from DataTable (auto-enriched when bulk actions are present). */
|
|
35
37
|
selectedRowIds?: string[]
|
|
36
38
|
selectedCount?: number
|
|
@@ -83,6 +85,7 @@ export function computeCatalogMerchandisingPageContext(
|
|
|
83
85
|
context: HostInjectionContext | undefined,
|
|
84
86
|
): MerchandisingPageContext {
|
|
85
87
|
const totalMatching = readNumber(context?.totalMatching ?? context?.total)
|
|
88
|
+
const totalMatchingIsCapped = context?.totalIsCapped === true
|
|
86
89
|
const selectedRowIds = Array.isArray(context?.selectedRowIds) ? context.selectedRowIds : []
|
|
87
90
|
const selectedCount = selectedRowIds.length > 0 ? selectedRowIds.length : readNumber(context?.selectedCount)
|
|
88
91
|
return {
|
|
@@ -93,6 +96,7 @@ export function computeCatalogMerchandisingPageContext(
|
|
|
93
96
|
extra: {
|
|
94
97
|
filter: normalizeFilters(context),
|
|
95
98
|
totalMatching,
|
|
99
|
+
totalMatchingIsCapped,
|
|
96
100
|
selectedCount,
|
|
97
101
|
},
|
|
98
102
|
}
|
|
@@ -24,6 +24,7 @@ type ChannelListResponse = {
|
|
|
24
24
|
items?: ChannelRow[]
|
|
25
25
|
total?: number
|
|
26
26
|
totalPages?: number
|
|
27
|
+
totalIsCapped?: boolean
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export default function ChannelsListPage() {
|
|
@@ -31,6 +32,7 @@ export default function ChannelsListPage() {
|
|
|
31
32
|
const [rows, setRows] = React.useState<ChannelRow[]>([])
|
|
32
33
|
const [total, setTotal] = React.useState(0)
|
|
33
34
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
35
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
34
36
|
const [page, setPage] = React.useState(1)
|
|
35
37
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
36
38
|
const [errorMessage, setErrorMessage] = React.useState<string | null>(null)
|
|
@@ -72,6 +74,7 @@ export default function ChannelsListPage() {
|
|
|
72
74
|
setRows(Array.isArray(data.items) ? data.items : [])
|
|
73
75
|
setTotal(typeof data.total === 'number' ? data.total : 0)
|
|
74
76
|
setTotalPages(typeof data.totalPages === 'number' ? data.totalPages : 1)
|
|
77
|
+
setTotalIsCapped(data.totalIsCapped === true)
|
|
75
78
|
}
|
|
76
79
|
setIsLoading(false)
|
|
77
80
|
}
|
|
@@ -139,6 +142,7 @@ export default function ChannelsListPage() {
|
|
|
139
142
|
pageSize,
|
|
140
143
|
total,
|
|
141
144
|
totalPages,
|
|
145
|
+
totalIsCapped,
|
|
142
146
|
onPageChange: setPage,
|
|
143
147
|
}}
|
|
144
148
|
/>
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Legacy-EAV-Schreibvorgänge",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Query-Index-Ergebnisse auch bei unvollständiger Abdeckung bereitstellen.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Teilindex-Nutzung erzwingen",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maximal gemeldete Gesamtzahl einer Liste; die Zählung stoppt an der Obergrenze und begrenzte Summen werden z. B. als „10 000+“ angezeigt. 0 deaktiviert die Begrenzung.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Obergrenze für Listenzählung",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Fallback-Log-Level, wenn die Verbosität nicht gesetzt ist.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Log-Level",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Überschreibt die strukturierte Log-Verbosität wie Debug oder Trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Legacy EAV writes",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Serve query index results even when coverage is partial.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Force partial index usage",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maximum reported list total; counting stops at the cap and capped totals render as e.g. “10 000+”. 0 disables capping.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "List count cap",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Fallback log level applied when verbosity is not set.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Log level",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Overrides structured log verbosity such as debug or trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Escrituras EAV heredadas",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Servir resultados del índice de consultas incluso cuando la cobertura es parcial.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Forzar uso de índice parcial",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Total máximo informado en listas; el conteo se detiene en el límite y los totales limitados se muestran p. ej. como «10 000+». 0 desactiva el límite.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Límite del conteo de listas",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Nivel de registro de respaldo cuando la verbosidad no está configurada.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Nivel de registro",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Anula la verbosidad del registro estructurado, como debug o trace.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "레거시 EAV 쓰기",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "커버리지가 부분적이어도 쿼리 인덱스 결과를 제공합니다.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "부분 인덱스 사용 강제",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "목록 총계의 최대 보고 값입니다. 카운트는 상한에서 멈추며 제한된 총계는 예를 들어 “10 000+”로 표시됩니다. 0이면 상한이 비활성화됩니다.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "목록 카운트 상한",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "상세 수준이 설정되지 않았을 때 적용되는 대체 로그 레벨입니다.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "로그 레벨",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "debug나 trace와 같은 구조화된 로그 상세 수준을 재정의합니다.",
|
|
@@ -155,6 +155,8 @@
|
|
|
155
155
|
"configs.systemStatus.variables.entitiesBackcompatEav.label": "Zapis do legacy EAV",
|
|
156
156
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.description": "Pozwala korzystać z wyników indeksu zapytań nawet przy częściowym pokryciu.",
|
|
157
157
|
"configs.systemStatus.variables.forceQueryIndexOnPartialIndexes.label": "Wymuś użycie częściowego indeksu",
|
|
158
|
+
"configs.systemStatus.variables.listCountCap.description": "Maksymalna raportowana liczba wyników listy; zliczanie zatrzymuje się na limicie, a ograniczone sumy są pokazywane np. jako „10 000+”. 0 wyłącza limit.",
|
|
159
|
+
"configs.systemStatus.variables.listCountCap.label": "Limit licznika list",
|
|
158
160
|
"configs.systemStatus.variables.logLevel.description": "Domyślny poziom logowania używany, gdy nie ustawiono szczegółowości.",
|
|
159
161
|
"configs.systemStatus.variables.logLevel.label": "Poziom logowania",
|
|
160
162
|
"configs.systemStatus.variables.logVerbosity.description": "Nadpisuje poziom szczegółowości logów, np. debug lub trace.",
|
|
@@ -267,6 +267,15 @@ export const SYSTEM_STATUS_VARIABLES: SystemStatusVariableDefinition[] = [
|
|
|
267
267
|
docUrl: `${SYSTEM_STATUS_DOC_BASE}#optimize_index_coverage_stats`,
|
|
268
268
|
defaultValue: 'false',
|
|
269
269
|
},
|
|
270
|
+
{
|
|
271
|
+
key: 'OM_LIST_COUNT_CAP',
|
|
272
|
+
category: 'query_index',
|
|
273
|
+
kind: 'string',
|
|
274
|
+
labelKey: 'configs.systemStatus.variables.listCountCap.label',
|
|
275
|
+
descriptionKey: 'configs.systemStatus.variables.listCountCap.description',
|
|
276
|
+
docUrl: `${SYSTEM_STATUS_DOC_BASE}#om_list_count_cap`,
|
|
277
|
+
defaultValue: '10000',
|
|
278
|
+
},
|
|
270
279
|
{
|
|
271
280
|
key: 'FORCE_QUERY_INDEX_ON_PARTIAL_INDEXES',
|
|
272
281
|
category: 'query_index',
|
|
@@ -41,6 +41,7 @@ type ResponsePayload = {
|
|
|
41
41
|
total: number
|
|
42
42
|
page: number
|
|
43
43
|
totalPages: number
|
|
44
|
+
totalIsCapped?: boolean
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
export default function CurrenciesPage() {
|
|
@@ -50,6 +51,7 @@ export default function CurrenciesPage() {
|
|
|
50
51
|
const [page, setPage] = React.useState(1)
|
|
51
52
|
const [total, setTotal] = React.useState(0)
|
|
52
53
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
54
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
53
55
|
const [search, setSearch] = React.useState('')
|
|
54
56
|
const [filters, setFilters] = React.useState<FilterValues>({})
|
|
55
57
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -96,6 +98,7 @@ export default function CurrenciesPage() {
|
|
|
96
98
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
97
99
|
setTotal(payload.total || 0)
|
|
98
100
|
setTotalPages(payload.totalPages || 1)
|
|
101
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
99
102
|
}
|
|
100
103
|
} catch (error) {
|
|
101
104
|
if (!cancelled) {
|
|
@@ -342,7 +345,7 @@ export default function CurrenciesPage() {
|
|
|
342
345
|
createLabel={t('currencies.list.actions.create')}
|
|
343
346
|
/>
|
|
344
347
|
)}
|
|
345
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
348
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
346
349
|
isLoading={isLoading}
|
|
347
350
|
perspective={{ tableId: extensionPoints.hosts.currenciesTable.tableId }}
|
|
348
351
|
/>
|
|
@@ -42,6 +42,7 @@ type ResponsePayload = {
|
|
|
42
42
|
total: number
|
|
43
43
|
page: number
|
|
44
44
|
totalPages: number
|
|
45
|
+
totalIsCapped?: boolean
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export default function ExchangeRatesPage() {
|
|
@@ -51,6 +52,7 @@ export default function ExchangeRatesPage() {
|
|
|
51
52
|
const [page, setPage] = React.useState(1)
|
|
52
53
|
const [total, setTotal] = React.useState(0)
|
|
53
54
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
55
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
54
56
|
const [search, setSearch] = React.useState('')
|
|
55
57
|
const [filters, setFilters] = React.useState<FilterValues>({})
|
|
56
58
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -100,6 +102,7 @@ export default function ExchangeRatesPage() {
|
|
|
100
102
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
101
103
|
setTotal(payload.total || 0)
|
|
102
104
|
setTotalPages(payload.totalPages || 1)
|
|
105
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
103
106
|
}
|
|
104
107
|
} catch (error) {
|
|
105
108
|
if (!cancelled) {
|
|
@@ -332,7 +335,7 @@ export default function ExchangeRatesPage() {
|
|
|
332
335
|
createLabel={t('exchangeRates.list.actions.create')}
|
|
333
336
|
/>
|
|
334
337
|
)}
|
|
335
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
338
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
336
339
|
isLoading={isLoading}
|
|
337
340
|
perspective={{ tableId: extensionPoints.hosts.exchangeRatesTable.tableId }}
|
|
338
341
|
/>
|
|
@@ -34,6 +34,7 @@ type RolesResponse = {
|
|
|
34
34
|
items?: RoleRow[]
|
|
35
35
|
total?: number
|
|
36
36
|
totalPages?: number
|
|
37
|
+
totalIsCapped?: boolean
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export default function CustomerRolesPage() {
|
|
@@ -45,6 +46,7 @@ export default function CustomerRolesPage() {
|
|
|
45
46
|
const [pageSize] = React.useState(50)
|
|
46
47
|
const [total, setTotal] = React.useState(0)
|
|
47
48
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
49
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
48
50
|
const [search, setSearch] = React.useState('')
|
|
49
51
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
50
52
|
const [reloadToken, setReloadToken] = React.useState(0)
|
|
@@ -88,6 +90,7 @@ export default function CustomerRolesPage() {
|
|
|
88
90
|
setRows(items)
|
|
89
91
|
setTotal(typeof payload?.total === 'number' ? payload.total : items.length)
|
|
90
92
|
setTotalPages(typeof payload?.totalPages === 'number' ? payload.totalPages : 1)
|
|
93
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
91
94
|
} catch (err) {
|
|
92
95
|
if (!cancelled) {
|
|
93
96
|
const message = err instanceof Error ? err.message : t('customer_accounts.admin.roles.error.load', 'Failed to load roles')
|
|
@@ -240,7 +243,7 @@ export default function CustomerRolesPage() {
|
|
|
240
243
|
]}
|
|
241
244
|
/>
|
|
242
245
|
)}
|
|
243
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
246
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
244
247
|
isLoading={isLoading}
|
|
245
248
|
/>
|
|
246
249
|
</PageBody>
|
|
@@ -41,6 +41,7 @@ type UsersResponse = {
|
|
|
41
41
|
items?: UserRow[]
|
|
42
42
|
total?: number
|
|
43
43
|
totalPages?: number
|
|
44
|
+
totalIsCapped?: boolean
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function formatDate(value: string | null | undefined, fallback: string): string {
|
|
@@ -235,6 +236,7 @@ export default function CustomerAccountsPage() {
|
|
|
235
236
|
const [pageSize] = React.useState(50)
|
|
236
237
|
const [total, setTotal] = React.useState(0)
|
|
237
238
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
239
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
238
240
|
const [search, setSearch] = React.useState('')
|
|
239
241
|
const [filterValues, setFilterValues] = React.useState<FilterValues>({})
|
|
240
242
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -314,6 +316,7 @@ export default function CustomerAccountsPage() {
|
|
|
314
316
|
setRows(items)
|
|
315
317
|
setTotal(typeof payload?.total === 'number' ? payload.total : items.length)
|
|
316
318
|
setTotalPages(typeof payload?.totalPages === 'number' ? payload.totalPages : 1)
|
|
319
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
317
320
|
} catch (err) {
|
|
318
321
|
if (!cancelled) {
|
|
319
322
|
const message = err instanceof Error ? err.message : t('customer_accounts.admin.error.loadUsers', 'Failed to load customer users')
|
|
@@ -579,7 +582,7 @@ export default function CustomerAccountsPage() {
|
|
|
579
582
|
]}
|
|
580
583
|
/>
|
|
581
584
|
)}
|
|
582
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
585
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
583
586
|
isLoading={isLoading}
|
|
584
587
|
/>
|
|
585
588
|
<CreateUserDialog
|
|
@@ -85,7 +85,7 @@ const listCompaniesTool = defineApiBackedAiTool<
|
|
|
85
85
|
name: 'customers.list_companies',
|
|
86
86
|
displayName: 'List companies',
|
|
87
87
|
description:
|
|
88
|
-
'Search / list companies for the caller tenant + organization. Returns { items, total, limit, offset }.',
|
|
88
|
+
'Search / list companies for the caller tenant + organization. Returns { items, total, totalIsCapped, limit, offset }. When totalIsCapped is true, total is a floor ("at least N", render it as "N+"), and pagination is exhausted only when a page returns fewer than limit items — never when offset reaches total.',
|
|
89
89
|
inputSchema: listCompaniesInput,
|
|
90
90
|
requiredFeatures: ['customers.companies.view'],
|
|
91
91
|
toOperation: (input, ctx) => {
|
|
@@ -122,6 +122,9 @@ const listCompaniesTool = defineApiBackedAiTool<
|
|
|
122
122
|
sizeBucket: row.size_bucket ?? row.sizeBucket ?? null,
|
|
123
123
|
})),
|
|
124
124
|
total: typeof data.total === 'number' ? data.total : 0,
|
|
125
|
+
// A capped count reports a floor: phrase the total as "at least N" and
|
|
126
|
+
// never treat it as proof that pagination is exhausted.
|
|
127
|
+
totalIsCapped: (data as { totalIsCapped?: boolean }).totalIsCapped === true,
|
|
125
128
|
limit,
|
|
126
129
|
offset,
|
|
127
130
|
}
|
|
@@ -99,7 +99,7 @@ const listDealsTool = defineApiBackedAiTool<ListDealsInput, ListDealsApiResponse
|
|
|
99
99
|
name: 'customers.list_deals',
|
|
100
100
|
displayName: 'List deals',
|
|
101
101
|
description:
|
|
102
|
-
'Search / list deals for the caller tenant + organization. Optional filters include linked person / company / pipeline stage.',
|
|
102
|
+
'Search / list deals for the caller tenant + organization. Optional filters include linked person / company / pipeline stage. Returns { items, total, totalIsCapped, limit, offset }. When totalIsCapped is true, total is a floor ("at least N", render it as "N+"), and pagination is exhausted only when a page returns fewer than limit items — never when offset reaches total.',
|
|
103
103
|
inputSchema: listDealsInput,
|
|
104
104
|
requiredFeatures: ['customers.deals.view'],
|
|
105
105
|
toOperation: (input, ctx) => {
|
|
@@ -155,6 +155,9 @@ const listDealsTool = defineApiBackedAiTool<ListDealsInput, ListDealsApiResponse
|
|
|
155
155
|
}
|
|
156
156
|
}),
|
|
157
157
|
total: typeof data.total === 'number' ? data.total : 0,
|
|
158
|
+
// A capped count reports a floor: phrase the total as "at least N" and
|
|
159
|
+
// never treat it as proof that pagination is exhausted.
|
|
160
|
+
totalIsCapped: (data as { totalIsCapped?: boolean }).totalIsCapped === true,
|
|
158
161
|
limit,
|
|
159
162
|
offset,
|
|
160
163
|
}
|
|
@@ -90,7 +90,7 @@ const listPeopleTool = defineApiBackedAiTool<ListPeopleInput, ListPeopleApiRespo
|
|
|
90
90
|
name: 'customers.list_people',
|
|
91
91
|
displayName: 'List people',
|
|
92
92
|
description:
|
|
93
|
-
'Search / list people (CRM persons) for the caller tenant + organization. Returns { items, total, limit, offset }.',
|
|
93
|
+
'Search / list people (CRM persons) for the caller tenant + organization. Returns { items, total, totalIsCapped, limit, offset }. When totalIsCapped is true, total is a floor ("at least N", render it as "N+"), and pagination is exhausted only when a page returns fewer than limit items — never when offset reaches total.',
|
|
94
94
|
inputSchema: listPeopleInput,
|
|
95
95
|
requiredFeatures: ['customers.people.view'],
|
|
96
96
|
toOperation: async (input, ctx) => {
|
|
@@ -144,6 +144,9 @@ const listPeopleTool = defineApiBackedAiTool<ListPeopleInput, ListPeopleApiRespo
|
|
|
144
144
|
return {
|
|
145
145
|
items: rawItems.map((row) => toCustomerListSummary(row)),
|
|
146
146
|
total: typeof data.total === 'number' ? data.total : 0,
|
|
147
|
+
// A capped count reports a floor: phrase the total as "at least N" and
|
|
148
|
+
// never treat it as proof that pagination is exhausted.
|
|
149
|
+
totalIsCapped: (data as { totalIsCapped?: boolean }).totalIsCapped === true,
|
|
147
150
|
limit,
|
|
148
151
|
offset,
|
|
149
152
|
}
|
|
@@ -118,6 +118,7 @@ type CompaniesResponse = {
|
|
|
118
118
|
total?: number
|
|
119
119
|
page?: number
|
|
120
120
|
totalPages?: number
|
|
121
|
+
totalIsCapped?: boolean
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
type DictionaryKindKey = CustomerDictionaryKind
|
|
@@ -198,6 +199,7 @@ export default function CustomersCompaniesPage() {
|
|
|
198
199
|
const [sorting, setSorting] = React.useState<SortingState>([])
|
|
199
200
|
const [total, setTotal] = React.useState(0)
|
|
200
201
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
202
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
201
203
|
const [search, setSearch] = React.useState('')
|
|
202
204
|
const pathname = usePathname()
|
|
203
205
|
const searchParams = useSearchParams()
|
|
@@ -422,6 +424,7 @@ export default function CustomersCompaniesPage() {
|
|
|
422
424
|
setRows(items.map((item) => mapApiItem(item as Record<string, unknown>)).filter((row): row is CompanyRow => !!row))
|
|
423
425
|
setTotal(typeof payload.total === 'number' ? payload.total : items.length)
|
|
424
426
|
setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)
|
|
427
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
425
428
|
} catch (err) {
|
|
426
429
|
if (!cancelled) {
|
|
427
430
|
setCacheStatus(null)
|
|
@@ -963,7 +966,7 @@ export default function CustomersCompaniesPage() {
|
|
|
963
966
|
/>
|
|
964
967
|
)}
|
|
965
968
|
virtualized
|
|
966
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage, pageSizeOptions: [10, 25, 50, 100], onPageSizeChange: handlePageSizeChange, cacheStatus }}
|
|
969
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage, pageSizeOptions: [10, 25, 50, 100], onPageSizeChange: handlePageSizeChange, cacheStatus }}
|
|
967
970
|
isLoading={isLoading}
|
|
968
971
|
/>
|
|
969
972
|
<AdvancedFilterPanel
|
|
@@ -125,6 +125,7 @@ type DealsResponse = {
|
|
|
125
125
|
items?: Array<Record<string, unknown>>
|
|
126
126
|
total?: number
|
|
127
127
|
totalPages?: number
|
|
128
|
+
totalIsCapped?: boolean
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
type FilterOption = { value: string; label: string }
|
|
@@ -210,6 +211,7 @@ export default function CustomersDealsPage() {
|
|
|
210
211
|
const [sorting, setSorting] = React.useState<import('@tanstack/react-table').SortingState>([])
|
|
211
212
|
const [total, setTotal] = React.useState(0)
|
|
212
213
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
214
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
213
215
|
const [search, setSearch] = React.useState(() => searchParams?.get('search')?.trim() ?? '')
|
|
214
216
|
const [isLoading, setIsLoading] = React.useState(false)
|
|
215
217
|
const [reloadToken, setReloadToken] = React.useState(0)
|
|
@@ -397,6 +399,7 @@ export default function CustomersDealsPage() {
|
|
|
397
399
|
setRows(mapped)
|
|
398
400
|
setTotal(typeof payload.total === 'number' ? payload.total : mapped.length)
|
|
399
401
|
setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)
|
|
402
|
+
setTotalIsCapped(payload.totalIsCapped === true)
|
|
400
403
|
} catch (err) {
|
|
401
404
|
if (!cancelled) {
|
|
402
405
|
setCacheStatus(null)
|
|
@@ -412,10 +415,12 @@ export default function CustomersDealsPage() {
|
|
|
412
415
|
}, [queryParams, reloadToken, scopeVersion, t])
|
|
413
416
|
|
|
414
417
|
React.useEffect(() => {
|
|
415
|
-
|
|
418
|
+
// A capped totalPages is a floor — pages past it hold reachable rows, so
|
|
419
|
+
// clamping would bounce a deep-linked user off data that exists.
|
|
420
|
+
if (!totalIsCapped && totalPages > 0 && page > totalPages) {
|
|
416
421
|
setPage(totalPages)
|
|
417
422
|
}
|
|
418
|
-
}, [page, totalPages])
|
|
423
|
+
}, [page, totalPages, totalIsCapped])
|
|
419
424
|
|
|
420
425
|
const queryRef = React.useRef(searchParams?.toString() ?? '')
|
|
421
426
|
React.useEffect(() => {
|
|
@@ -1136,6 +1141,7 @@ export default function CustomersDealsPage() {
|
|
|
1136
1141
|
pageSize,
|
|
1137
1142
|
total,
|
|
1138
1143
|
totalPages,
|
|
1144
|
+
totalIsCapped,
|
|
1139
1145
|
onPageChange: (nextPage) => setPage(nextPage),
|
|
1140
1146
|
pageSizeOptions: [10, 25, 50, 100],
|
|
1141
1147
|
onPageSizeChange: handlePageSizeChange,
|
|
@@ -125,6 +125,7 @@ type PeopleResponse = {
|
|
|
125
125
|
total?: number
|
|
126
126
|
page?: number
|
|
127
127
|
totalPages?: number
|
|
128
|
+
totalIsCapped?: boolean
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
type DictionaryKindKey = CustomerDictionaryKind
|
|
@@ -206,6 +207,7 @@ export default function CustomersPeoplePage() {
|
|
|
206
207
|
const [sorting, setSorting] = React.useState<SortingState>([])
|
|
207
208
|
const [total, setTotal] = React.useState(0)
|
|
208
209
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
210
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
209
211
|
const [search, setSearch] = React.useState('')
|
|
210
212
|
const pathname = usePathname()
|
|
211
213
|
const searchParams = useSearchParams()
|
|
@@ -435,6 +437,7 @@ export default function CustomersPeoplePage() {
|
|
|
435
437
|
setRows(items.map((item) => mapApiItem(item as Record<string, unknown>)).filter((row): row is PersonRow => !!row))
|
|
436
438
|
setTotal(typeof payload.total === 'number' ? payload.total : items.length)
|
|
437
439
|
setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)
|
|
440
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
438
441
|
} catch (err) {
|
|
439
442
|
if (!cancelled) {
|
|
440
443
|
setCacheStatus(null)
|
|
@@ -990,7 +993,7 @@ export default function CustomersPeoplePage() {
|
|
|
990
993
|
/>
|
|
991
994
|
)}
|
|
992
995
|
virtualized
|
|
993
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage, cacheStatus, pageSizeOptions: [10, 25, 50, 100], onPageSizeChange: handlePageSizeChange }}
|
|
996
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage, cacheStatus, pageSizeOptions: [10, 25, 50, 100], onPageSizeChange: handlePageSizeChange }}
|
|
994
997
|
isLoading={isLoading}
|
|
995
998
|
/>
|
|
996
999
|
<AdvancedFilterPanel
|
|
@@ -47,6 +47,7 @@ type CustomerTodosResponse = {
|
|
|
47
47
|
page: number
|
|
48
48
|
pageSize: number
|
|
49
49
|
totalPages: number
|
|
50
|
+
totalIsCapped?: boolean
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
const TASKS_TAB_QUERY = 'tab=tasks'
|
|
@@ -279,6 +280,7 @@ export function CustomerTodosTable(): React.JSX.Element {
|
|
|
279
280
|
pageSize,
|
|
280
281
|
total: data?.total ?? 0,
|
|
281
282
|
totalPages: data?.totalPages ?? 0,
|
|
283
|
+
totalIsCapped: data?.totalIsCapped === true,
|
|
282
284
|
onPageChange: setPage,
|
|
283
285
|
}}
|
|
284
286
|
isLoading={isLoading}
|
|
@@ -74,6 +74,7 @@ type ResponsePayload = {
|
|
|
74
74
|
total: number
|
|
75
75
|
page: number
|
|
76
76
|
totalPages: number
|
|
77
|
+
totalIsCapped?: boolean
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
type SyncOption = {
|
|
@@ -153,6 +154,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
153
154
|
const [page, setPage] = React.useState(1)
|
|
154
155
|
const [total, setTotal] = React.useState(0)
|
|
155
156
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
157
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
156
158
|
const [search, setSearch] = React.useState('')
|
|
157
159
|
const [filterValues, setFilterValues] = React.useState<FilterValues>({})
|
|
158
160
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -200,6 +202,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
200
202
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
201
203
|
setTotal(payload.total || 0)
|
|
202
204
|
setTotalPages(payload.totalPages || 1)
|
|
205
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
203
206
|
setIsLoading(false)
|
|
204
207
|
}
|
|
205
208
|
}
|
|
@@ -1065,7 +1068,7 @@ export default function SyncRunsDashboardPage() {
|
|
|
1065
1068
|
}] : []),
|
|
1066
1069
|
]} />
|
|
1067
1070
|
)}
|
|
1068
|
-
pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}
|
|
1071
|
+
pagination={{ page, pageSize: 20, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
1069
1072
|
isLoading={isLoading}
|
|
1070
1073
|
/>
|
|
1071
1074
|
</PageBody>
|
|
@@ -32,6 +32,7 @@ type ResponsePayload = {
|
|
|
32
32
|
page?: number
|
|
33
33
|
pageSize?: number
|
|
34
34
|
totalPages: number
|
|
35
|
+
totalIsCapped?: boolean
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
function formatDate(value: string | null, t: (key: string) => string) {
|
|
@@ -50,6 +51,7 @@ export default function DevicesAdminListPage() {
|
|
|
50
51
|
const [page, setPage] = React.useState(1)
|
|
51
52
|
const [total, setTotal] = React.useState(0)
|
|
52
53
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
54
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
53
55
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
54
56
|
const [reloadToken, setReloadToken] = React.useState(0)
|
|
55
57
|
const scopeVersion = useOrganizationScopeVersion()
|
|
@@ -138,6 +140,7 @@ export default function DevicesAdminListPage() {
|
|
|
138
140
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
139
141
|
setTotal(payload.total || 0)
|
|
140
142
|
setTotalPages(payload.totalPages || 1)
|
|
143
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
141
144
|
}
|
|
142
145
|
} catch (error) {
|
|
143
146
|
if (!cancelled) {
|
|
@@ -249,7 +252,7 @@ export default function DevicesAdminListPage() {
|
|
|
249
252
|
{ id: 'deactivate', label: t('devices.list.actions.deactivate'), destructive: true, onSelect: () => { void handleDeactivate(row) } },
|
|
250
253
|
]} />
|
|
251
254
|
)}
|
|
252
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
255
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
253
256
|
isLoading={isLoading}
|
|
254
257
|
/>
|
|
255
258
|
</PageBody>
|