@open-mercato/core 0.6.4-develop.4236.1.9fa6806b34 → 0.6.4-develop.4254.1.7a123d970c
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/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/authFixtures.js +70 -1
- package/dist/helpers/integration/authFixtures.js.map +2 -2
- package/dist/helpers/integration/dbFixtures.js +98 -0
- package/dist/helpers/integration/dbFixtures.js.map +7 -0
- package/dist/modules/business_rules/api/execute/route.js +2 -1
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/api/rules/route.js +10 -0
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/backend/logs/[id]/page.js +24 -5
- package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +6 -0
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +116 -9
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/subscribers/crud-rule-trigger.js +3 -2
- package/dist/modules/business_rules/subscribers/crud-rule-trigger.js.map +2 -2
- package/dist/modules/catalog/api/offers/route.js +15 -5
- package/dist/modules/catalog/api/offers/route.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js +21 -4
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/lib/pricing.js +6 -0
- package/dist/modules/catalog/lib/pricing.js.map +2 -2
- package/dist/modules/catalog/services/catalogPricingService.js +5 -1
- package/dist/modules/catalog/services/catalogPricingService.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +15 -2
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/comments/route.js +15 -3
- package/dist/modules/customers/api/comments/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +2 -4
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +2 -4
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -4
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +2 -4
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +2 -9
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +2 -9
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +2 -8
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +2 -4
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +2 -4
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +2 -4
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/directory/utils/organizationScopeGuard.js +22 -0
- package/dist/modules/directory/utils/organizationScopeGuard.js.map +7 -0
- package/dist/modules/progress/acl.js +8 -4
- package/dist/modules/progress/acl.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +8 -0
- package/dist/modules/workflows/cli.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +8 -4
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/setup.js +3 -1
- package/dist/modules/workflows/setup.js.map +2 -2
- package/package.json +7 -7
- package/src/helpers/integration/authFixtures.ts +98 -0
- package/src/helpers/integration/dbFixtures.ts +144 -0
- package/src/modules/business_rules/api/execute/route.ts +2 -1
- package/src/modules/business_rules/api/rules/route.ts +10 -0
- package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
- package/src/modules/business_rules/cli.ts +6 -0
- package/src/modules/business_rules/lib/rule-engine.ts +163 -9
- package/src/modules/business_rules/subscribers/crud-rule-trigger.ts +3 -2
- package/src/modules/catalog/api/offers/route.ts +20 -5
- package/src/modules/catalog/api/products/route.ts +23 -4
- package/src/modules/catalog/lib/pricing.ts +9 -0
- package/src/modules/catalog/services/catalogPricingService.ts +6 -0
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
- package/src/modules/customers/api/activities/route.ts +16 -5
- package/src/modules/customers/api/comments/route.ts +15 -5
- package/src/modules/customers/api/companies/[id]/people/route.ts +2 -4
- package/src/modules/customers/api/companies/[id]/route.ts +2 -5
- package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -4
- package/src/modules/customers/api/deals/[id]/people/route.ts +2 -4
- package/src/modules/customers/api/deals/[id]/route.ts +2 -9
- package/src/modules/customers/api/deals/[id]/stats/route.ts +2 -9
- package/src/modules/customers/api/entity-roles-factory.ts +2 -12
- package/src/modules/customers/api/people/[id]/companies/context.ts +2 -5
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +2 -5
- package/src/modules/customers/api/people/[id]/route.ts +2 -5
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
- package/src/modules/directory/utils/organizationScopeGuard.ts +39 -0
- package/src/modules/progress/acl.ts +4 -0
- package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
- package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
- package/src/modules/workflows/cli.ts +8 -0
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
- package/src/modules/workflows/lib/seeds.ts +13 -3
- package/src/modules/workflows/setup.ts +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/workflows/backend/instances/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { WorkflowInstance, WorkflowEvent, WorkflowDefinition } from '../../../data/entities'\nimport { WorkflowGraphReadOnly } from '../../../components/WorkflowGraph'\nimport { WorkflowLegend } from '../../../components/WorkflowLegend'\nimport { MobileInstanceOverview } from '../../../components/mobile/MobileInstanceOverview'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { definitionToGraph } from '../../../lib/graph-utils'\nimport { Node } from '@xyflow/react'\n\nexport default function WorkflowInstanceDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const isMobile = useIsMobile()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n\n const { data: instance, isLoading, error } = useQuery({\n queryKey: ['workflow-instance', id],\n queryFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${id}`)\n if (!response.ok) {\n throw new Error(t('workflows.instances.notFound') || 'Instance not found')\n }\n const data = await response.json()\n return data.data as WorkflowInstance\n },\n enabled: !!id,\n })\n\n const { data: events = [], isLoading: eventsLoading } = useQuery({\n queryKey: ['workflow-events', instance?.id],\n queryFn: async () => {\n const response = await apiFetch(\n `/api/workflows/events?workflowInstanceId=${instance!.id}&sortField=occurredAt&sortDir=desc&pageSize=100`\n )\n if (!response.ok) {\n throw new Error('Failed to fetch events')\n }\n const data = await response.json()\n return (data.items || []) as WorkflowEvent[]\n },\n enabled: !!instance?.id,\n })\n\n const { data: workflowDefinition, isLoading: definitionLoading } = useQuery({\n queryKey: ['workflow-definition-for-instance', instance?.definitionId],\n queryFn: async () => {\n // Fetch definition by ID\n const response = await apiFetch(`/api/workflows/definitions/${instance!.definitionId}`)\n if (!response.ok) {\n console.error('Failed to fetch workflow definition:', response.statusText)\n return null\n }\n const result = await response.json()\n return result.data as WorkflowDefinition\n },\n enabled: !!instance?.definitionId,\n })\n\n const calculateDuration = (startedAt: string | Date, completedAt: string | Date | null | undefined) => {\n const start = typeof startedAt === 'string' ? new Date(startedAt).getTime() : startedAt.getTime()\n const end = completedAt ? (typeof completedAt === 'string' ? new Date(completedAt).getTime() : completedAt.getTime()) : Date.now()\n const duration = end - start\n\n if (duration < 1000) {\n return `${duration}ms`\n } else if (duration < 60000) {\n return `${Math.floor(duration / 1000)}s`\n } else if (duration < 3600000) {\n return `${Math.floor(duration / 60000)}m ${Math.floor((duration % 60000) / 1000)}s`\n } else {\n const hours = Math.floor(duration / 3600000)\n const minutes = Math.floor((duration % 3600000) / 60000)\n return `${hours}h ${minutes}m`\n }\n }\n\n const getStatusBadgeClass = (status: WorkflowInstance['status']) => {\n switch (status) {\n case 'RUNNING':\n return 'bg-blue-100 text-blue-800'\n case 'PAUSED':\n return 'bg-yellow-100 text-yellow-800'\n case 'WAITING_FOR_ACTIVITIES':\n return 'bg-cyan-100 text-cyan-800'\n case 'COMPLETED':\n return 'bg-green-100 text-green-800'\n case 'FAILED':\n return 'bg-red-100 text-red-800'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n case 'COMPENSATING':\n return 'bg-orange-100 text-orange-800'\n case 'COMPENSATED':\n return 'bg-purple-100 text-purple-800'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const getEventTypeBadgeClass = (eventType: string) => {\n if (eventType.includes('COMPENSATION') || eventType.includes('Compensation')) {\n return 'bg-orange-100 text-orange-800'\n } else if (eventType.includes('STARTED') || eventType.includes('ENTERED')) {\n return 'bg-blue-100 text-blue-800'\n } else if (eventType.includes('COMPLETED') || eventType.includes('EXITED')) {\n return 'bg-green-100 text-green-800'\n } else if (eventType.includes('FAILED') || eventType.includes('REJECTED')) {\n return 'bg-red-100 text-red-800'\n } else if (eventType.includes('CANCELLED')) {\n return 'bg-muted text-foreground'\n } else if (eventType.includes('PAUSED')) {\n return 'bg-yellow-100 text-yellow-800'\n } else {\n return 'bg-muted text-foreground'\n }\n }\n\n const cancelMutation = useMutation({\n mutationFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${instance!.id}/cancel`, {\n method: 'POST',\n })\n if (!response.ok) {\n throw new Error(t('workflows.instances.cancelFailed'))\n }\n return response.json()\n },\n onSuccess: () => {\n flash(t('workflows.instances.messages.cancelled'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instance', id] })\n },\n onError: (error) => {\n console.error('Error cancelling instance:', error)\n flash(t('workflows.instances.cancelFailed'), 'error')\n },\n })\n\n const retryMutation = useMutation({\n mutationFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${instance!.id}/retry`, {\n method: 'POST',\n })\n if (!response.ok) {\n throw new Error(t('workflows.instances.retryFailed'))\n }\n return response.json()\n },\n onSuccess: () => {\n flash(t('workflows.instances.messages.retried'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instance', id] })\n },\n onError: (error) => {\n console.error('Error retrying instance:', error)\n flash(t('workflows.instances.retryFailed'), 'error')\n },\n })\n\n const handleCancel = async () => {\n if (!instance) return\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirmCancel'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n cancelMutation.mutate()\n }\n\n const handleRetry = async () => {\n if (!instance) return\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirmRetry'),\n variant: 'default',\n })\n if (!confirmed) {\n return\n }\n retryMutation.mutate()\n }\n\n // Generate graph with execution status\n const { graphNodes, graphEdges } = React.useMemo(() => {\n if (!workflowDefinition?.definition) {\n return { graphNodes: [], graphEdges: [] }\n }\n\n // Convert definition to graph\n const { nodes, edges } = definitionToGraph(workflowDefinition.definition, { autoLayout: true })\n\n // Determine step statuses from events\n const stepStatuses = new Map<string, 'completed' | 'active' | 'pending' | 'failed' | 'skipped'>()\n const stepTimings = new Map<string, { startedAt?: Date; completedAt?: Date }>()\n\n // Process events to determine status\n for (const event of events) {\n const stepId = event.eventData?.stepId || event.eventData?.toStepId\n if (!stepId) continue\n\n if (event.eventType === 'STEP_ENTERED' || event.eventType === 'StepEntered') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), startedAt: new Date(event.occurredAt) })\n if (!stepStatuses.has(stepId)) {\n stepStatuses.set(stepId, 'active')\n }\n } else if (event.eventType === 'STEP_COMPLETED' || event.eventType === 'STEP_EXITED' || event.eventType === 'StepExited') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), completedAt: new Date(event.occurredAt) })\n stepStatuses.set(stepId, 'completed')\n } else if (event.eventType === 'STEP_FAILED' || event.eventType === 'StepFailed') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), completedAt: new Date(event.occurredAt) })\n stepStatuses.set(stepId, 'failed')\n }\n }\n\n // Mark current step as active\n if (instance?.currentStepId && !stepStatuses.has(instance.currentStepId)) {\n stepStatuses.set(instance.currentStepId, 'active')\n } else if (instance?.currentStepId && stepStatuses.get(instance.currentStepId) !== 'completed') {\n stepStatuses.set(instance.currentStepId, 'active')\n }\n\n // Mark all other steps as pending, with special handling for START/END\n for (const node of nodes) {\n if (!stepStatuses.has(node.id)) {\n const nodeType = node.type\n const isCurrentStep = instance?.currentStepId === node.id\n\n if (nodeType === 'start') {\n // START node is completed if we've moved past it\n // It's active if we're still at start (edge case)\n if (isCurrentStep) {\n stepStatuses.set(node.id, 'active')\n } else {\n stepStatuses.set(node.id, 'completed')\n }\n } else if (nodeType === 'end') {\n // END node is completed if we've reached it\n // Or if workflow is in COMPLETED status\n if (isCurrentStep || instance?.status === 'COMPLETED') {\n stepStatuses.set(node.id, 'completed')\n } else {\n stepStatuses.set(node.id, 'pending')\n }\n } else {\n // All other nodes without events are pending\n stepStatuses.set(node.id, 'pending')\n }\n }\n }\n\n // Apply styles to nodes based on status\n const styledNodes: Node[] = nodes.map((node) => {\n const status = stepStatuses.get(node.id) || 'pending'\n const timing = stepTimings.get(node.id)\n\n // Calculate duration for tooltip\n const duration = timing?.startedAt && timing?.completedAt\n ? calculateDuration(timing.startedAt, timing.completedAt)\n : timing?.startedAt\n ? calculateDuration(timing.startedAt, null)\n : null\n\n // Build tooltip content\n let tooltipContent = `${node.data.label || node.id}\\n`\n tooltipContent += `Status: ${status}\\n`\n if (timing?.startedAt) {\n tooltipContent += `Started: ${timing.startedAt.toLocaleString()}\\n`\n }\n if (timing?.completedAt) {\n tooltipContent += `Completed: ${timing.completedAt.toLocaleString()}\\n`\n }\n if (duration) {\n tooltipContent += `Duration: ${duration}`\n }\n\n // Define colors and styles based on status\n let style: React.CSSProperties = {}\n switch (status) {\n case 'completed':\n style = {\n backgroundColor: '#10B981', // green-500\n color: 'white',\n borderColor: '#059669', // green-600\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'active':\n style = {\n backgroundColor: '#3B82F6', // blue-500\n color: 'white',\n borderColor: '#1D4ED8', // blue-700\n borderWidth: '3px',\n borderRadius: '16px',\n boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.3)',\n }\n break\n case 'failed':\n style = {\n backgroundColor: '#EF4444', // red-500\n color: 'white',\n borderColor: '#B91C1C', // red-700\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'skipped':\n style = {\n backgroundColor: '#FEF3C7', // yellow-100\n color: '#78350F', // yellow-900\n borderColor: '#F59E0B', // yellow-500\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'pending':\n default:\n style = {\n backgroundColor: '#E5E7EB', // gray-200\n color: '#374151', // gray-700\n borderColor: '#9CA3AF', // gray-400\n borderWidth: '2px',\n borderRadius: '8px',\n }\n break\n }\n\n return {\n ...node,\n data: {\n ...node.data,\n status,\n timing,\n duration,\n tooltip: tooltipContent,\n },\n style,\n }\n })\n\n return { graphNodes: styledNodes, graphEdges: edges }\n }, [workflowDefinition, events, instance?.currentStepId])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('workflows.instances.detail.loading') || 'Loading workflow instance...'}</span>\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n if (error || !instance) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <p>{error ? t('workflows.instances.loadFailed') : t('workflows.instances.detail.notFound') || 'Workflow instance not found.'}</p>\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/instances\">\n {t('workflows.instances.actions.backToList') || 'Back to instances'}\n </Link>\n </Button>\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n const canCancel = ['RUNNING', 'PAUSED'].includes(instance.status)\n const canRetry = instance.status === 'FAILED'\n const actionLoading = cancelMutation.isPending || retryMutation.isPending\n\n if (isMobile) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/instances\"\n backLabel={t('workflows.instances.backToList', 'Back to instances')}\n entityTypeLabel={t('workflows.instances.detail.type', 'Workflow instance')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{instance.workflowId}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{instance.id.slice(0, 8)}</span>\n </div>\n }\n menuActions={[\n ...(canCancel ? [{\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: handleCancel,\n disabled: actionLoading,\n }] : []),\n ...(canRetry ? [{\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: handleRetry,\n disabled: actionLoading,\n }] : []),\n ]}\n />\n <MobileInstanceOverview\n instance={instance}\n events={events}\n graphNodes={graphNodes}\n graphEdges={graphEdges}\n definitionLoading={definitionLoading}\n hasDefinition={!!workflowDefinition}\n getStatusBadgeClass={getStatusBadgeClass}\n getEventTypeBadgeClass={getEventTypeBadgeClass}\n calculateDuration={calculateDuration}\n />\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/instances\"\n backLabel={t('workflows.instances.backToList', 'Back to instances')}\n entityTypeLabel={t('workflows.instances.detail.type', 'Workflow instance')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{instance.workflowId}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{instance.id.slice(0, 8)}</span>\n </div>\n }\n menuActions={[\n ...(canCancel ? [{\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: handleCancel,\n disabled: actionLoading,\n }] : []),\n ...(canRetry ? [{\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: handleRetry,\n disabled: actionLoading,\n }] : []),\n ]}\n />\n\n {/* Execution Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.overview')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.workflowId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n <div className=\"font-mono\">{instance.workflowId}</div>\n <div className=\"text-xs text-muted-foreground\">v{instance.version}</div>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.status')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(\n instance.status\n )}`}\n >\n {t(`workflows.instances.status.${instance.status}`)}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.currentStep')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {instance.currentStepId || '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {instance.correlationKey || '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.startedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(instance.startedAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.completedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {instance.completedAt ? new Date(instance.completedAt).toLocaleString() : '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.duration')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {calculateDuration(instance.startedAt, instance.completedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.retryCount')}\n </dt>\n <dd className=\"mt-1\">\n <span className={instance.retryCount > 0 ? 'text-orange-600 font-medium text-sm' : 'text-sm text-foreground'}>\n {instance.retryCount}\n </span>\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Visual Workflow Graph */}\n {definitionLoading && (\n <div className=\"rounded-lg border bg-card p-6\">\n <div className=\"flex items-center justify-center py-8\">\n <Spinner className=\"h-6 w-6\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">Loading workflow visualization...</span>\n </div>\n </div>\n )}\n {!definitionLoading && workflowDefinition && graphNodes.length > 0 && (\n <div className=\"rounded-lg border bg-card p-4 md:p-6\">\n <h2 className=\"text-lg font-semibold text-foreground mb-4\">\n {t('workflows.instances.sections.visualFlow') || 'Visual Workflow Flow'}\n </h2>\n\n <div className=\"flex flex-col gap-4 lg:flex-row lg:gap-6\">\n {/* Left Sidebar - Legend */}\n <div className=\"order-2 lg:order-1 lg:w-64 lg:flex-shrink-0\">\n <WorkflowLegend />\n </div>\n\n {/* Main Visualization */}\n <div className=\"order-1 lg:order-2 flex-1 border rounded-lg overflow-hidden h-[62svh] min-h-[360px] lg:h-[800px]\">\n <WorkflowGraphReadOnly\n nodes={graphNodes}\n edges={graphEdges}\n height=\"100%\"\n />\n </div>\n </div>\n </div>\n )}\n {!definitionLoading && !workflowDefinition && instance && (\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.visualFlow') || 'Visual Workflow Flow'}\n </h2>\n <div className=\"flex items-center justify-center py-8 text-muted-foreground\">\n <p className=\"text-sm\">Workflow definition not found (ID: {instance.definitionId})</p>\n </div>\n </div>\n )}\n\n\n {/* Compensation Status */}\n {(instance.status === 'COMPENSATING' || instance.status === 'COMPENSATED') && (\n <div className=\"rounded-lg border border-orange-300 bg-orange-50 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-orange-800\">\n {t('workflows.instances.sections.compensation') || 'Compensation (Saga Pattern)'}\n </h2>\n <div className=\"space-y-4\">\n <p className=\"text-sm text-orange-700\">\n {instance.status === 'COMPENSATING'\n ? (t('workflows.instances.compensation.inProgress') || 'Workflow is currently executing compensation activities to rollback changes.')\n : (t('workflows.instances.compensation.completed') || 'Compensation has been completed. All changes have been rolled back.')}\n </p>\n\n {/* Show compensation activities from events */}\n {events.filter(e =>\n e.eventType.includes('COMPENSATION') ||\n e.eventType.includes('Compensation')\n ).length > 0 && (\n <div className=\"mt-4\">\n <h3 className=\"text-sm font-medium text-orange-800 mb-2\">\n {t('workflows.instances.compensation.activities') || 'Compensation Activities'}\n </h3>\n <div className=\"space-y-2\">\n {events\n .filter(e => e.eventType.includes('COMPENSATION') || e.eventType.includes('Compensation'))\n .reverse()\n .map((event) => (\n <div key={event.id} className=\"flex items-start gap-2 p-2 bg-card rounded border border-orange-200\">\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {event.eventType}\n </span>\n <span className=\"text-xs text-orange-600\">\n {new Date(event.occurredAt).toLocaleTimeString()}\n </span>\n {event.eventData?.activityName && (\n <span className=\"text-xs text-orange-700 font-medium\">\n {event.eventData.activityName}\n </span>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Error Message (if present) */}\n {instance.errorMessage && (\n <div className=\"rounded-lg border border-destructive bg-destructive/5 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-destructive\">\n {t('workflows.instances.fields.lastError')}\n </h2>\n <pre className=\"text-sm text-destructive whitespace-pre-wrap font-mono\">\n {instance.errorMessage}\n </pre>\n {instance.errorDetails && (\n <div className=\"mt-4\">\n <JsonDisplay\n data={instance.errorDetails}\n className=\"border-destructive/20 bg-destructive/5\"\n maxInitialDepth={1}\n />\n </div>\n )}\n </div>\n )}\n\n {/* Context */}\n <JsonDisplay\n data={instance.context}\n title={t('workflows.instances.sections.context')}\n />\n\n {/* Metadata */}\n {instance.metadata && Object.keys(instance.metadata).length > 0 && (\n <JsonDisplay\n data={instance.metadata}\n title={t('workflows.instances.sections.metadata')}\n />\n )}\n\n {/* Execution Timeline */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.executionTimeline') || 'Execution Timeline'}\n </h2>\n {eventsLoading ? (\n <div className=\"flex items-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span className=\"text-sm\">{t('common.loading')}</span>\n </div>\n ) : events.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('workflows.instances.noExecutionHistory')}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {events\n .filter(\n (e) =>\n e.eventType.includes('STEP_') ||\n e.eventType.includes('WORKFLOW_STARTED') ||\n e.eventType.includes('WORKFLOW_COMPLETED') ||\n e.eventType.includes('WORKFLOW_FAILED')\n )\n .reverse()\n .map((event, idx) => (\n <div key={event.id} className=\"flex items-start gap-3 p-3 bg-muted rounded-lg border\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full bg-background border-2 border-border flex items-center justify-center text-xs font-medium\">\n {idx + 1}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {t(`workflows.events.types.${event.eventType}`) || event.eventType}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {new Date(event.occurredAt).toLocaleTimeString()}\n </span>\n </div>\n {event.eventData && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {event.eventData.toStepId && `-> ${event.eventData.toStepId}`}\n {event.eventData.fromStepId && `${event.eventData.fromStepId} -> ${event.eventData.toStepId}`}\n </p>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Event Log */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.executionHistory')}\n </h2>\n {eventsLoading ? (\n <div className=\"flex items-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span className=\"text-sm\">{t('common.loading')}</span>\n </div>\n ) : events.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('workflows.instances.noExecutionHistory')}\n </p>\n ) : (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"min-w-full divide-y divide-border\">\n <thead className=\"bg-muted\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.occurredAt')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.eventType')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.eventData')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.userId')}\n </th>\n </tr>\n </thead>\n <tbody className=\"bg-background divide-y divide-border\">\n {events.map((event) => (\n <tr key={event.id} className=\"hover:bg-muted/50\">\n <td className=\"px-4 py-3 whitespace-nowrap text-sm text-foreground\">\n {new Date(event.occurredAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {t(`workflows.events.types.${event.eventType}`) || event.eventType}\n </span>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <details className=\"cursor-pointer\">\n <summary className=\"text-primary hover:underline\">\n {t('common.details')}\n </summary>\n <div className=\"mt-2\">\n <JsonDisplay\n data={event.eventData}\n showCopy={false}\n maxInitialDepth={1}\n />\n </div>\n </details>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-sm text-muted-foreground\">\n {event.userId || '-'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { WorkflowInstance, WorkflowEvent, WorkflowDefinition } from '../../../data/entities'\nimport { WorkflowGraphReadOnly } from '../../../components/WorkflowGraph'\nimport { WorkflowLegend } from '../../../components/WorkflowLegend'\nimport { MobileInstanceOverview } from '../../../components/mobile/MobileInstanceOverview'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { definitionToGraph } from '../../../lib/graph-utils'\nimport { Node } from '@xyflow/react'\nimport { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'\n\nexport default function WorkflowInstanceDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const isMobile = useIsMobile()\n const queryClient = useQueryClient()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n\n const { data: instance, isLoading, error } = useQuery({\n queryKey: ['workflow-instance', id],\n queryFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${id}`)\n if (!response.ok) {\n const httpErr = new Error(\n response.status === 404\n ? t('workflows.instances.detail.notFound', 'Workflow instance not found.')\n : t('workflows.instances.loadFailed', 'Failed to load workflow instance.')\n ) as Error & { status: number }\n httpErr.status = response.status\n throw httpErr\n }\n const data = await response.json()\n return data.data as WorkflowInstance\n },\n enabled: !!id,\n })\n\n const { data: events = [], isLoading: eventsLoading } = useQuery({\n queryKey: ['workflow-events', instance?.id],\n queryFn: async () => {\n const response = await apiFetch(\n `/api/workflows/events?workflowInstanceId=${instance!.id}&sortField=occurredAt&sortDir=desc&pageSize=100`\n )\n if (!response.ok) {\n throw new Error('Failed to fetch events')\n }\n const data = await response.json()\n return (data.items || []) as WorkflowEvent[]\n },\n enabled: !!instance?.id,\n })\n\n const { data: workflowDefinition, isLoading: definitionLoading } = useQuery({\n queryKey: ['workflow-definition-for-instance', instance?.definitionId],\n queryFn: async () => {\n // Fetch definition by ID\n const response = await apiFetch(`/api/workflows/definitions/${instance!.definitionId}`)\n if (!response.ok) {\n console.error('Failed to fetch workflow definition:', response.statusText)\n return null\n }\n const result = await response.json()\n return result.data as WorkflowDefinition\n },\n enabled: !!instance?.definitionId,\n })\n\n const calculateDuration = (startedAt: string | Date, completedAt: string | Date | null | undefined) => {\n const start = typeof startedAt === 'string' ? new Date(startedAt).getTime() : startedAt.getTime()\n const end = completedAt ? (typeof completedAt === 'string' ? new Date(completedAt).getTime() : completedAt.getTime()) : Date.now()\n const duration = end - start\n\n if (duration < 1000) {\n return `${duration}ms`\n } else if (duration < 60000) {\n return `${Math.floor(duration / 1000)}s`\n } else if (duration < 3600000) {\n return `${Math.floor(duration / 60000)}m ${Math.floor((duration % 60000) / 1000)}s`\n } else {\n const hours = Math.floor(duration / 3600000)\n const minutes = Math.floor((duration % 3600000) / 60000)\n return `${hours}h ${minutes}m`\n }\n }\n\n const getStatusBadgeClass = (status: WorkflowInstance['status']) => {\n switch (status) {\n case 'RUNNING':\n return 'bg-blue-100 text-blue-800'\n case 'PAUSED':\n return 'bg-yellow-100 text-yellow-800'\n case 'WAITING_FOR_ACTIVITIES':\n return 'bg-cyan-100 text-cyan-800'\n case 'COMPLETED':\n return 'bg-green-100 text-green-800'\n case 'FAILED':\n return 'bg-red-100 text-red-800'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n case 'COMPENSATING':\n return 'bg-orange-100 text-orange-800'\n case 'COMPENSATED':\n return 'bg-purple-100 text-purple-800'\n default:\n return 'bg-muted text-muted-foreground'\n }\n }\n\n const getEventTypeBadgeClass = (eventType: string) => {\n if (eventType.includes('COMPENSATION') || eventType.includes('Compensation')) {\n return 'bg-orange-100 text-orange-800'\n } else if (eventType.includes('STARTED') || eventType.includes('ENTERED')) {\n return 'bg-blue-100 text-blue-800'\n } else if (eventType.includes('COMPLETED') || eventType.includes('EXITED')) {\n return 'bg-green-100 text-green-800'\n } else if (eventType.includes('FAILED') || eventType.includes('REJECTED')) {\n return 'bg-red-100 text-red-800'\n } else if (eventType.includes('CANCELLED')) {\n return 'bg-muted text-foreground'\n } else if (eventType.includes('PAUSED')) {\n return 'bg-yellow-100 text-yellow-800'\n } else {\n return 'bg-muted text-foreground'\n }\n }\n\n const cancelMutation = useMutation({\n mutationFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${instance!.id}/cancel`, {\n method: 'POST',\n })\n if (!response.ok) {\n throw new Error(t('workflows.instances.cancelFailed'))\n }\n return response.json()\n },\n onSuccess: () => {\n flash(t('workflows.instances.messages.cancelled'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instance', id] })\n },\n onError: (error) => {\n console.error('Error cancelling instance:', error)\n flash(t('workflows.instances.cancelFailed'), 'error')\n },\n })\n\n const retryMutation = useMutation({\n mutationFn: async () => {\n const response = await apiFetch(`/api/workflows/instances/${instance!.id}/retry`, {\n method: 'POST',\n })\n if (!response.ok) {\n throw new Error(t('workflows.instances.retryFailed'))\n }\n return response.json()\n },\n onSuccess: () => {\n flash(t('workflows.instances.messages.retried'), 'success')\n queryClient.invalidateQueries({ queryKey: ['workflow-instance', id] })\n },\n onError: (error) => {\n console.error('Error retrying instance:', error)\n flash(t('workflows.instances.retryFailed'), 'error')\n },\n })\n\n const handleCancel = async () => {\n if (!instance) return\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirmCancel'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n cancelMutation.mutate()\n }\n\n const handleRetry = async () => {\n if (!instance) return\n const confirmed = await confirmDialog({\n title: t('workflows.instances.confirmRetry'),\n variant: 'default',\n })\n if (!confirmed) {\n return\n }\n retryMutation.mutate()\n }\n\n // Generate graph with execution status\n const { graphNodes, graphEdges } = React.useMemo(() => {\n if (!workflowDefinition?.definition) {\n return { graphNodes: [], graphEdges: [] }\n }\n\n // Convert definition to graph\n const { nodes, edges } = definitionToGraph(workflowDefinition.definition, { autoLayout: true })\n\n // Determine step statuses from events\n const stepStatuses = new Map<string, 'completed' | 'active' | 'pending' | 'failed' | 'skipped'>()\n const stepTimings = new Map<string, { startedAt?: Date; completedAt?: Date }>()\n\n // Process events to determine status\n for (const event of events) {\n const stepId = event.eventData?.stepId || event.eventData?.toStepId\n if (!stepId) continue\n\n if (event.eventType === 'STEP_ENTERED' || event.eventType === 'StepEntered') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), startedAt: new Date(event.occurredAt) })\n if (!stepStatuses.has(stepId)) {\n stepStatuses.set(stepId, 'active')\n }\n } else if (event.eventType === 'STEP_COMPLETED' || event.eventType === 'STEP_EXITED' || event.eventType === 'StepExited') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), completedAt: new Date(event.occurredAt) })\n stepStatuses.set(stepId, 'completed')\n } else if (event.eventType === 'STEP_FAILED' || event.eventType === 'StepFailed') {\n stepTimings.set(stepId, { ...stepTimings.get(stepId), completedAt: new Date(event.occurredAt) })\n stepStatuses.set(stepId, 'failed')\n }\n }\n\n // Mark current step as active\n if (instance?.currentStepId && !stepStatuses.has(instance.currentStepId)) {\n stepStatuses.set(instance.currentStepId, 'active')\n } else if (instance?.currentStepId && stepStatuses.get(instance.currentStepId) !== 'completed') {\n stepStatuses.set(instance.currentStepId, 'active')\n }\n\n // Mark all other steps as pending, with special handling for START/END\n for (const node of nodes) {\n if (!stepStatuses.has(node.id)) {\n const nodeType = node.type\n const isCurrentStep = instance?.currentStepId === node.id\n\n if (nodeType === 'start') {\n // START node is completed if we've moved past it\n // It's active if we're still at start (edge case)\n if (isCurrentStep) {\n stepStatuses.set(node.id, 'active')\n } else {\n stepStatuses.set(node.id, 'completed')\n }\n } else if (nodeType === 'end') {\n // END node is completed if we've reached it\n // Or if workflow is in COMPLETED status\n if (isCurrentStep || instance?.status === 'COMPLETED') {\n stepStatuses.set(node.id, 'completed')\n } else {\n stepStatuses.set(node.id, 'pending')\n }\n } else {\n // All other nodes without events are pending\n stepStatuses.set(node.id, 'pending')\n }\n }\n }\n\n // Apply styles to nodes based on status\n const styledNodes: Node[] = nodes.map((node) => {\n const status = stepStatuses.get(node.id) || 'pending'\n const timing = stepTimings.get(node.id)\n\n // Calculate duration for tooltip\n const duration = timing?.startedAt && timing?.completedAt\n ? calculateDuration(timing.startedAt, timing.completedAt)\n : timing?.startedAt\n ? calculateDuration(timing.startedAt, null)\n : null\n\n // Build tooltip content\n let tooltipContent = `${node.data.label || node.id}\\n`\n tooltipContent += `Status: ${status}\\n`\n if (timing?.startedAt) {\n tooltipContent += `Started: ${timing.startedAt.toLocaleString()}\\n`\n }\n if (timing?.completedAt) {\n tooltipContent += `Completed: ${timing.completedAt.toLocaleString()}\\n`\n }\n if (duration) {\n tooltipContent += `Duration: ${duration}`\n }\n\n // Define colors and styles based on status\n let style: React.CSSProperties = {}\n switch (status) {\n case 'completed':\n style = {\n backgroundColor: '#10B981', // green-500\n color: 'white',\n borderColor: '#059669', // green-600\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'active':\n style = {\n backgroundColor: '#3B82F6', // blue-500\n color: 'white',\n borderColor: '#1D4ED8', // blue-700\n borderWidth: '3px',\n borderRadius: '16px',\n boxShadow: '0 0 0 3px rgba(59, 130, 246, 0.3)',\n }\n break\n case 'failed':\n style = {\n backgroundColor: '#EF4444', // red-500\n color: 'white',\n borderColor: '#B91C1C', // red-700\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'skipped':\n style = {\n backgroundColor: '#FEF3C7', // yellow-100\n color: '#78350F', // yellow-900\n borderColor: '#F59E0B', // yellow-500\n borderWidth: '3px',\n borderRadius: '16px',\n }\n break\n case 'pending':\n default:\n style = {\n backgroundColor: '#E5E7EB', // gray-200\n color: '#374151', // gray-700\n borderColor: '#9CA3AF', // gray-400\n borderWidth: '2px',\n borderRadius: '8px',\n }\n break\n }\n\n return {\n ...node,\n data: {\n ...node.data,\n status,\n timing,\n duration,\n tooltip: tooltipContent,\n },\n style,\n }\n })\n\n return { graphNodes: styledNodes, graphEdges: edges }\n }, [workflowDefinition, events, instance?.currentStepId])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('workflows.instances.detail.loading') || 'Loading workflow instance...'}</span>\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n const isNotFound = !isLoading && (error as (Error & { status?: number }) | null)?.status === 404\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('workflows.instances.detail.notFound', 'Workflow instance not found.')}\n backHref=\"/backend/instances\"\n backLabel={t('workflows.instances.actions.backToList', 'Back to instances')}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n if (error || !instance) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={(error as Error | null)?.message ?? t('workflows.instances.loadFailed', 'Failed to load workflow instance.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/instances\">{t('workflows.instances.actions.backToList', 'Back to instances')}</Link>\n </Button>\n }\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n const canCancel = ['RUNNING', 'PAUSED'].includes(instance.status)\n const canRetry = instance.status === 'FAILED'\n const actionLoading = cancelMutation.isPending || retryMutation.isPending\n\n if (isMobile) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/instances\"\n backLabel={t('workflows.instances.backToList', 'Back to instances')}\n entityTypeLabel={t('workflows.instances.detail.type', 'Workflow instance')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{instance.workflowId}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{instance.id.slice(0, 8)}</span>\n </div>\n }\n menuActions={[\n ...(canCancel ? [{\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: handleCancel,\n disabled: actionLoading,\n }] : []),\n ...(canRetry ? [{\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: handleRetry,\n disabled: actionLoading,\n }] : []),\n ]}\n />\n <MobileInstanceOverview\n instance={instance}\n events={events}\n graphNodes={graphNodes}\n graphEdges={graphEdges}\n definitionLoading={definitionLoading}\n hasDefinition={!!workflowDefinition}\n getStatusBadgeClass={getStatusBadgeClass}\n getEventTypeBadgeClass={getEventTypeBadgeClass}\n calculateDuration={calculateDuration}\n />\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/instances\"\n backLabel={t('workflows.instances.backToList', 'Back to instances')}\n entityTypeLabel={t('workflows.instances.detail.type', 'Workflow instance')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{instance.workflowId}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{instance.id.slice(0, 8)}</span>\n </div>\n }\n menuActions={[\n ...(canCancel ? [{\n id: 'cancel',\n label: t('workflows.instances.actions.cancel'),\n onSelect: handleCancel,\n disabled: actionLoading,\n }] : []),\n ...(canRetry ? [{\n id: 'retry',\n label: t('workflows.instances.actions.retry'),\n onSelect: handleRetry,\n disabled: actionLoading,\n }] : []),\n ]}\n />\n\n {/* Execution Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.overview')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.workflowId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n <div className=\"font-mono\">{instance.workflowId}</div>\n <div className=\"text-xs text-muted-foreground\">v{instance.version}</div>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.status')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(\n instance.status\n )}`}\n >\n {t(`workflows.instances.status.${instance.status}`)}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.currentStep')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {instance.currentStepId || '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {instance.correlationKey || '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.startedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(instance.startedAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.completedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {instance.completedAt ? new Date(instance.completedAt).toLocaleString() : '-'}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.duration')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {calculateDuration(instance.startedAt, instance.completedAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.retryCount')}\n </dt>\n <dd className=\"mt-1\">\n <span className={instance.retryCount > 0 ? 'text-orange-600 font-medium text-sm' : 'text-sm text-foreground'}>\n {instance.retryCount}\n </span>\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Visual Workflow Graph */}\n {definitionLoading && (\n <div className=\"rounded-lg border bg-card p-6\">\n <div className=\"flex items-center justify-center py-8\">\n <Spinner className=\"h-6 w-6\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">Loading workflow visualization...</span>\n </div>\n </div>\n )}\n {!definitionLoading && workflowDefinition && graphNodes.length > 0 && (\n <div className=\"rounded-lg border bg-card p-4 md:p-6\">\n <h2 className=\"text-lg font-semibold text-foreground mb-4\">\n {t('workflows.instances.sections.visualFlow') || 'Visual Workflow Flow'}\n </h2>\n\n <div className=\"flex flex-col gap-4 lg:flex-row lg:gap-6\">\n {/* Left Sidebar - Legend */}\n <div className=\"order-2 lg:order-1 lg:w-64 lg:flex-shrink-0\">\n <WorkflowLegend />\n </div>\n\n {/* Main Visualization */}\n <div className=\"order-1 lg:order-2 flex-1 border rounded-lg overflow-hidden h-[62svh] min-h-[360px] lg:h-[800px]\">\n <WorkflowGraphReadOnly\n nodes={graphNodes}\n edges={graphEdges}\n height=\"100%\"\n />\n </div>\n </div>\n </div>\n )}\n {!definitionLoading && !workflowDefinition && instance && (\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.visualFlow') || 'Visual Workflow Flow'}\n </h2>\n <div className=\"flex items-center justify-center py-8 text-muted-foreground\">\n <p className=\"text-sm\">Workflow definition not found (ID: {instance.definitionId})</p>\n </div>\n </div>\n )}\n\n\n {/* Compensation Status */}\n {(instance.status === 'COMPENSATING' || instance.status === 'COMPENSATED') && (\n <div className=\"rounded-lg border border-orange-300 bg-orange-50 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-orange-800\">\n {t('workflows.instances.sections.compensation') || 'Compensation (Saga Pattern)'}\n </h2>\n <div className=\"space-y-4\">\n <p className=\"text-sm text-orange-700\">\n {instance.status === 'COMPENSATING'\n ? (t('workflows.instances.compensation.inProgress') || 'Workflow is currently executing compensation activities to rollback changes.')\n : (t('workflows.instances.compensation.completed') || 'Compensation has been completed. All changes have been rolled back.')}\n </p>\n\n {/* Show compensation activities from events */}\n {events.filter(e =>\n e.eventType.includes('COMPENSATION') ||\n e.eventType.includes('Compensation')\n ).length > 0 && (\n <div className=\"mt-4\">\n <h3 className=\"text-sm font-medium text-orange-800 mb-2\">\n {t('workflows.instances.compensation.activities') || 'Compensation Activities'}\n </h3>\n <div className=\"space-y-2\">\n {events\n .filter(e => e.eventType.includes('COMPENSATION') || e.eventType.includes('Compensation'))\n .reverse()\n .map((event) => (\n <div key={event.id} className=\"flex items-start gap-2 p-2 bg-card rounded border border-orange-200\">\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {event.eventType}\n </span>\n <span className=\"text-xs text-orange-600\">\n {new Date(event.occurredAt).toLocaleTimeString()}\n </span>\n {event.eventData?.activityName && (\n <span className=\"text-xs text-orange-700 font-medium\">\n {event.eventData.activityName}\n </span>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Error Message (if present) */}\n {instance.errorMessage && (\n <div className=\"rounded-lg border border-destructive bg-destructive/5 p-6\">\n <h2 className=\"text-lg font-semibold mb-4 text-destructive\">\n {t('workflows.instances.fields.lastError')}\n </h2>\n <pre className=\"text-sm text-destructive whitespace-pre-wrap font-mono\">\n {instance.errorMessage}\n </pre>\n {instance.errorDetails && (\n <div className=\"mt-4\">\n <JsonDisplay\n data={instance.errorDetails}\n className=\"border-destructive/20 bg-destructive/5\"\n maxInitialDepth={1}\n />\n </div>\n )}\n </div>\n )}\n\n {/* Context */}\n <JsonDisplay\n data={instance.context}\n title={t('workflows.instances.sections.context')}\n />\n\n {/* Metadata */}\n {instance.metadata && Object.keys(instance.metadata).length > 0 && (\n <JsonDisplay\n data={instance.metadata}\n title={t('workflows.instances.sections.metadata')}\n />\n )}\n\n {/* Execution Timeline */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.executionTimeline') || 'Execution Timeline'}\n </h2>\n {eventsLoading ? (\n <div className=\"flex items-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span className=\"text-sm\">{t('common.loading')}</span>\n </div>\n ) : events.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('workflows.instances.noExecutionHistory')}\n </p>\n ) : (\n <div className=\"space-y-2\">\n {events\n .filter(\n (e) =>\n e.eventType.includes('STEP_') ||\n e.eventType.includes('WORKFLOW_STARTED') ||\n e.eventType.includes('WORKFLOW_COMPLETED') ||\n e.eventType.includes('WORKFLOW_FAILED')\n )\n .reverse()\n .map((event, idx) => (\n <div key={event.id} className=\"flex items-start gap-3 p-3 bg-muted rounded-lg border\">\n <div className=\"flex-shrink-0 w-8 h-8 rounded-full bg-background border-2 border-border flex items-center justify-center text-xs font-medium\">\n {idx + 1}\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {t(`workflows.events.types.${event.eventType}`) || event.eventType}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {new Date(event.occurredAt).toLocaleTimeString()}\n </span>\n </div>\n {event.eventData && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {event.eventData.toStepId && `-> ${event.eventData.toStepId}`}\n {event.eventData.fromStepId && `${event.eventData.fromStepId} -> ${event.eventData.toStepId}`}\n </p>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Event Log */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.instances.sections.executionHistory')}\n </h2>\n {eventsLoading ? (\n <div className=\"flex items-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span className=\"text-sm\">{t('common.loading')}</span>\n </div>\n ) : events.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('workflows.instances.noExecutionHistory')}\n </p>\n ) : (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"min-w-full divide-y divide-border\">\n <thead className=\"bg-muted\">\n <tr>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.occurredAt')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.eventType')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.eventData')}\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('workflows.events.userId')}\n </th>\n </tr>\n </thead>\n <tbody className=\"bg-background divide-y divide-border\">\n {events.map((event) => (\n <tr key={event.id} className=\"hover:bg-muted/50\">\n <td className=\"px-4 py-3 whitespace-nowrap text-sm text-foreground\">\n {new Date(event.occurredAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {t(`workflows.events.types.${event.eventType}`) || event.eventType}\n </span>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <details className=\"cursor-pointer\">\n <summary className=\"text-primary hover:underline\">\n {t('common.details')}\n </summary>\n <div className=\"mt-2\">\n <JsonDisplay\n data={event.eventData}\n showCopy={false}\n maxInitialDepth={1}\n />\n </div>\n </details>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-sm text-muted-foreground\">\n {event.userId || '-'}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </div>\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["error"]
|
|
7
7
|
}
|
|
@@ -24,6 +24,7 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
24
24
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
25
25
|
import { MobileTaskForm } from "../../../components/mobile/MobileTaskForm.js";
|
|
26
26
|
import { useIsMobile } from "@open-mercato/ui/hooks/useIsMobile";
|
|
27
|
+
import { RecordNotFoundState, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
27
28
|
function UserTaskDetailPage({ params }) {
|
|
28
29
|
const router = useRouter();
|
|
29
30
|
const t = useT();
|
|
@@ -39,9 +40,13 @@ function UserTaskDetailPage({ params }) {
|
|
|
39
40
|
`/api/workflows/tasks/${params.id}`
|
|
40
41
|
);
|
|
41
42
|
if (!result.ok) {
|
|
42
|
-
|
|
43
|
+
const httpErr = new Error(
|
|
44
|
+
result.status === 404 ? t("workflows.tasks.detail.notFound", "Task not found") : t("workflows.tasks.detail.loadFailed", "Failed to load task")
|
|
45
|
+
);
|
|
46
|
+
httpErr.status = result.status;
|
|
47
|
+
throw httpErr;
|
|
43
48
|
}
|
|
44
|
-
return result.result?.data
|
|
49
|
+
return result.result?.data ?? null;
|
|
45
50
|
}
|
|
46
51
|
});
|
|
47
52
|
const handleFieldChange = (fieldName, value) => {
|
|
@@ -297,11 +302,25 @@ function UserTaskDetailPage({ params }) {
|
|
|
297
302
|
/* @__PURE__ */ jsx("span", { className: "ml-3 text-muted-foreground", children: t("workflows.tasks.detail.loading") })
|
|
298
303
|
] }) }) });
|
|
299
304
|
}
|
|
305
|
+
const isNotFound = !isLoading && error?.status === 404;
|
|
306
|
+
if (isNotFound) {
|
|
307
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
308
|
+
RecordNotFoundState,
|
|
309
|
+
{
|
|
310
|
+
label: t("workflows.tasks.detail.notFound", "Task not found"),
|
|
311
|
+
backHref: "/backend/tasks",
|
|
312
|
+
backLabel: t("workflows.tasks.detail.backToList", "Back to Tasks")
|
|
313
|
+
}
|
|
314
|
+
) }) });
|
|
315
|
+
}
|
|
300
316
|
if (error || !task) {
|
|
301
|
-
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
317
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
318
|
+
ErrorMessage,
|
|
319
|
+
{
|
|
320
|
+
label: error?.message ?? t("workflows.tasks.detail.loadFailed", "Failed to load task"),
|
|
321
|
+
action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/tasks", children: t("workflows.tasks.detail.backToList", "Back to Tasks") }) })
|
|
322
|
+
}
|
|
323
|
+
) }) });
|
|
305
324
|
}
|
|
306
325
|
const isCompletable = task.status === "PENDING" || task.status === "IN_PROGRESS";
|
|
307
326
|
const isOverdue = task.dueDate && new Date(task.dueDate) < /* @__PURE__ */ new Date() && isCompletable;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/workflows/backend/tasks/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { EmailInput } from '@open-mercato/ui/primitives/email-input'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { MobileTaskForm } from '../../../components/mobile/MobileTaskForm'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport type { UserTaskResponse, UserTaskStatus } from '../../../data/types'\n\nexport default function UserTaskDetailPage({ params }: { params: { id: string } }) {\n const router = useRouter()\n const t = useT()\n const isMobile = useIsMobile()\n const [formData, setFormData] = React.useState<Record<string, string | number | boolean>>({})\n const [comments, setComments] = React.useState('')\n const [submitting, setSubmitting] = React.useState(false)\n // Tracks the first required field that failed validation so we can mark the\n // field with aria-invalid + a red ring (Radix Select can't carry HTML\n // `required`, so we enforce constraint validation in JS instead).\n const [invalidField, setInvalidField] = React.useState<string | null>(null)\n\n const { data: task, isLoading, error } = useQuery({\n queryKey: ['workflow-task', params.id],\n queryFn: async () => {\n const result = await apiCall<{ data: UserTaskResponse }>(\n `/api/workflows/tasks/${params.id}`\n )\n\n if (!result.ok) {\n throw new Error('Failed to fetch task')\n }\n\n return result.result?.data || null\n },\n })\n\n const handleFieldChange = (fieldName: string, value: any) => {\n setFormData(prev => ({\n ...prev,\n [fieldName]: value,\n }))\n // Clear invalid state once the user touches the offending field.\n if (invalidField === fieldName) setInvalidField(null)\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!task) return\n\n // Validate required fields. Radix Select doesn't expose HTML `required`,\n // so we enforce constraint validation here and surface it visually via\n // `invalidField` + aria-invalid on the offending field.\n if (task.formSchema?.required) {\n for (const requiredField of task.formSchema.required) {\n if (!formData[requiredField] || formData[requiredField] === '') {\n const fieldSchema = task.formSchema.properties?.[requiredField]\n const fieldLabel = fieldSchema?.title ?? requiredField\n flash(t('workflows.tasks.detail.validation.requiredField', { field: fieldLabel }), 'error')\n setInvalidField(requiredField)\n // Scroll + focus the trigger so the user sees what's missing.\n if (typeof document !== 'undefined') {\n const trigger = document.getElementById(requiredField)\n trigger?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n trigger?.focus()\n }\n return\n }\n }\n }\n setInvalidField(null)\n\n setSubmitting(true)\n\n try {\n const result = await apiCall(`/api/workflows/tasks/${params.id}/complete`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n formData,\n comments: comments || undefined,\n }),\n })\n\n if (result.ok) {\n flash(t('workflows.tasks.messages.completed'), 'success')\n router.push('/backend/tasks')\n } else {\n const error = result.result as any\n flash(error?.error || t('workflows.tasks.messages.completeFailed'), 'error')\n }\n } catch (err) {\n console.error('Error completing task:', err)\n flash(t('workflows.tasks.messages.completeFailed'), 'error')\n } finally {\n setSubmitting(false)\n }\n }\n\n const fieldValue = (fieldName: string): string | number => {\n const val = formData[fieldName]\n if (val == null || val === false) return ''\n if (typeof val === 'boolean') return ''\n return val\n }\n\n const renderFormField = (fieldName: string, fieldSchema: any) => {\n const fieldType = fieldSchema.type || 'string'\n const fieldTitle = fieldSchema.title || fieldName\n const fieldDescription = fieldSchema.description\n const required = task?.formSchema?.required?.includes(fieldName) || false\n const enumValues = fieldSchema.enum\n\n const inputClasses = \"w-full px-3 py-2 border border-border rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n const labelClasses = \"block text-sm font-medium text-foreground mb-1\"\n\n // Handle enum (select dropdown)\n if (enumValues && Array.isArray(enumValues)) {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Select\n value={fieldValue(fieldName) ? String(fieldValue(fieldName)) : undefined}\n onValueChange={(value) => handleFieldChange(fieldName, value ?? '')}\n >\n <SelectTrigger\n id={fieldName}\n className={`${inputClasses} ${invalidField === fieldName ? 'ring-2 ring-status-error-border border-status-error-border' : ''}`}\n aria-required={required}\n aria-invalid={invalidField === fieldName ? true : undefined}\n >\n <SelectValue placeholder={t('workflows.tasks.detail.form.selectOption')} />\n </SelectTrigger>\n <SelectContent>\n {enumValues.map((value: any) => (\n <SelectItem key={value} value={value}>\n {value}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n // Handle different field types\n switch (fieldType) {\n case 'string':\n if (fieldSchema.format === 'email') {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <EmailInput\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n }\n if (fieldSchema.format === 'date') {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <input\n type=\"date\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n className={inputClasses}\n />\n </div>\n )\n }\n if (fieldSchema.maxLength && fieldSchema.maxLength > 200) {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <textarea\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n rows={4}\n className={inputClasses}\n />\n </div>\n )\n }\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"text\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n\n case 'number':\n case 'integer':\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"number\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value ? Number(e.target.value) : '')}\n required={required}\n step={fieldType === 'integer' ? 1 : 'any'}\n />\n </div>\n )\n\n case 'boolean':\n return (\n <div key={fieldName} className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={fieldName}\n checked={!!formData[fieldName]}\n onChange={(e) => handleFieldChange(fieldName, e.target.checked)}\n className=\"w-4 h-4 text-primary border-border rounded focus-visible:ring-ring\"\n />\n <label htmlFor={fieldName} className=\"text-sm font-medium text-foreground\">\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n </div>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground ml-6\">{fieldDescription}</p>\n )}\n </div>\n )\n\n default:\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"text\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n }\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 if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex items-center justify-center py-12\">\n <Spinner />\n <span className=\"ml-3 text-muted-foreground\">{t('workflows.tasks.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n if (error || !task) {\n return (\n <Page>\n <PageBody>\n <div className=\"p-8 text-center\">\n <p className=\"text-status-error-text\">{t('workflows.tasks.detail.notFound')}</p>\n <Button onClick={() => router.push('/backend/tasks')} className=\"mt-4\">\n {t('workflows.tasks.detail.backToList')}\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const isCompletable = task.status === 'PENDING' || task.status === 'IN_PROGRESS'\n const isOverdue = task.dueDate && new Date(task.dueDate) < new Date() && isCompletable\n\n if (isMobile) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/tasks\"\n backLabel={t('workflows.tasks.backToList', 'Back to tasks')}\n />\n <MobileTaskForm\n task={task}\n formData={formData}\n comments={comments}\n submitting={submitting}\n isCompletable={isCompletable}\n isOverdue={!!isOverdue}\n onFieldChange={handleFieldChange}\n onCommentsChange={setComments}\n onSubmit={handleSubmit}\n onCancel={() => router.push('/backend/tasks')}\n getStatusBadgeClass={getStatusBadgeClass}\n />\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"max-w-4xl mx-auto space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/tasks\"\n backLabel={t('workflows.tasks.backToList', 'Back to tasks')}\n entityTypeLabel={t('workflows.tasks.detail.type', 'User task')}\n title={task.taskName}\n subtitle={task.description || undefined}\n statusBadge={\n <span\n className={`inline-flex items-center px-3 py-1 rounded text-sm font-medium ${getStatusBadgeClass(task.status)}`}\n >\n {t(`workflows.tasks.statuses.${task.status}`)}\n </span>\n }\n />\n\n <div className=\"space-y-3\">\n\n {isOverdue && (\n <div className=\"bg-status-error-bg border border-status-error-border rounded-lg p-3\">\n <p className=\"text-sm text-status-error-text font-medium\">\n {t('workflows.tasks.detail.overdueWarning')}\n </p>\n </div>\n )}\n </div>\n\n <Separator />\n\n {/* Task Information */}\n <div className=\"bg-muted/50 rounded-lg p-4 space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('workflows.tasks.detail.sections.taskInfo')}</h2>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.fields.createdAt')}:</span>\n <span className=\"ml-2 text-foreground\">{new Date(task.createdAt).toLocaleString()}</span>\n </div>\n {task.dueDate && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.fields.dueDate')}:</span>\n <span className={`ml-2 ${isOverdue ? 'text-status-error-text font-medium' : 'text-foreground'}`}>\n {new Date(task.dueDate).toLocaleString()}\n </span>\n </div>\n )}\n {task.assignedTo && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.detail.assignedTo')}:</span>\n <span className=\"ml-2 text-foreground\">{task.assignedTo}</span>\n </div>\n )}\n {task.claimedBy && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.claimedBy')}:</span>\n <span className=\"ml-2 text-foreground\">{task.claimedBy}</span>\n </div>\n )}\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.detail.workflowInstance')}:</span>\n <Link\n href={`/backend/instances/${task.workflowInstanceId}`}\n className=\"ml-2 text-primary hover:underline text-xs font-mono\"\n >\n {task.workflowInstanceId.slice(0, 8)}...\n </Link>\n </div>\n </div>\n </div>\n\n {!isCompletable && (\n <div className=\"bg-status-info-bg border border-status-info-border rounded-lg p-4\">\n <p className=\"text-sm text-status-info-text\">\n {t('workflows.tasks.detail.cannotComplete')}\n </p>\n </div>\n )}\n\n {isCompletable && (\n <>\n <Separator />\n\n {/* Dynamic Form */}\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {task.formSchema?.properties && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold\">{t('workflows.tasks.detail.sections.form')}</h2>\n {Object.keys(task.formSchema!.properties!).map((fieldName) =>\n renderFormField(fieldName, task.formSchema!.properties![fieldName])\n )}\n </div>\n )}\n\n {!task.formSchema?.properties && (\n <div className=\"bg-status-info-bg border border-status-info-border rounded-lg p-4\">\n <p className=\"text-sm text-status-info-text\">\n {t('workflows.tasks.detail.noFormSchema')}\n </p>\n </div>\n )}\n\n <Separator />\n\n {/* Comments */}\n <div className=\"space-y-2\">\n <label htmlFor=\"comments\" className=\"block text-sm font-medium text-foreground\">\n {t('workflows.tasks.detail.comments')} ({t('workflows.tasks.detail.optional')})\n </label>\n <textarea\n id=\"comments\"\n value={comments}\n onChange={(e) => setComments(e.target.value)}\n rows={3}\n className=\"w-full px-3 py-2 border border-border rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={t('workflows.tasks.detail.commentsPlaceholder')}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-col gap-3 pt-4 sm:flex-row sm:items-center\">\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"w-full sm:w-auto bg-primary text-primary-foreground hover:bg-primary/90\"\n >\n {submitting ? t('workflows.tasks.detail.submitting') : t('workflows.tasks.detail.completeTask')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push('/backend/tasks')}\n disabled={submitting}\n className=\"w-full sm:w-auto\"\n >\n {t('common.cancel')}\n </Button>\n </div>\n </form>\n </>\n )}\n\n {task.status === 'COMPLETED' && task.formData && (\n <>\n <Separator />\n <JsonDisplay\n data={task.formData}\n title={t('workflows.tasks.detail.sections.submittedData')}\n maxInitialDepth={2}\n />\n {task.comments && (\n <div className=\"bg-muted/50 rounded-lg p-4\">\n <p className=\"text-sm font-medium text-foreground mb-2\">{t('workflows.tasks.detail.comments')}:</p>\n <p className=\"text-sm text-muted-foreground whitespace-pre-wrap\">{task.comments}</p>\n </div>\n )}\n </>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { EmailInput } from '@open-mercato/ui/primitives/email-input'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useQuery } from '@tanstack/react-query'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { MobileTaskForm } from '../../../components/mobile/MobileTaskForm'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport type { UserTaskResponse, UserTaskStatus } from '../../../data/types'\nimport { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'\n\nexport default function UserTaskDetailPage({ params }: { params: { id: string } }) {\n const router = useRouter()\n const t = useT()\n const isMobile = useIsMobile()\n const [formData, setFormData] = React.useState<Record<string, string | number | boolean>>({})\n const [comments, setComments] = React.useState('')\n const [submitting, setSubmitting] = React.useState(false)\n // Tracks the first required field that failed validation so we can mark the\n // field with aria-invalid + a red ring (Radix Select can't carry HTML\n // `required`, so we enforce constraint validation in JS instead).\n const [invalidField, setInvalidField] = React.useState<string | null>(null)\n\n const { data: task, isLoading, error } = useQuery({\n queryKey: ['workflow-task', params.id],\n queryFn: async () => {\n const result = await apiCall<{ data: UserTaskResponse }>(\n `/api/workflows/tasks/${params.id}`\n )\n if (!result.ok) {\n const httpErr = new Error(\n result.status === 404\n ? t('workflows.tasks.detail.notFound', 'Task not found')\n : t('workflows.tasks.detail.loadFailed', 'Failed to load task')\n ) as Error & { status: number }\n httpErr.status = result.status\n throw httpErr\n }\n return result.result?.data ?? null\n },\n })\n\n const handleFieldChange = (fieldName: string, value: any) => {\n setFormData(prev => ({\n ...prev,\n [fieldName]: value,\n }))\n // Clear invalid state once the user touches the offending field.\n if (invalidField === fieldName) setInvalidField(null)\n }\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n\n if (!task) return\n\n // Validate required fields. Radix Select doesn't expose HTML `required`,\n // so we enforce constraint validation here and surface it visually via\n // `invalidField` + aria-invalid on the offending field.\n if (task.formSchema?.required) {\n for (const requiredField of task.formSchema.required) {\n if (!formData[requiredField] || formData[requiredField] === '') {\n const fieldSchema = task.formSchema.properties?.[requiredField]\n const fieldLabel = fieldSchema?.title ?? requiredField\n flash(t('workflows.tasks.detail.validation.requiredField', { field: fieldLabel }), 'error')\n setInvalidField(requiredField)\n // Scroll + focus the trigger so the user sees what's missing.\n if (typeof document !== 'undefined') {\n const trigger = document.getElementById(requiredField)\n trigger?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n trigger?.focus()\n }\n return\n }\n }\n }\n setInvalidField(null)\n\n setSubmitting(true)\n\n try {\n const result = await apiCall(`/api/workflows/tasks/${params.id}/complete`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n formData,\n comments: comments || undefined,\n }),\n })\n\n if (result.ok) {\n flash(t('workflows.tasks.messages.completed'), 'success')\n router.push('/backend/tasks')\n } else {\n const error = result.result as any\n flash(error?.error || t('workflows.tasks.messages.completeFailed'), 'error')\n }\n } catch (err) {\n console.error('Error completing task:', err)\n flash(t('workflows.tasks.messages.completeFailed'), 'error')\n } finally {\n setSubmitting(false)\n }\n }\n\n const fieldValue = (fieldName: string): string | number => {\n const val = formData[fieldName]\n if (val == null || val === false) return ''\n if (typeof val === 'boolean') return ''\n return val\n }\n\n const renderFormField = (fieldName: string, fieldSchema: any) => {\n const fieldType = fieldSchema.type || 'string'\n const fieldTitle = fieldSchema.title || fieldName\n const fieldDescription = fieldSchema.description\n const required = task?.formSchema?.required?.includes(fieldName) || false\n const enumValues = fieldSchema.enum\n\n const inputClasses = \"w-full px-3 py-2 border border-border rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n const labelClasses = \"block text-sm font-medium text-foreground mb-1\"\n\n // Handle enum (select dropdown)\n if (enumValues && Array.isArray(enumValues)) {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Select\n value={fieldValue(fieldName) ? String(fieldValue(fieldName)) : undefined}\n onValueChange={(value) => handleFieldChange(fieldName, value ?? '')}\n >\n <SelectTrigger\n id={fieldName}\n className={`${inputClasses} ${invalidField === fieldName ? 'ring-2 ring-status-error-border border-status-error-border' : ''}`}\n aria-required={required}\n aria-invalid={invalidField === fieldName ? true : undefined}\n >\n <SelectValue placeholder={t('workflows.tasks.detail.form.selectOption')} />\n </SelectTrigger>\n <SelectContent>\n {enumValues.map((value: any) => (\n <SelectItem key={value} value={value}>\n {value}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )\n }\n\n // Handle different field types\n switch (fieldType) {\n case 'string':\n if (fieldSchema.format === 'email') {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <EmailInput\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n }\n if (fieldSchema.format === 'date') {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <input\n type=\"date\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n className={inputClasses}\n />\n </div>\n )\n }\n if (fieldSchema.maxLength && fieldSchema.maxLength > 200) {\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <textarea\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n rows={4}\n className={inputClasses}\n />\n </div>\n )\n }\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"text\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n\n case 'number':\n case 'integer':\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"number\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value ? Number(e.target.value) : '')}\n required={required}\n step={fieldType === 'integer' ? 1 : 'any'}\n />\n </div>\n )\n\n case 'boolean':\n return (\n <div key={fieldName} className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={fieldName}\n checked={!!formData[fieldName]}\n onChange={(e) => handleFieldChange(fieldName, e.target.checked)}\n className=\"w-4 h-4 text-primary border-border rounded focus-visible:ring-ring\"\n />\n <label htmlFor={fieldName} className=\"text-sm font-medium text-foreground\">\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n </div>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground ml-6\">{fieldDescription}</p>\n )}\n </div>\n )\n\n default:\n return (\n <div key={fieldName} className=\"space-y-2\">\n <label htmlFor={fieldName} className={labelClasses}>\n {fieldTitle}\n {required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n {fieldDescription && (\n <p className=\"text-xs text-muted-foreground\">{fieldDescription}</p>\n )}\n <Input\n type=\"text\"\n id={fieldName}\n value={fieldValue(fieldName)}\n onChange={(e) => handleFieldChange(fieldName, e.target.value)}\n required={required}\n />\n </div>\n )\n }\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 if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex items-center justify-center py-12\">\n <Spinner />\n <span className=\"ml-3 text-muted-foreground\">{t('workflows.tasks.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const isNotFound = !isLoading && (error as (Error & { status?: number }) | null)?.status === 404\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('workflows.tasks.detail.notFound', 'Task not found')}\n backHref=\"/backend/tasks\"\n backLabel={t('workflows.tasks.detail.backToList', 'Back to Tasks')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !task) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={(error as Error | null)?.message ?? t('workflows.tasks.detail.loadFailed', 'Failed to load task')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/tasks\">{t('workflows.tasks.detail.backToList', 'Back to Tasks')}</Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const isCompletable = task.status === 'PENDING' || task.status === 'IN_PROGRESS'\n const isOverdue = task.dueDate && new Date(task.dueDate) < new Date() && isCompletable\n\n if (isMobile) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/tasks\"\n backLabel={t('workflows.tasks.backToList', 'Back to tasks')}\n />\n <MobileTaskForm\n task={task}\n formData={formData}\n comments={comments}\n submitting={submitting}\n isCompletable={isCompletable}\n isOverdue={!!isOverdue}\n onFieldChange={handleFieldChange}\n onCommentsChange={setComments}\n onSubmit={handleSubmit}\n onCancel={() => router.push('/backend/tasks')}\n getStatusBadgeClass={getStatusBadgeClass}\n />\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"max-w-4xl mx-auto space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/tasks\"\n backLabel={t('workflows.tasks.backToList', 'Back to tasks')}\n entityTypeLabel={t('workflows.tasks.detail.type', 'User task')}\n title={task.taskName}\n subtitle={task.description || undefined}\n statusBadge={\n <span\n className={`inline-flex items-center px-3 py-1 rounded text-sm font-medium ${getStatusBadgeClass(task.status)}`}\n >\n {t(`workflows.tasks.statuses.${task.status}`)}\n </span>\n }\n />\n\n <div className=\"space-y-3\">\n\n {isOverdue && (\n <div className=\"bg-status-error-bg border border-status-error-border rounded-lg p-3\">\n <p className=\"text-sm text-status-error-text font-medium\">\n {t('workflows.tasks.detail.overdueWarning')}\n </p>\n </div>\n )}\n </div>\n\n <Separator />\n\n {/* Task Information */}\n <div className=\"bg-muted/50 rounded-lg p-4 space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('workflows.tasks.detail.sections.taskInfo')}</h2>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.fields.createdAt')}:</span>\n <span className=\"ml-2 text-foreground\">{new Date(task.createdAt).toLocaleString()}</span>\n </div>\n {task.dueDate && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.fields.dueDate')}:</span>\n <span className={`ml-2 ${isOverdue ? 'text-status-error-text font-medium' : 'text-foreground'}`}>\n {new Date(task.dueDate).toLocaleString()}\n </span>\n </div>\n )}\n {task.assignedTo && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.detail.assignedTo')}:</span>\n <span className=\"ml-2 text-foreground\">{task.assignedTo}</span>\n </div>\n )}\n {task.claimedBy && (\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.claimedBy')}:</span>\n <span className=\"ml-2 text-foreground\">{task.claimedBy}</span>\n </div>\n )}\n <div>\n <span className=\"text-muted-foreground\">{t('workflows.tasks.detail.workflowInstance')}:</span>\n <Link\n href={`/backend/instances/${task.workflowInstanceId}`}\n className=\"ml-2 text-primary hover:underline text-xs font-mono\"\n >\n {task.workflowInstanceId.slice(0, 8)}...\n </Link>\n </div>\n </div>\n </div>\n\n {!isCompletable && (\n <div className=\"bg-status-info-bg border border-status-info-border rounded-lg p-4\">\n <p className=\"text-sm text-status-info-text\">\n {t('workflows.tasks.detail.cannotComplete')}\n </p>\n </div>\n )}\n\n {isCompletable && (\n <>\n <Separator />\n\n {/* Dynamic Form */}\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {task.formSchema?.properties && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-semibold\">{t('workflows.tasks.detail.sections.form')}</h2>\n {Object.keys(task.formSchema!.properties!).map((fieldName) =>\n renderFormField(fieldName, task.formSchema!.properties![fieldName])\n )}\n </div>\n )}\n\n {!task.formSchema?.properties && (\n <div className=\"bg-status-info-bg border border-status-info-border rounded-lg p-4\">\n <p className=\"text-sm text-status-info-text\">\n {t('workflows.tasks.detail.noFormSchema')}\n </p>\n </div>\n )}\n\n <Separator />\n\n {/* Comments */}\n <div className=\"space-y-2\">\n <label htmlFor=\"comments\" className=\"block text-sm font-medium text-foreground\">\n {t('workflows.tasks.detail.comments')} ({t('workflows.tasks.detail.optional')})\n </label>\n <textarea\n id=\"comments\"\n value={comments}\n onChange={(e) => setComments(e.target.value)}\n rows={3}\n className=\"w-full px-3 py-2 border border-border rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder={t('workflows.tasks.detail.commentsPlaceholder')}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-col gap-3 pt-4 sm:flex-row sm:items-center\">\n <Button\n type=\"submit\"\n disabled={submitting}\n className=\"w-full sm:w-auto bg-primary text-primary-foreground hover:bg-primary/90\"\n >\n {submitting ? t('workflows.tasks.detail.submitting') : t('workflows.tasks.detail.completeTask')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => router.push('/backend/tasks')}\n disabled={submitting}\n className=\"w-full sm:w-auto\"\n >\n {t('common.cancel')}\n </Button>\n </div>\n </form>\n </>\n )}\n\n {task.status === 'COMPLETED' && task.formData && (\n <>\n <Separator />\n <JsonDisplay\n data={task.formData}\n title={t('workflows.tasks.detail.sections.submittedData')}\n maxInitialDepth={2}\n />\n {task.comments && (\n <div className=\"bg-muted/50 rounded-lg p-4\">\n <p className=\"text-sm font-medium text-foreground mb-2\">{t('workflows.tasks.detail.comments')}:</p>\n <p className=\"text-sm text-muted-foreground whitespace-pre-wrap\">{task.comments}</p>\n </div>\n )}\n </>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["error"]
|
|
7
7
|
}
|
|
@@ -2,6 +2,10 @@ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
|
2
2
|
import { getRedisUrl, getRedisUrlOrThrow } from "@open-mercato/shared/lib/redis/connection";
|
|
3
3
|
import { WorkflowDefinition } from "./data/entities.js";
|
|
4
4
|
import { BusinessRule } from "@open-mercato/core/modules/business_rules/data/entities";
|
|
5
|
+
import {
|
|
6
|
+
invalidateBusinessRuleDiscoveryCache,
|
|
7
|
+
resolveBusinessRuleDiscoveryCache
|
|
8
|
+
} from "@open-mercato/core/modules/business_rules/lib/rule-engine";
|
|
5
9
|
import * as fs from "fs";
|
|
6
10
|
import * as path from "path";
|
|
7
11
|
import { fileURLToPath } from "url";
|
|
@@ -43,6 +47,7 @@ const seedDemoWithRules = {
|
|
|
43
47
|
try {
|
|
44
48
|
const { resolve } = await createRequestContainer();
|
|
45
49
|
const em = resolve("em");
|
|
50
|
+
const cache = resolveBusinessRuleDiscoveryCache(resolve);
|
|
46
51
|
const { BusinessRule: BusinessRule2 } = await import("../business_rules/data/entities.js");
|
|
47
52
|
const rulesPath = path.join(__dirname, "examples", "guard-rules-example.json");
|
|
48
53
|
const rulesData = JSON.parse(fs.readFileSync(rulesPath, "utf8"));
|
|
@@ -65,6 +70,7 @@ const seedDemoWithRules = {
|
|
|
65
70
|
organizationId
|
|
66
71
|
});
|
|
67
72
|
await em.persist(rule).flush();
|
|
73
|
+
await invalidateBusinessRuleDiscoveryCache(cache, tenantId, organizationId);
|
|
68
74
|
console.log(` \u2713 Seeded guard rule: ${rule.ruleName}`);
|
|
69
75
|
seededCount++;
|
|
70
76
|
}
|
|
@@ -147,6 +153,7 @@ const seedOrderApproval = {
|
|
|
147
153
|
try {
|
|
148
154
|
const { resolve } = await createRequestContainer();
|
|
149
155
|
const em = resolve("em");
|
|
156
|
+
const cache = resolveBusinessRuleDiscoveryCache(resolve);
|
|
150
157
|
const guardRulesPath = path.join(__dirname, "examples", "order-approval-guard-rules.json");
|
|
151
158
|
const guardRulesData = JSON.parse(fs.readFileSync(guardRulesPath, "utf8"));
|
|
152
159
|
let rulesSeeded = 0;
|
|
@@ -172,6 +179,7 @@ const seedOrderApproval = {
|
|
|
172
179
|
}
|
|
173
180
|
if (rulesSeeded > 0) {
|
|
174
181
|
await em.flush();
|
|
182
|
+
await invalidateBusinessRuleDiscoveryCache(cache, tenantId, organizationId);
|
|
175
183
|
}
|
|
176
184
|
console.log(`\u2705 Seeded order approval guard rules`);
|
|
177
185
|
console.log(` - Guard rules seeded: ${rulesSeeded}`);
|