@open-mercato/core 0.6.8-develop.7030.1.b84302d973 → 0.6.8-develop.7032.1.70d74d4bfe
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/business_rules/lib/expression-evaluator.js +9 -9
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +10 -9
- package/dist/modules/business_rules/lib/rule-evaluator.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/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/business_rules/lib/expression-evaluator.ts +9 -9
- package/src/modules/business_rules/lib/rule-evaluator.ts +10 -9
- 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/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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/workflows/backend/instances/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/workflows/extension-points'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype WorkflowInstance = {\n id: string\n definitionId: string\n workflowId: string\n version: number\n status: 'RUNNING' | 'PAUSED' | 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'COMPENSATING' | 'COMPENSATED'\n currentStepId: string\n correlationKey: string | null\n startedAt: string\n completedAt: string | null\n cancelledAt: string | null\n errorMessage: string | null\n retryCount: number\n tenantId: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\ntype InstancesResponse = {\n data: WorkflowInstance[]\n pagination: {\n total: number\n limit: number\n offset: number\n hasMore: boolean\n }\n}\n\nexport default function WorkflowInstancesListPage() {\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(50)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const t = useT()\n const router = useRouter()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflow-instances', 'list', filterValues, page],\n queryFn: async () => {\n const params = new URLSearchParams()\n const offset = (page - 1) * pageSize\n params.set('limit', pageSize.toString())\n params.set('offset', offset.toString())\n\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.workflowId) params.set('workflowId', filterValues.workflowId as string)\n if (filterValues.correlationKey) params.set('correlationKey', filterValues.correlationKey as string)\n if (filterValues.entityType) params.set('entityType', filterValues.entityType as string)\n if (filterValues.entityId) params.set('entityId', filterValues.entityId as string)\n\n const result = await apiCall<InstancesResponse>(\n `/api/workflows/instances?${params.toString()}`\n )\n\n if (!result.ok) {\n throw new Error('Failed to fetch workflow instances')\n }\n\n const response = result.result\n if (response?.pagination) {\n setTotal(response.pagination.total || 0)\n const calculatedPages = Math.ceil((response.pagination.total || 0) / pageSize)\n setTotalPages(calculatedPages || 1)\n }\n\n return response?.data || []\n },\n })\n\n const handleCancel = async (id: string, workflowId: string) => {\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirm.cancel', { id: workflowId }),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n const result = await apiCall(`/api/workflows/instances/${id}/cancel`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.instances.messages.cancelled'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })\n } else {\n flash(t('workflows.instances.messages.cancelFailed'), 'error')\n }\n }\n\n const handleRetry = async (id: string, workflowId: string) => {\n const ok = await confirmDialog({\n title: t('workflows.instances.confirm.retry', { id: workflowId }),\n variant: 'default',\n })\n if (!ok) {\n return\n }\n\n const result = await apiCall(`/api/workflows/instances/${id}/retry`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.instances.messages.retried'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })\n } else {\n flash(t('workflows.instances.messages.retryFailed'), 'error')\n }\n }\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const getStatusBadgeClass = (status: WorkflowInstance['status']) => {\n switch (status) {\n case 'RUNNING':\n return 'bg-status-info-bg text-status-info-text'\n case 'PAUSED':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'COMPLETED':\n return 'bg-status-success-bg text-status-success-text'\n case 'FAILED':\n return 'bg-status-error-bg text-status-error-text'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n case 'COMPENSATING':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'COMPENSATED':\n return 'bg-status-neutral-bg text-status-neutral-text'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('workflows.instances.filters.status'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.instances.status.RUNNING'), value: 'RUNNING' },\n { label: t('workflows.instances.status.PAUSED'), value: 'PAUSED' },\n { label: t('workflows.instances.status.COMPLETED'), value: 'COMPLETED' },\n { label: t('workflows.instances.status.FAILED'), value: 'FAILED' },\n { label: t('workflows.instances.status.CANCELLED'), value: 'CANCELLED' },\n { label: t('workflows.instances.status.COMPENSATING'), value: 'COMPENSATING' },\n { label: t('workflows.instances.status.COMPENSATED'), value: 'COMPENSATED' },\n ],\n },\n {\n id: 'workflowId',\n type: 'text',\n label: t('workflows.instances.filters.workflowId'),\n placeholder: t('workflows.instances.filters.workflowIdPlaceholder'),\n },\n {\n id: 'correlationKey',\n type: 'text',\n label: t('workflows.instances.filters.correlationKey'),\n placeholder: t('workflows.instances.filters.correlationKeyPlaceholder'),\n },\n {\n id: 'entityType',\n type: 'text',\n label: t('workflows.instances.filters.entityType'),\n placeholder: t('workflows.instances.filters.entityTypePlaceholder'),\n },\n {\n id: 'entityId',\n type: 'text',\n label: t('workflows.instances.filters.entityId'),\n placeholder: t('workflows.instances.filters.entityIdPlaceholder'),\n },\n ]\n\n const columns: ColumnDef<WorkflowInstance>[] = [\n {\n id: 'workflowId',\n header: t('workflows.instances.fields.workflowId'),\n accessorKey: 'workflowId',\n cell: ({ row }) => (\n <Link href={`/backend/instances/${row.original.id}`} className=\"block hover:underline\">\n <div className=\"font-mono text-sm font-medium\">{row.original.workflowId}</div>\n {row.original.correlationKey && (\n <div className=\"text-xs text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}: {row.original.correlationKey}\n </div>\n )}\n </Link>\n ),\n },\n {\n id: 'status',\n header: t('workflows.instances.fields.status'),\n accessorKey: 'status',\n cell: ({ row }) => (\n <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>\n {t(`workflows.instances.status.${row.original.status}`)}\n </span>\n ),\n },\n {\n id: 'currentStep',\n header: t('workflows.instances.fields.currentStep'),\n accessorKey: 'currentStepId',\n cell: ({ row }) => (\n <span className=\"text-sm text-muted-foreground\">{row.original.currentStepId}</span>\n ),\n },\n {\n id: 'timing',\n header: t('workflows.instances.fields.timing'),\n cell: ({ row }) => {\n const started = new Date(row.original.startedAt)\n const completed = row.original.completedAt ? new Date(row.original.completedAt) : null\n const duration = completed ? completed.getTime() - started.getTime() : Date.now() - started.getTime()\n const durationText = duration < 60000\n ? `${Math.floor(duration / 1000)}s`\n : `${Math.floor(duration / 60000)}m`\n\n return (\n <div className=\"text-sm\">\n <div className=\"text-foreground\">{started.toLocaleString()}</div>\n <div className=\"text-xs text-muted-foreground\">\n {completed ? t('workflows.instances.duration') : t('workflows.instances.elapsed')}: {durationText}\n </div>\n </div>\n )\n },\n },\n {\n id: 'retryCount',\n header: t('workflows.instances.fields.retryCount'),\n accessorKey: 'retryCount',\n cell: ({ row }) => (\n <span className={`text-sm ${row.original.retryCount > 0 ? 'text-status-warning-text font-medium' : 'text-muted-foreground'}`}>\n {row.original.retryCount}\n </span>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n const items: Array<{ id: string; label: string; href?: string; onSelect?: () => void }> = [\n {\n id: 'view',\n label: t('workflows.instances.actions.viewDetails'),\n href: `/backend/instances/${row.original.id}`,\n },\n ]\n\n if (row.original.status === 'RUNNING' || row.original.status === 'PAUSED') {\n items.push({\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: () => void handleCancel(row.original.id, row.original.workflowId),\n })\n }\n\n if (row.original.status === 'FAILED') {\n items.push({\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: () => void handleRetry(row.original.id, row.original.workflowId),\n })\n }\n\n return <RowActions items={items} />\n },\n },\n ]\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <div className=\"p-8 text-center\">\n <p className=\"text-status-error-text\">{t('workflows.instances.messages.loadFailed')}</p>\n <Button onClick={() => queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })} className=\"mt-4\">\n {t('common.retry')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('workflows.instances.list.title')}\n columns={columns}\n data={data || []}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n perspective={{\n tableId: extensionPoints.hosts.instancesTable.tableId,\n }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/workflows/extension-points'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype WorkflowInstance = {\n id: string\n definitionId: string\n workflowId: string\n version: number\n status: 'RUNNING' | 'PAUSED' | 'COMPLETED' | 'FAILED' | 'CANCELLED' | 'COMPENSATING' | 'COMPENSATED'\n currentStepId: string\n correlationKey: string | null\n startedAt: string\n completedAt: string | null\n cancelledAt: string | null\n errorMessage: string | null\n retryCount: number\n tenantId: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\ntype InstancesResponse = {\n data: WorkflowInstance[]\n pagination: {\n total: number\n limit: number\n offset: number\n hasMore: boolean\n totalIsCapped?: boolean\n }\n}\n\nexport default function WorkflowInstancesListPage() {\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(50)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const t = useT()\n const router = useRouter()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflow-instances', 'list', filterValues, page],\n queryFn: async () => {\n const params = new URLSearchParams()\n const offset = (page - 1) * pageSize\n params.set('limit', pageSize.toString())\n params.set('offset', offset.toString())\n\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.workflowId) params.set('workflowId', filterValues.workflowId as string)\n if (filterValues.correlationKey) params.set('correlationKey', filterValues.correlationKey as string)\n if (filterValues.entityType) params.set('entityType', filterValues.entityType as string)\n if (filterValues.entityId) params.set('entityId', filterValues.entityId as string)\n\n const result = await apiCall<InstancesResponse>(\n `/api/workflows/instances?${params.toString()}`\n )\n\n if (!result.ok) {\n throw new Error('Failed to fetch workflow instances')\n }\n\n const response = result.result\n if (response?.pagination) {\n setTotal(response.pagination.total || 0)\n const calculatedPages = Math.ceil((response.pagination.total || 0) / pageSize)\n setTotalPages(calculatedPages || 1)\n setTotalIsCapped(response.pagination?.totalIsCapped === true)\n }\n\n return response?.data || []\n },\n })\n\n const handleCancel = async (id: string, workflowId: string) => {\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirm.cancel', { id: workflowId }),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n const result = await apiCall(`/api/workflows/instances/${id}/cancel`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.instances.messages.cancelled'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })\n } else {\n flash(t('workflows.instances.messages.cancelFailed'), 'error')\n }\n }\n\n const handleRetry = async (id: string, workflowId: string) => {\n const ok = await confirmDialog({\n title: t('workflows.instances.confirm.retry', { id: workflowId }),\n variant: 'default',\n })\n if (!ok) {\n return\n }\n\n const result = await apiCall(`/api/workflows/instances/${id}/retry`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.instances.messages.retried'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })\n } else {\n flash(t('workflows.instances.messages.retryFailed'), 'error')\n }\n }\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const getStatusBadgeClass = (status: WorkflowInstance['status']) => {\n switch (status) {\n case 'RUNNING':\n return 'bg-status-info-bg text-status-info-text'\n case 'PAUSED':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'COMPLETED':\n return 'bg-status-success-bg text-status-success-text'\n case 'FAILED':\n return 'bg-status-error-bg text-status-error-text'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n case 'COMPENSATING':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'COMPENSATED':\n return 'bg-status-neutral-bg text-status-neutral-text'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('workflows.instances.filters.status'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.instances.status.RUNNING'), value: 'RUNNING' },\n { label: t('workflows.instances.status.PAUSED'), value: 'PAUSED' },\n { label: t('workflows.instances.status.COMPLETED'), value: 'COMPLETED' },\n { label: t('workflows.instances.status.FAILED'), value: 'FAILED' },\n { label: t('workflows.instances.status.CANCELLED'), value: 'CANCELLED' },\n { label: t('workflows.instances.status.COMPENSATING'), value: 'COMPENSATING' },\n { label: t('workflows.instances.status.COMPENSATED'), value: 'COMPENSATED' },\n ],\n },\n {\n id: 'workflowId',\n type: 'text',\n label: t('workflows.instances.filters.workflowId'),\n placeholder: t('workflows.instances.filters.workflowIdPlaceholder'),\n },\n {\n id: 'correlationKey',\n type: 'text',\n label: t('workflows.instances.filters.correlationKey'),\n placeholder: t('workflows.instances.filters.correlationKeyPlaceholder'),\n },\n {\n id: 'entityType',\n type: 'text',\n label: t('workflows.instances.filters.entityType'),\n placeholder: t('workflows.instances.filters.entityTypePlaceholder'),\n },\n {\n id: 'entityId',\n type: 'text',\n label: t('workflows.instances.filters.entityId'),\n placeholder: t('workflows.instances.filters.entityIdPlaceholder'),\n },\n ]\n\n const columns: ColumnDef<WorkflowInstance>[] = [\n {\n id: 'workflowId',\n header: t('workflows.instances.fields.workflowId'),\n accessorKey: 'workflowId',\n cell: ({ row }) => (\n <Link href={`/backend/instances/${row.original.id}`} className=\"block hover:underline\">\n <div className=\"font-mono text-sm font-medium\">{row.original.workflowId}</div>\n {row.original.correlationKey && (\n <div className=\"text-xs text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}: {row.original.correlationKey}\n </div>\n )}\n </Link>\n ),\n },\n {\n id: 'status',\n header: t('workflows.instances.fields.status'),\n accessorKey: 'status',\n cell: ({ row }) => (\n <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>\n {t(`workflows.instances.status.${row.original.status}`)}\n </span>\n ),\n },\n {\n id: 'currentStep',\n header: t('workflows.instances.fields.currentStep'),\n accessorKey: 'currentStepId',\n cell: ({ row }) => (\n <span className=\"text-sm text-muted-foreground\">{row.original.currentStepId}</span>\n ),\n },\n {\n id: 'timing',\n header: t('workflows.instances.fields.timing'),\n cell: ({ row }) => {\n const started = new Date(row.original.startedAt)\n const completed = row.original.completedAt ? new Date(row.original.completedAt) : null\n const duration = completed ? completed.getTime() - started.getTime() : Date.now() - started.getTime()\n const durationText = duration < 60000\n ? `${Math.floor(duration / 1000)}s`\n : `${Math.floor(duration / 60000)}m`\n\n return (\n <div className=\"text-sm\">\n <div className=\"text-foreground\">{started.toLocaleString()}</div>\n <div className=\"text-xs text-muted-foreground\">\n {completed ? t('workflows.instances.duration') : t('workflows.instances.elapsed')}: {durationText}\n </div>\n </div>\n )\n },\n },\n {\n id: 'retryCount',\n header: t('workflows.instances.fields.retryCount'),\n accessorKey: 'retryCount',\n cell: ({ row }) => (\n <span className={`text-sm ${row.original.retryCount > 0 ? 'text-status-warning-text font-medium' : 'text-muted-foreground'}`}>\n {row.original.retryCount}\n </span>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n const items: Array<{ id: string; label: string; href?: string; onSelect?: () => void }> = [\n {\n id: 'view',\n label: t('workflows.instances.actions.viewDetails'),\n href: `/backend/instances/${row.original.id}`,\n },\n ]\n\n if (row.original.status === 'RUNNING' || row.original.status === 'PAUSED') {\n items.push({\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: () => void handleCancel(row.original.id, row.original.workflowId),\n })\n }\n\n if (row.original.status === 'FAILED') {\n items.push({\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: () => void handleRetry(row.original.id, row.original.workflowId),\n })\n }\n\n return <RowActions items={items} />\n },\n },\n ]\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <div className=\"p-8 text-center\">\n <p className=\"text-status-error-text\">{t('workflows.instances.messages.loadFailed')}</p>\n <Button onClick={() => queryClient.invalidateQueries({ queryKey: ['workflow-instances'] })} className=\"mt-4\">\n {t('common.retry')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('workflows.instances.list.title')}\n columns={columns}\n data={data || []}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n perspective={{\n tableId: extensionPoints.hosts.instancesTable.tableId,\n }}\n pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -17,6 +17,7 @@ function UserTasksListPage() {
|
|
|
17
17
|
const [pageSize] = React.useState(50);
|
|
18
18
|
const [total, setTotal] = React.useState(0);
|
|
19
19
|
const [totalPages, setTotalPages] = React.useState(1);
|
|
20
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false);
|
|
20
21
|
const t = useT();
|
|
21
22
|
const router = useRouter();
|
|
22
23
|
const queryClient = useQueryClient();
|
|
@@ -46,6 +47,7 @@ function UserTasksListPage() {
|
|
|
46
47
|
setTotal(response.pagination.total || 0);
|
|
47
48
|
const calculatedPages = Math.ceil((response.pagination.total || 0) / pageSize);
|
|
48
49
|
setTotalPages(calculatedPages || 1);
|
|
50
|
+
setTotalIsCapped(response.pagination?.totalIsCapped === true);
|
|
49
51
|
}
|
|
50
52
|
return response?.data || [];
|
|
51
53
|
}
|
|
@@ -247,7 +249,7 @@ function UserTasksListPage() {
|
|
|
247
249
|
perspective: {
|
|
248
250
|
tableId: extensionPoints.hosts.tasksTable.tableId
|
|
249
251
|
},
|
|
250
|
-
pagination: { page, pageSize, total, totalPages, onPageChange: setPage }
|
|
252
|
+
pagination: { page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }
|
|
251
253
|
}
|
|
252
254
|
) }),
|
|
253
255
|
ConfirmDialogElement
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/workflows/backend/tasks/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/workflows/extension-points'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype UserTaskStatus = 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED'\n\ntype UserTask = {\n id: string\n workflowInstanceId: string\n stepInstanceId: string\n taskName: string\n description: string | null\n status: UserTaskStatus\n formSchema: any | null\n formData: any | null\n assignedTo: string | null\n assignedToRoles: string[] | null\n claimedBy: string | null\n claimedAt: string | null\n dueDate: string | null\n escalatedAt: string | null\n escalatedTo: string | null\n completedBy: string | null\n completedAt: string | null\n comments: string | null\n tenantId: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\ntype TasksResponse = {\n data: UserTask[]\n pagination: {\n total: number\n limit: number\n offset: number\n hasMore: boolean\n }\n}\n\nexport default function UserTasksListPage() {\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(50)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const t = useT()\n const router = useRouter()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({\n myTasks: 'true', // Default to \"My Tasks\" view\n })\n\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflow-tasks', 'list', filterValues, page],\n queryFn: async () => {\n const params = new URLSearchParams()\n const offset = (page - 1) * pageSize\n params.set('limit', pageSize.toString())\n params.set('offset', offset.toString())\n\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.overdue === 'true') params.set('overdue', 'true')\n if (filterValues.workflowInstanceId) params.set('workflowInstanceId', filterValues.workflowInstanceId as string)\n\n const result = await apiCall<TasksResponse>(\n `/api/workflows/tasks?${params.toString()}`\n )\n\n if (!result.ok) {\n throw new Error('Failed to fetch user tasks')\n }\n\n const response = result.result\n if (response?.pagination) {\n setTotal(response.pagination.total || 0)\n const calculatedPages = Math.ceil((response.pagination.total || 0) / pageSize)\n setTotalPages(calculatedPages || 1)\n }\n\n return response?.data || []\n },\n })\n\n const handleClaim = async (id: string, taskName: string) => {\n const confirmed = await confirmDialog({\n title: t('workflows.tasks.confirm.claim', { name: taskName }),\n variant: 'default',\n })\n if (!confirmed) {\n return\n }\n\n const result = await apiCall(`/api/workflows/tasks/${id}/claim`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.tasks.messages.claimed'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-tasks'] })\n } else {\n flash(t('workflows.tasks.messages.claimFailed'), 'error')\n }\n }\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({ myTasks: 'true' })\n setPage(1)\n }, [])\n\n const getStatusBadgeClass = (status: UserTaskStatus) => {\n switch (status) {\n case 'PENDING':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'IN_PROGRESS':\n return 'bg-status-info-bg text-status-info-text'\n case 'COMPLETED':\n return 'bg-status-success-bg text-status-success-text'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const isOverdue = (task: UserTask) => {\n if (!task.dueDate || task.status === 'COMPLETED' || task.status === 'CANCELLED') {\n return false\n }\n return new Date(task.dueDate) < new Date()\n }\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('workflows.tasks.filters.status'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.tasks.statuses.PENDING'), value: 'PENDING' },\n { label: t('workflows.tasks.statuses.IN_PROGRESS'), value: 'IN_PROGRESS' },\n { label: t('workflows.tasks.statuses.COMPLETED'), value: 'COMPLETED' },\n { label: t('workflows.tasks.statuses.CANCELLED'), value: 'CANCELLED' },\n ],\n },\n {\n id: 'myTasks',\n type: 'select',\n label: t('workflows.tasks.filters.view'),\n options: [\n { label: t('workflows.tasks.filters.myTasks'), value: 'true' },\n { label: t('workflows.tasks.filters.allTasks'), value: '' },\n ],\n },\n {\n id: 'overdue',\n type: 'select',\n label: t('workflows.tasks.filters.overdue'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.tasks.filters.overdueOnly'), value: 'true' },\n ],\n },\n {\n id: 'workflowInstanceId',\n type: 'text',\n label: t('workflows.tasks.filters.workflowInstanceId'),\n placeholder: t('workflows.tasks.filters.workflowInstanceIdPlaceholder'),\n },\n ]\n\n const columns: ColumnDef<UserTask>[] = [\n {\n id: 'taskName',\n header: t('workflows.tasks.fields.taskName'),\n accessorKey: 'taskName',\n cell: ({ row }) => (\n <div>\n <div className=\"font-medium text-sm\">{row.original.taskName}</div>\n {row.original.description && (\n <div className=\"text-xs text-muted-foreground line-clamp-1\">\n {row.original.description}\n </div>\n )}\n {isOverdue(row.original) && (\n <div className=\"text-xs text-status-error-text font-medium mt-1\">\n {t('workflows.tasks.overdue')}\n </div>\n )}\n </div>\n ),\n },\n {\n id: 'status',\n header: t('workflows.tasks.fields.status'),\n accessorKey: 'status',\n cell: ({ row }) => (\n <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>\n {t(`workflows.tasks.statuses.${row.original.status}`)}\n </span>\n ),\n },\n {\n id: 'assignment',\n header: t('workflows.tasks.fields.assignment'),\n cell: ({ row }) => {\n if (row.original.claimedBy) {\n return (\n <div className=\"text-sm\">\n <div className=\"text-foreground\">{t('workflows.tasks.claimedBy')}: {row.original.claimedBy}</div>\n </div>\n )\n }\n if (row.original.assignedTo) {\n return <div className=\"text-sm text-foreground\">{row.original.assignedTo}</div>\n }\n if (row.original.assignedToRoles && row.original.assignedToRoles.length > 0) {\n return (\n <div className=\"text-sm text-muted-foreground\">\n {t('workflows.tasks.roles')}: {row.original.assignedToRoles.join(', ')}\n </div>\n )\n }\n return <span className=\"text-sm text-muted-foreground\">-</span>\n },\n },\n {\n id: 'dueDate',\n header: t('workflows.tasks.fields.dueDate'),\n accessorKey: 'dueDate',\n cell: ({ row }) => {\n if (!row.original.dueDate) {\n return <span className=\"text-sm text-muted-foreground\">-</span>\n }\n const dueDate = new Date(row.original.dueDate)\n const overdue = isOverdue(row.original)\n return (\n <div className={`text-sm ${overdue ? 'text-status-error-text font-medium' : 'text-foreground'}`}>\n {dueDate.toLocaleString()}\n </div>\n )\n },\n },\n {\n id: 'createdAt',\n header: t('workflows.tasks.fields.createdAt'),\n accessorKey: 'createdAt',\n cell: ({ row }) => (\n <span className=\"text-sm text-muted-foreground\">\n {new Date(row.original.createdAt).toLocaleString()}\n </span>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n const items: Array<{ id: string; label: string; href?: string; onSelect?: () => void }> = [\n {\n id: 'view',\n label: t('workflows.tasks.actions.viewDetails'),\n href: `/backend/tasks/${row.original.id}`,\n },\n ]\n\n // Allow claiming if task is PENDING and assigned to roles (not specific user)\n if (\n row.original.status === 'PENDING' &&\n !row.original.assignedTo &&\n row.original.assignedToRoles &&\n row.original.assignedToRoles.length > 0\n ) {\n items.push({\n id: 'claim',\n label: t('workflows.tasks.actions.claim'),\n onSelect: () => void handleClaim(row.original.id, row.original.taskName),\n })\n }\n\n // Allow completing if task is in progress or pending\n if (row.original.status === 'PENDING' || row.original.status === 'IN_PROGRESS') {\n items.push({\n id: 'complete',\n label: t('workflows.tasks.actions.complete'),\n href: `/backend/tasks/${row.original.id}`,\n })\n }\n\n return <RowActions items={items} />\n },\n },\n ]\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <div className=\"p-8 text-center\">\n <p className=\"text-status-error-text\">{t('workflows.tasks.messages.loadFailed')}</p>\n <Button onClick={() => queryClient.invalidateQueries({ queryKey: ['workflow-tasks'] })} className=\"mt-4\">\n {t('common.retry')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('workflows.tasks.list.title')}\n columns={columns}\n data={data || []}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n perspective={{\n tableId: extensionPoints.hosts.tasksTable.tableId,\n }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/workflows/extension-points'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype UserTaskStatus = 'PENDING' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED'\n\ntype UserTask = {\n id: string\n workflowInstanceId: string\n stepInstanceId: string\n taskName: string\n description: string | null\n status: UserTaskStatus\n formSchema: any | null\n formData: any | null\n assignedTo: string | null\n assignedToRoles: string[] | null\n claimedBy: string | null\n claimedAt: string | null\n dueDate: string | null\n escalatedAt: string | null\n escalatedTo: string | null\n completedBy: string | null\n completedAt: string | null\n comments: string | null\n tenantId: string\n organizationId: string\n createdAt: string\n updatedAt: string\n}\n\ntype TasksResponse = {\n data: UserTask[]\n pagination: {\n total: number\n limit: number\n offset: number\n hasMore: boolean\n totalIsCapped?: boolean\n }\n}\n\nexport default function UserTasksListPage() {\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(50)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const t = useT()\n const router = useRouter()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({\n myTasks: 'true', // Default to \"My Tasks\" view\n })\n\n const { data, isLoading, error } = useQuery({\n queryKey: ['workflow-tasks', 'list', filterValues, page],\n queryFn: async () => {\n const params = new URLSearchParams()\n const offset = (page - 1) * pageSize\n params.set('limit', pageSize.toString())\n params.set('offset', offset.toString())\n\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.overdue === 'true') params.set('overdue', 'true')\n if (filterValues.workflowInstanceId) params.set('workflowInstanceId', filterValues.workflowInstanceId as string)\n\n const result = await apiCall<TasksResponse>(\n `/api/workflows/tasks?${params.toString()}`\n )\n\n if (!result.ok) {\n throw new Error('Failed to fetch user tasks')\n }\n\n const response = result.result\n if (response?.pagination) {\n setTotal(response.pagination.total || 0)\n const calculatedPages = Math.ceil((response.pagination.total || 0) / pageSize)\n setTotalPages(calculatedPages || 1)\n setTotalIsCapped(response.pagination?.totalIsCapped === true)\n }\n\n return response?.data || []\n },\n })\n\n const handleClaim = async (id: string, taskName: string) => {\n const confirmed = await confirmDialog({\n title: t('workflows.tasks.confirm.claim', { name: taskName }),\n variant: 'default',\n })\n if (!confirmed) {\n return\n }\n\n const result = await apiCall(`/api/workflows/tasks/${id}/claim`, {\n method: 'POST',\n })\n\n if (result.ok) {\n flash(t('workflows.tasks.messages.claimed'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-tasks'] })\n } else {\n flash(t('workflows.tasks.messages.claimFailed'), 'error')\n }\n }\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({ myTasks: 'true' })\n setPage(1)\n }, [])\n\n const getStatusBadgeClass = (status: UserTaskStatus) => {\n switch (status) {\n case 'PENDING':\n return 'bg-status-warning-bg text-status-warning-text'\n case 'IN_PROGRESS':\n return 'bg-status-info-bg text-status-info-text'\n case 'COMPLETED':\n return 'bg-status-success-bg text-status-success-text'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const isOverdue = (task: UserTask) => {\n if (!task.dueDate || task.status === 'COMPLETED' || task.status === 'CANCELLED') {\n return false\n }\n return new Date(task.dueDate) < new Date()\n }\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('workflows.tasks.filters.status'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.tasks.statuses.PENDING'), value: 'PENDING' },\n { label: t('workflows.tasks.statuses.IN_PROGRESS'), value: 'IN_PROGRESS' },\n { label: t('workflows.tasks.statuses.COMPLETED'), value: 'COMPLETED' },\n { label: t('workflows.tasks.statuses.CANCELLED'), value: 'CANCELLED' },\n ],\n },\n {\n id: 'myTasks',\n type: 'select',\n label: t('workflows.tasks.filters.view'),\n options: [\n { label: t('workflows.tasks.filters.myTasks'), value: 'true' },\n { label: t('workflows.tasks.filters.allTasks'), value: '' },\n ],\n },\n {\n id: 'overdue',\n type: 'select',\n label: t('workflows.tasks.filters.overdue'),\n options: [\n { label: t('common.all'), value: '' },\n { label: t('workflows.tasks.filters.overdueOnly'), value: 'true' },\n ],\n },\n {\n id: 'workflowInstanceId',\n type: 'text',\n label: t('workflows.tasks.filters.workflowInstanceId'),\n placeholder: t('workflows.tasks.filters.workflowInstanceIdPlaceholder'),\n },\n ]\n\n const columns: ColumnDef<UserTask>[] = [\n {\n id: 'taskName',\n header: t('workflows.tasks.fields.taskName'),\n accessorKey: 'taskName',\n cell: ({ row }) => (\n <div>\n <div className=\"font-medium text-sm\">{row.original.taskName}</div>\n {row.original.description && (\n <div className=\"text-xs text-muted-foreground line-clamp-1\">\n {row.original.description}\n </div>\n )}\n {isOverdue(row.original) && (\n <div className=\"text-xs text-status-error-text font-medium mt-1\">\n {t('workflows.tasks.overdue')}\n </div>\n )}\n </div>\n ),\n },\n {\n id: 'status',\n header: t('workflows.tasks.fields.status'),\n accessorKey: 'status',\n cell: ({ row }) => (\n <span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>\n {t(`workflows.tasks.statuses.${row.original.status}`)}\n </span>\n ),\n },\n {\n id: 'assignment',\n header: t('workflows.tasks.fields.assignment'),\n cell: ({ row }) => {\n if (row.original.claimedBy) {\n return (\n <div className=\"text-sm\">\n <div className=\"text-foreground\">{t('workflows.tasks.claimedBy')}: {row.original.claimedBy}</div>\n </div>\n )\n }\n if (row.original.assignedTo) {\n return <div className=\"text-sm text-foreground\">{row.original.assignedTo}</div>\n }\n if (row.original.assignedToRoles && row.original.assignedToRoles.length > 0) {\n return (\n <div className=\"text-sm text-muted-foreground\">\n {t('workflows.tasks.roles')}: {row.original.assignedToRoles.join(', ')}\n </div>\n )\n }\n return <span className=\"text-sm text-muted-foreground\">-</span>\n },\n },\n {\n id: 'dueDate',\n header: t('workflows.tasks.fields.dueDate'),\n accessorKey: 'dueDate',\n cell: ({ row }) => {\n if (!row.original.dueDate) {\n return <span className=\"text-sm text-muted-foreground\">-</span>\n }\n const dueDate = new Date(row.original.dueDate)\n const overdue = isOverdue(row.original)\n return (\n <div className={`text-sm ${overdue ? 'text-status-error-text font-medium' : 'text-foreground'}`}>\n {dueDate.toLocaleString()}\n </div>\n )\n },\n },\n {\n id: 'createdAt',\n header: t('workflows.tasks.fields.createdAt'),\n accessorKey: 'createdAt',\n cell: ({ row }) => (\n <span className=\"text-sm text-muted-foreground\">\n {new Date(row.original.createdAt).toLocaleString()}\n </span>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }) => {\n const items: Array<{ id: string; label: string; href?: string; onSelect?: () => void }> = [\n {\n id: 'view',\n label: t('workflows.tasks.actions.viewDetails'),\n href: `/backend/tasks/${row.original.id}`,\n },\n ]\n\n // Allow claiming if task is PENDING and assigned to roles (not specific user)\n if (\n row.original.status === 'PENDING' &&\n !row.original.assignedTo &&\n row.original.assignedToRoles &&\n row.original.assignedToRoles.length > 0\n ) {\n items.push({\n id: 'claim',\n label: t('workflows.tasks.actions.claim'),\n onSelect: () => void handleClaim(row.original.id, row.original.taskName),\n })\n }\n\n // Allow completing if task is in progress or pending\n if (row.original.status === 'PENDING' || row.original.status === 'IN_PROGRESS') {\n items.push({\n id: 'complete',\n label: t('workflows.tasks.actions.complete'),\n href: `/backend/tasks/${row.original.id}`,\n })\n }\n\n return <RowActions items={items} />\n },\n },\n ]\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <div className=\"p-8 text-center\">\n <p className=\"text-status-error-text\">{t('workflows.tasks.messages.loadFailed')}</p>\n <Button onClick={() => queryClient.invalidateQueries({ queryKey: ['workflow-tasks'] })} className=\"mt-4\">\n {t('common.retry')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('workflows.tasks.list.title')}\n columns={columns}\n data={data || []}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n perspective={{\n tableId: extensionPoints.hosts.tasksTable.tableId,\n }}\n pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -252,16 +252,16 @@
|
|
|
252
252
|
"zod": "^4.4.3"
|
|
253
253
|
},
|
|
254
254
|
"peerDependencies": {
|
|
255
|
-
"@open-mercato/ai-assistant": "0.6.8-develop.
|
|
256
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
257
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
255
|
+
"@open-mercato/ai-assistant": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
256
|
+
"@open-mercato/shared": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
257
|
+
"@open-mercato/ui": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
258
258
|
"react": "^19.0.0",
|
|
259
259
|
"react-dom": "^19.0.0"
|
|
260
260
|
},
|
|
261
261
|
"devDependencies": {
|
|
262
|
-
"@open-mercato/ai-assistant": "0.6.8-develop.
|
|
263
|
-
"@open-mercato/shared": "0.6.8-develop.
|
|
264
|
-
"@open-mercato/ui": "0.6.8-develop.
|
|
262
|
+
"@open-mercato/ai-assistant": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
263
|
+
"@open-mercato/shared": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
264
|
+
"@open-mercato/ui": "0.6.8-develop.7032.1.70d74d4bfe",
|
|
265
265
|
"@testing-library/dom": "^10.4.1",
|
|
266
266
|
"@testing-library/jest-dom": "^7.0.0",
|
|
267
267
|
"@testing-library/react": "^16.3.1",
|
|
@@ -36,6 +36,7 @@ type ResponsePayload = {
|
|
|
36
36
|
total: number
|
|
37
37
|
page: number
|
|
38
38
|
totalPages: number
|
|
39
|
+
totalIsCapped?: boolean
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
function formatDate(value: string | null, t: (key: string, params?: Record<string, string | number>) => string) {
|
|
@@ -54,6 +55,7 @@ export default function ApiKeysListPage() {
|
|
|
54
55
|
const [page, setPage] = React.useState(1)
|
|
55
56
|
const [total, setTotal] = React.useState(0)
|
|
56
57
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
58
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
57
59
|
const [search, setSearch] = React.useState('')
|
|
58
60
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
59
61
|
const [reloadToken, setReloadToken] = React.useState(0)
|
|
@@ -87,6 +89,7 @@ export default function ApiKeysListPage() {
|
|
|
87
89
|
setRows(Array.isArray(payload.items) ? payload.items : [])
|
|
88
90
|
setTotal(payload.total || 0)
|
|
89
91
|
setTotalPages(payload.totalPages || 1)
|
|
92
|
+
setTotalIsCapped(payload?.totalIsCapped === true)
|
|
90
93
|
}
|
|
91
94
|
} catch (error) {
|
|
92
95
|
if (!cancelled) {
|
|
@@ -198,7 +201,7 @@ export default function ApiKeysListPage() {
|
|
|
198
201
|
createLabel={t('api_keys.list.actions.create')}
|
|
199
202
|
/>
|
|
200
203
|
)}
|
|
201
|
-
pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}
|
|
204
|
+
pagination={{ page, pageSize: 20, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
202
205
|
isLoading={isLoading}
|
|
203
206
|
/>
|
|
204
207
|
</PageBody>
|
|
@@ -42,6 +42,7 @@ type AttachmentLibraryResponse = {
|
|
|
42
42
|
pageSize: number
|
|
43
43
|
total: number
|
|
44
44
|
totalPages: number
|
|
45
|
+
totalIsCapped?: boolean
|
|
45
46
|
availableTags: string[]
|
|
46
47
|
partitions: Array<{ code: string; title: string; description?: string | null; isPublic?: boolean }>
|
|
47
48
|
error?: string
|
|
@@ -1054,6 +1055,7 @@ export function AttachmentLibrary() {
|
|
|
1054
1055
|
|
|
1055
1056
|
const total = data?.total ?? 0
|
|
1056
1057
|
const totalPages = data?.totalPages ?? 0
|
|
1058
|
+
const totalIsCapped = data?.totalIsCapped === true
|
|
1057
1059
|
return (
|
|
1058
1060
|
<>
|
|
1059
1061
|
<DataTable<AttachmentRow>
|
|
@@ -1154,6 +1156,7 @@ export function AttachmentLibrary() {
|
|
|
1154
1156
|
pageSize: PAGE_SIZE,
|
|
1155
1157
|
total,
|
|
1156
1158
|
totalPages,
|
|
1159
|
+
totalIsCapped,
|
|
1157
1160
|
onPageChange: (next) => setPage(next),
|
|
1158
1161
|
}}
|
|
1159
1162
|
/>
|
|
@@ -21,6 +21,7 @@ type ActionLogResponse = {
|
|
|
21
21
|
pageSize: number
|
|
22
22
|
total: number
|
|
23
23
|
totalPages: number
|
|
24
|
+
totalIsCapped?: boolean
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
type AccessLogResponse = {
|
|
@@ -30,6 +31,7 @@ type AccessLogResponse = {
|
|
|
30
31
|
pageSize: number
|
|
31
32
|
total: number
|
|
32
33
|
totalPages: number
|
|
34
|
+
totalIsCapped?: boolean
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
type TabOption = 'actions' | 'access'
|
|
@@ -48,11 +50,13 @@ export default function AuditLogsPage() {
|
|
|
48
50
|
const [actionsPageSize, setActionsPageSize] = React.useState(DEFAULT_PAGE_SIZE)
|
|
49
51
|
const [actionsTotal, setActionsTotal] = React.useState(0)
|
|
50
52
|
const [actionsTotalPages, setActionsTotalPages] = React.useState(1)
|
|
53
|
+
const [actionsTotalIsCapped, setActionsTotalIsCapped] = React.useState(false)
|
|
51
54
|
const actionsPageSizeRef = React.useRef(DEFAULT_PAGE_SIZE)
|
|
52
55
|
const [accessPage, setAccessPage] = React.useState(1)
|
|
53
56
|
const [accessPageSize, setAccessPageSize] = React.useState(DEFAULT_PAGE_SIZE)
|
|
54
57
|
const [accessTotal, setAccessTotal] = React.useState(0)
|
|
55
58
|
const [accessTotalPages, setAccessTotalPages] = React.useState(1)
|
|
59
|
+
const [accessTotalIsCapped, setAccessTotalIsCapped] = React.useState(false)
|
|
56
60
|
const accessPageSizeRef = React.useRef(DEFAULT_PAGE_SIZE)
|
|
57
61
|
|
|
58
62
|
const fetchActions = React.useCallback(async (page: number, pageSize: number) => {
|
|
@@ -95,6 +99,7 @@ export default function AuditLogsPage() {
|
|
|
95
99
|
})
|
|
96
100
|
setActionsTotal(actionsRes.total ?? (actionsRes.items?.length ?? 0))
|
|
97
101
|
setActionsTotalPages(actionsRes.totalPages ?? 1)
|
|
102
|
+
setActionsTotalIsCapped(actionsRes.totalIsCapped === true)
|
|
98
103
|
setAccessLogs(accessRes.items ?? [])
|
|
99
104
|
const resolvedPage = accessRes.page ?? accessPageNum
|
|
100
105
|
const resolvedPageSize = accessRes.pageSize ?? accessPageSizeNum
|
|
@@ -111,6 +116,7 @@ export default function AuditLogsPage() {
|
|
|
111
116
|
})
|
|
112
117
|
setAccessTotal(resolvedTotal)
|
|
113
118
|
setAccessTotalPages(resolvedTotalPages)
|
|
119
|
+
setAccessTotalIsCapped(accessRes.totalIsCapped === true)
|
|
114
120
|
}, [fetchActions, fetchAccess])
|
|
115
121
|
|
|
116
122
|
const loadWithState = React.useCallback(async (
|
|
@@ -210,6 +216,7 @@ export default function AuditLogsPage() {
|
|
|
210
216
|
pageSize: actionsPageSize,
|
|
211
217
|
total: actionsTotal,
|
|
212
218
|
totalPages: actionsTotalPages,
|
|
219
|
+
totalIsCapped: actionsTotalIsCapped,
|
|
213
220
|
onPageChange: handleActionsPageChange,
|
|
214
221
|
}}
|
|
215
222
|
/>
|
|
@@ -225,6 +232,7 @@ export default function AuditLogsPage() {
|
|
|
225
232
|
pageSize: accessPageSize,
|
|
226
233
|
total: accessTotal,
|
|
227
234
|
totalPages: accessTotalPages,
|
|
235
|
+
totalIsCapped: accessTotalIsCapped,
|
|
228
236
|
onPageChange: handleAccessPageChange,
|
|
229
237
|
}}
|
|
230
238
|
/>
|
|
@@ -33,6 +33,7 @@ export default function RolesListPage() {
|
|
|
33
33
|
const [page, setPage] = React.useState(1)
|
|
34
34
|
const [total, setTotal] = React.useState(0)
|
|
35
35
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
36
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
36
37
|
const [search, setSearch] = React.useState('')
|
|
37
38
|
const [rows, setRows] = React.useState<Row[]>([])
|
|
38
39
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -55,7 +56,7 @@ export default function RolesListPage() {
|
|
|
55
56
|
items?: Row[]
|
|
56
57
|
total?: number
|
|
57
58
|
totalPages?: number
|
|
58
|
-
isSuperAdmin?: boolean
|
|
59
|
+
isSuperAdmin?: boolean; totalIsCapped?: boolean
|
|
59
60
|
}>(
|
|
60
61
|
`/api/auth/roles?${params.toString()}`,
|
|
61
62
|
undefined,
|
|
@@ -65,6 +66,7 @@ export default function RolesListPage() {
|
|
|
65
66
|
setRows(j.items || [])
|
|
66
67
|
setTotal(j.total || 0)
|
|
67
68
|
setTotalPages(j.totalPages || 1)
|
|
69
|
+
setTotalIsCapped(j?.totalIsCapped === true)
|
|
68
70
|
setIsSuperAdmin(!!j.isSuperAdmin)
|
|
69
71
|
}
|
|
70
72
|
} finally {
|
|
@@ -156,7 +158,7 @@ export default function RolesListPage() {
|
|
|
156
158
|
createLabel={t('auth.roles.list.actions.create', 'Create')}
|
|
157
159
|
/>
|
|
158
160
|
)}
|
|
159
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
161
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
160
162
|
isLoading={isLoading}
|
|
161
163
|
/>
|
|
162
164
|
</PageBody>
|
|
@@ -351,7 +351,7 @@ export default function UsersListPage() {
|
|
|
351
351
|
const { data: usersData, isLoading } = useQuery({
|
|
352
352
|
queryKey: ['users', params, scopeVersion],
|
|
353
353
|
queryFn: async () => {
|
|
354
|
-
const call = await apiCall<{ items: Row[]; total: number; totalPages: number; isSuperAdmin?: boolean }>(
|
|
354
|
+
const call = await apiCall<{ items: Row[]; total: number; totalPages: number; totalIsCapped?: boolean; isSuperAdmin?: boolean }>(
|
|
355
355
|
`/api/auth/users?${params}`,
|
|
356
356
|
)
|
|
357
357
|
if (!call.ok) {
|
|
@@ -364,6 +364,7 @@ export default function UsersListPage() {
|
|
|
364
364
|
const rows = usersData?.items || []
|
|
365
365
|
const total = usersData?.total || 0
|
|
366
366
|
const totalPages = usersData?.totalPages || 1
|
|
367
|
+
const totalIsCapped = usersData?.totalIsCapped === true
|
|
367
368
|
const isSuperAdmin = !!usersData?.isSuperAdmin
|
|
368
369
|
const rowsWithOrgNames: Row[] = React.useMemo(() => rows.map(row => ({
|
|
369
370
|
...row,
|
|
@@ -456,7 +457,7 @@ export default function UsersListPage() {
|
|
|
456
457
|
{ id: 'delete', label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },
|
|
457
458
|
]} />
|
|
458
459
|
)}
|
|
459
|
-
pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}
|
|
460
|
+
pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
460
461
|
isLoading={isLoading}
|
|
461
462
|
/>
|
|
462
463
|
</PageBody>
|
|
@@ -38,6 +38,7 @@ type LogsResponse = {
|
|
|
38
38
|
items: RuleExecutionLog[]
|
|
39
39
|
total: number
|
|
40
40
|
totalPages: number
|
|
41
|
+
totalIsCapped?: boolean
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export default function ExecutionLogsPage() {
|
|
@@ -45,6 +46,7 @@ export default function ExecutionLogsPage() {
|
|
|
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 t = useT()
|
|
49
51
|
const [filterValues, setFilterValues] = React.useState<FilterValues>({})
|
|
50
52
|
|
|
@@ -76,6 +78,7 @@ export default function ExecutionLogsPage() {
|
|
|
76
78
|
if (response) {
|
|
77
79
|
setTotal(response.total || 0)
|
|
78
80
|
setTotalPages(response.totalPages || 1)
|
|
81
|
+
setTotalIsCapped(response?.totalIsCapped === true)
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
return response?.items || []
|
|
@@ -246,7 +249,7 @@ export default function ExecutionLogsPage() {
|
|
|
246
249
|
onFiltersClear={handleFiltersClear}
|
|
247
250
|
isLoading={isLoading}
|
|
248
251
|
error={error ? t('business_rules.logs.messages.loadFailed') : undefined}
|
|
249
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
252
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
250
253
|
/>
|
|
251
254
|
</PageBody>
|
|
252
255
|
</Page>
|
|
@@ -42,6 +42,7 @@ type RulesResponse = {
|
|
|
42
42
|
items: Rule[]
|
|
43
43
|
total: number
|
|
44
44
|
totalPages: number
|
|
45
|
+
totalIsCapped?: boolean
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
export default function RulesListPage() {
|
|
@@ -49,6 +50,7 @@ export default function RulesListPage() {
|
|
|
49
50
|
const [pageSize] = React.useState(20)
|
|
50
51
|
const [total, setTotal] = React.useState(0)
|
|
51
52
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
53
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
52
54
|
const t = useT()
|
|
53
55
|
const router = useRouter()
|
|
54
56
|
const queryClient = useQueryClient()
|
|
@@ -82,6 +84,7 @@ export default function RulesListPage() {
|
|
|
82
84
|
if (response) {
|
|
83
85
|
setTotal(response.total || 0)
|
|
84
86
|
setTotalPages(response.totalPages || 1)
|
|
87
|
+
setTotalIsCapped(response?.totalIsCapped === true)
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
return response?.items || []
|
|
@@ -352,7 +355,7 @@ export default function RulesListPage() {
|
|
|
352
355
|
createLabel={t('business_rules.actions.create')}
|
|
353
356
|
/>
|
|
354
357
|
)}
|
|
355
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
358
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
356
359
|
/>
|
|
357
360
|
</PageBody>
|
|
358
361
|
{ConfirmDialogElement}
|
|
@@ -35,6 +35,7 @@ type RuleSetsResponse = {
|
|
|
35
35
|
items: RuleSet[]
|
|
36
36
|
total: number
|
|
37
37
|
totalPages: number
|
|
38
|
+
totalIsCapped?: boolean
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export default function RuleSetsListPage() {
|
|
@@ -42,6 +43,7 @@ export default function RuleSetsListPage() {
|
|
|
42
43
|
const [pageSize] = React.useState(20)
|
|
43
44
|
const [total, setTotal] = React.useState(0)
|
|
44
45
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
46
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
45
47
|
const t = useT()
|
|
46
48
|
const router = useRouter()
|
|
47
49
|
const queryClient = useQueryClient()
|
|
@@ -72,6 +74,7 @@ export default function RuleSetsListPage() {
|
|
|
72
74
|
if (response) {
|
|
73
75
|
setTotal(response.total || 0)
|
|
74
76
|
setTotalPages(response.totalPages || 1)
|
|
77
|
+
setTotalIsCapped(response?.totalIsCapped === true)
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
return response?.items || []
|
|
@@ -258,7 +261,7 @@ export default function RuleSetsListPage() {
|
|
|
258
261
|
createLabel={t('business_rules.sets.actions.create')}
|
|
259
262
|
/>
|
|
260
263
|
)}
|
|
261
|
-
pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
|
|
264
|
+
pagination={{ page, pageSize, total, totalPages, totalIsCapped, onPageChange: setPage }}
|
|
262
265
|
/>
|
|
263
266
|
</PageBody>
|
|
264
267
|
{ConfirmDialogElement}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComparisonOperator, LogicalOperator } from '../data/validators'
|
|
2
2
|
import { testLinearRegex } from '@open-mercato/shared/lib/regex/linear'
|
|
3
3
|
import { getNestedValue, resolveSpecialValue } from './value-resolver'
|
|
4
|
-
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
4
|
+
import { createLogger, isLevelEnabled } from '@open-mercato/shared/lib/logger'
|
|
5
5
|
|
|
6
6
|
const logger = createLogger('business_rules').child({ component: 'expression-evaluator' })
|
|
7
7
|
|
|
@@ -86,14 +86,14 @@ function evaluateSimpleCondition(
|
|
|
86
86
|
|
|
87
87
|
const result = applyOperator(leftValue, condition.operator, rightValue)
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
89
|
+
if (isLevelEnabled('debug')) {
|
|
90
|
+
logger.debug('Simple condition evaluated', {
|
|
91
|
+
field: condition.field,
|
|
92
|
+
operator: condition.operator,
|
|
93
|
+
actualValueType: typeof leftValue,
|
|
94
|
+
passed: result,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
97
|
|
|
98
98
|
return result
|
|
99
99
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BusinessRule } from '../data/entities'
|
|
2
2
|
import { evaluateExpression, type EvaluationContext, type ConditionExpression } from './expression-evaluator'
|
|
3
|
-
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
3
|
+
import { createLogger, isLevelEnabled } from '@open-mercato/shared/lib/logger'
|
|
4
4
|
|
|
5
5
|
const logger = createLogger('business_rules').child({ component: 'rule-evaluator' })
|
|
6
6
|
|
|
@@ -105,14 +105,15 @@ export async function evaluateSingleRule(
|
|
|
105
105
|
): Promise<SingleRuleResult> {
|
|
106
106
|
const startTime = Date.now()
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
if (isLevelEnabled('debug')) {
|
|
109
|
+
logger.debug('Evaluating rule', {
|
|
110
|
+
ruleId: rule.ruleId,
|
|
111
|
+
ruleName: rule.ruleName,
|
|
112
|
+
ruleType: rule.ruleType,
|
|
113
|
+
entityType: rule.entityType,
|
|
114
|
+
eventType: rule.eventType,
|
|
115
|
+
})
|
|
116
|
+
}
|
|
116
117
|
|
|
117
118
|
try {
|
|
118
119
|
// Check if rule is enabled
|
|
@@ -407,7 +407,7 @@ const MERCHANDISING_PROMPT_SECTIONS: PromptSection[] = [
|
|
|
407
407
|
'- Selection-first: if `pageContext.recordId` contains a non-empty comma-separated UUID list (or `pageContext.extra.selectedCount > 0`), the operator has selected rows in the grid and EXPECTS you to act on those first. Call catalog.list_selected_products with those IDs, present what you found, and THEN ask whether to expand to the full catalog or to a broader search. Do NOT silently fall back to catalog.search_products when a selection is present.',
|
|
408
408
|
'- "list products" with no selection → call catalog.search_products with NO parameters (returns all active products, paginated; default limit=50, max=100).',
|
|
409
409
|
'- User mentions a product name → call catalog.search_products with q=that name.',
|
|
410
|
-
'- If catalog.search_products
|
|
410
|
+
'- If catalog.search_products fills the page (as many items as `limit`), more may follow: say so and offer to fetch the next page; do NOT raise `limit` above 100. When `totalIsCapped` is true, `total` is a floor — phrase it as "at least N", never as an exact count.',
|
|
411
411
|
'Present results first, then offer refinement options. The user does NOT want to answer questions before seeing data.',
|
|
412
412
|
].join('\n'),
|
|
413
413
|
},
|