@open-mercato/core 0.4.2-canary-51881f6bf3 → 0.4.2-canary-5f415b8a44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/entities/workflow_event_trigger/index.js +33 -0
- package/dist/generated/entities/workflow_event_trigger/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +59 -58
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/auth/events.js +30 -0
- package/dist/modules/auth/events.js.map +7 -0
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +145 -0
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +7 -0
- package/dist/modules/business_rules/data/validators.js +34 -0
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +21 -1
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +182 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/events.js +34 -0
- package/dist/modules/catalog/events.js.map +7 -0
- package/dist/modules/customers/events.js +49 -0
- package/dist/modules/customers/events.js.map +7 -0
- package/dist/modules/directory/events.js +23 -0
- package/dist/modules/directory/events.js.map +7 -0
- package/dist/modules/sales/acl.js +1 -0
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +12 -0
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +62 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/events.js +63 -0
- package/dist/modules/sales/events.js.map +7 -0
- package/dist/modules/sales/lib/dictionaries.js +3 -0
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +25 -0
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +7 -0
- package/dist/modules/workflows/acl.js +2 -0
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +18 -6
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +6 -1
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +9 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +24 -15
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +150 -132
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +5 -6
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +81 -3
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +481 -0
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +7 -0
- package/dist/modules/workflows/components/EventTriggersEditor.js +553 -0
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +7 -0
- package/dist/modules/workflows/data/entities.js +64 -1
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +115 -0
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/events.js +38 -0
- package/dist/modules/workflows/events.js.map +7 -0
- package/dist/modules/workflows/examples/checkout-demo-definition.json +1 -5
- package/dist/modules/workflows/examples/order-approval-definition.json +257 -0
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +32 -0
- package/dist/modules/workflows/lib/activity-executor.js +75 -13
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/event-trigger-service.js +308 -0
- package/dist/modules/workflows/lib/event-trigger-service.js.map +7 -0
- package/dist/modules/workflows/lib/graph-utils.js +71 -2
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +22 -5
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +33 -23
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +157 -45
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/dist/modules/workflows/migrations/Migration20260123143500.js +36 -0
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +7 -0
- package/dist/modules/workflows/subscribers/event-trigger.js +78 -0
- package/dist/modules/workflows/subscribers/event-trigger.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +323 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +17 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +7 -0
- package/dist/modules/workflows/widgets/injection-table.js +19 -0
- package/dist/modules/workflows/widgets/injection-table.js.map +7 -0
- package/generated/entities/workflow_event_trigger/index.ts +15 -0
- package/generated/entities.ids.generated.ts +59 -58
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +3 -5
- package/src/modules/auth/events.ts +39 -0
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +163 -0
- package/src/modules/business_rules/data/validators.ts +40 -0
- package/src/modules/business_rules/index.ts +25 -0
- package/src/modules/business_rules/lib/rule-engine.ts +281 -1
- package/src/modules/catalog/events.ts +45 -0
- package/src/modules/customers/events.ts +63 -0
- package/src/modules/directory/events.ts +31 -0
- package/src/modules/sales/acl.ts +1 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +16 -0
- package/src/modules/sales/commands/documents.ts +74 -1
- package/src/modules/sales/events.ts +82 -0
- package/src/modules/sales/lib/dictionaries.ts +3 -0
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +28 -0
- package/src/modules/workflows/acl.ts +2 -0
- package/src/modules/workflows/api/instances/route.ts +21 -7
- package/src/modules/workflows/api/tasks/route.ts +7 -1
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +9 -0
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +9 -0
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +21 -3
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +5 -6
- package/src/modules/workflows/cli.ts +111 -0
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +581 -0
- package/src/modules/workflows/components/EventTriggersEditor.tsx +664 -0
- package/src/modules/workflows/data/entities.ts +124 -0
- package/src/modules/workflows/data/validators.ts +138 -0
- package/src/modules/workflows/events.ts +49 -0
- package/src/modules/workflows/examples/checkout-demo-definition.json +1 -5
- package/src/modules/workflows/examples/order-approval-definition.json +257 -0
- package/src/modules/workflows/examples/order-approval-guard-rules.json +32 -0
- package/src/modules/workflows/i18n/en.json +71 -0
- package/src/modules/workflows/lib/activity-executor.ts +129 -16
- package/src/modules/workflows/lib/event-trigger-service.ts +557 -0
- package/src/modules/workflows/lib/graph-utils.ts +117 -2
- package/src/modules/workflows/lib/seeds.ts +34 -8
- package/src/modules/workflows/lib/start-validator.ts +38 -28
- package/src/modules/workflows/lib/transition-handler.ts +208 -55
- package/src/modules/workflows/migrations/Migration20260123143500.ts +38 -0
- package/src/modules/workflows/subscribers/event-trigger.ts +109 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +446 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +16 -0
- package/src/modules/workflows/widgets/injection-table.ts +21 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
export const SALES_DOCUMENT_DATA_REFRESH_EVENT = 'sales:document:data:refresh'
|
|
4
|
+
|
|
5
|
+
export type SalesDocumentDataRefreshDetail = {
|
|
6
|
+
documentId: string
|
|
7
|
+
kind?: 'order' | 'quote'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function emitSalesDocumentDataRefresh(detail: SalesDocumentDataRefreshDetail): void {
|
|
11
|
+
if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return
|
|
12
|
+
window.dispatchEvent(
|
|
13
|
+
new CustomEvent<SalesDocumentDataRefreshDetail>(SALES_DOCUMENT_DATA_REFRESH_EVENT, { detail }),
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function subscribeSalesDocumentDataRefresh(
|
|
18
|
+
handler: (detail: SalesDocumentDataRefreshDetail) => void,
|
|
19
|
+
): () => void {
|
|
20
|
+
if (typeof window === 'undefined') return () => {}
|
|
21
|
+
const listener = (event: Event) => {
|
|
22
|
+
const detail = (event as CustomEvent<SalesDocumentDataRefreshDetail>).detail
|
|
23
|
+
if (!detail) return
|
|
24
|
+
handler(detail)
|
|
25
|
+
}
|
|
26
|
+
window.addEventListener(SALES_DOCUMENT_DATA_REFRESH_EVENT, listener as EventListener)
|
|
27
|
+
return () => window.removeEventListener(SALES_DOCUMENT_DATA_REFRESH_EVENT, listener as EventListener)
|
|
28
|
+
}
|
|
@@ -19,6 +19,8 @@ export const features = [
|
|
|
19
19
|
{ id: 'workflows.tasks.complete', title: 'Complete workflow tasks', module: moduleId },
|
|
20
20
|
{ id: 'workflows.signals.send', title: 'Send workflow signals', module: moduleId },
|
|
21
21
|
{ id: 'workflows.events.view', title: 'View workflow events', module: moduleId },
|
|
22
|
+
// Note: Event triggers are now embedded in workflow definitions.
|
|
23
|
+
// Trigger management permissions are covered by workflows.definitions.edit
|
|
22
24
|
]
|
|
23
25
|
|
|
24
26
|
export default features
|
|
@@ -70,19 +70,33 @@ export async function GET(request: NextRequest) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (status) {
|
|
73
|
-
|
|
73
|
+
// Support comma-separated status values (e.g., "RUNNING,PAUSED,WAITING_FOR_ACTIVITIES")
|
|
74
|
+
const statuses = status.split(',').map(s => s.trim()).filter(Boolean)
|
|
75
|
+
if (statuses.length === 1) {
|
|
76
|
+
where.status = statuses[0]
|
|
77
|
+
} else if (statuses.length > 1) {
|
|
78
|
+
where.status = { $in: statuses }
|
|
79
|
+
}
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
if (correlationKey) {
|
|
77
83
|
where.correlationKey = correlationKey
|
|
78
84
|
}
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
// For JSONB metadata filtering, use $contains with explicit key-value pairs
|
|
87
|
+
// MikroORM's dot notation creates table joins, not JSON access
|
|
88
|
+
if (entityType || entityId) {
|
|
89
|
+
where.$and = where.$and || []
|
|
90
|
+
if (entityType) {
|
|
91
|
+
where.$and.push({
|
|
92
|
+
metadata: { $contains: { entityType: entityType } }
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
if (entityId) {
|
|
96
|
+
where.$and.push({
|
|
97
|
+
metadata: { $contains: { entityId: entityId } }
|
|
98
|
+
})
|
|
99
|
+
}
|
|
86
100
|
}
|
|
87
101
|
|
|
88
102
|
const [instances, total] = await em.findAndCount(
|
|
@@ -67,7 +67,13 @@ export async function GET(request: NextRequest) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (status) {
|
|
70
|
-
|
|
70
|
+
// Handle comma-separated status values
|
|
71
|
+
const statusValues = status.split(',').map(s => s.trim()).filter(Boolean)
|
|
72
|
+
if (statusValues.length === 1) {
|
|
73
|
+
where.status = statusValues[0]
|
|
74
|
+
} else if (statusValues.length > 1) {
|
|
75
|
+
where.status = { $in: statusValues }
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
if (assignedTo) {
|
|
@@ -4,7 +4,7 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Edit Workflow Definition',
|
|
5
5
|
pageTitleKey: 'workflows.edit.title',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
8
|
{ label: 'Edit', labelKey: 'workflows.common.edit' },
|
|
9
9
|
],
|
|
10
10
|
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from '../../../components/formConfig'
|
|
20
20
|
import { StepsEditor } from '../../../components/StepsEditor'
|
|
21
21
|
import { TransitionsEditor } from '../../../components/TransitionsEditor'
|
|
22
|
+
import { EventTriggersEditor } from '../../../components/EventTriggersEditor'
|
|
22
23
|
|
|
23
24
|
export default function EditWorkflowDefinitionPage() {
|
|
24
25
|
const router = useRouter()
|
|
@@ -145,6 +146,14 @@ export default function EditWorkflowDefinitionPage() {
|
|
|
145
146
|
groups={formGroups}
|
|
146
147
|
submitLabel={t('workflows.form.update')}
|
|
147
148
|
/>
|
|
149
|
+
|
|
150
|
+
{/* Event Triggers Section */}
|
|
151
|
+
<div className="mt-8">
|
|
152
|
+
<EventTriggersEditor
|
|
153
|
+
workflowDefinitionId={definitionId!}
|
|
154
|
+
workflowId={definition?.workflowId}
|
|
155
|
+
/>
|
|
156
|
+
</div>
|
|
148
157
|
</PageBody>
|
|
149
158
|
</Page>
|
|
150
159
|
)
|
|
@@ -20,7 +20,7 @@ export const metadata = {
|
|
|
20
20
|
pageOrder: 100,
|
|
21
21
|
icon: createIcon,
|
|
22
22
|
breadcrumb: [
|
|
23
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
23
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
24
24
|
{ label: 'Create', labelKey: 'workflows.common.create' },
|
|
25
25
|
],
|
|
26
26
|
}
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
} from '../../../components/formConfig'
|
|
17
17
|
import { StepsEditor } from '../../../components/StepsEditor'
|
|
18
18
|
import { TransitionsEditor } from '../../../components/TransitionsEditor'
|
|
19
|
+
import { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'
|
|
20
|
+
import { Zap } from 'lucide-react'
|
|
19
21
|
|
|
20
22
|
export default function CreateWorkflowDefinitionPage() {
|
|
21
23
|
const router = useRouter()
|
|
@@ -50,6 +52,13 @@ export default function CreateWorkflowDefinitionPage() {
|
|
|
50
52
|
return (
|
|
51
53
|
<Page>
|
|
52
54
|
<PageBody>
|
|
55
|
+
<Alert variant="info" className="mb-6">
|
|
56
|
+
<Zap className="w-4 h-4" />
|
|
57
|
+
<AlertTitle>Event Triggers</AlertTitle>
|
|
58
|
+
<AlertDescription>
|
|
59
|
+
After creating this workflow definition, you can configure event triggers to automatically start the workflow when specific events occur in the system.
|
|
60
|
+
</AlertDescription>
|
|
61
|
+
</Alert>
|
|
53
62
|
<CrudForm
|
|
54
63
|
title={t('workflows.create.title')}
|
|
55
64
|
backHref="/backend/definitions"
|
|
@@ -19,7 +19,7 @@ export const metadata = {
|
|
|
19
19
|
pageOrder: 150,
|
|
20
20
|
icon: visualEditorIcon,
|
|
21
21
|
breadcrumb: [
|
|
22
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
22
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
23
23
|
{ label: 'Visual Editor', labelKey: 'workflows.backend.definitions.visual_editor.title' },
|
|
24
24
|
],
|
|
25
25
|
}
|
|
@@ -34,6 +34,8 @@ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
|
34
34
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
35
35
|
import {CircleQuestionMark, Info, PanelTopClose, PanelTopOpen, Play, Save, Trash2} from 'lucide-react'
|
|
36
36
|
import { NODE_TYPE_ICONS, NODE_TYPE_COLORS, NODE_TYPE_LABELS } from '../../../lib/node-type-icons'
|
|
37
|
+
import { DefinitionTriggersEditor } from '../../../components/DefinitionTriggersEditor'
|
|
38
|
+
import type { WorkflowDefinitionTrigger } from '../../../data/entities'
|
|
37
39
|
import * as React from "react";
|
|
38
40
|
|
|
39
41
|
/**
|
|
@@ -76,6 +78,7 @@ export default function VisualEditorPage() {
|
|
|
76
78
|
const [icon, setIcon] = useState('')
|
|
77
79
|
const [effectiveFrom, setEffectiveFrom] = useState('')
|
|
78
80
|
const [effectiveTo, setEffectiveTo] = useState('')
|
|
81
|
+
const [triggers, setTriggers] = useState<WorkflowDefinitionTrigger[]>([])
|
|
79
82
|
|
|
80
83
|
// Load existing definition if ID is provided
|
|
81
84
|
useEffect(() => {
|
|
@@ -113,6 +116,9 @@ export default function VisualEditorPage() {
|
|
|
113
116
|
setNodes(graph.nodes)
|
|
114
117
|
setEdges(graph.edges)
|
|
115
118
|
|
|
119
|
+
// Load embedded triggers from definition
|
|
120
|
+
setTriggers(definition.definition?.triggers || [])
|
|
121
|
+
|
|
116
122
|
flash('Workflow loaded successfully', 'success')
|
|
117
123
|
} catch (error) {
|
|
118
124
|
console.error('Error loading workflow definition:', error)
|
|
@@ -284,8 +290,12 @@ export default function VisualEditorPage() {
|
|
|
284
290
|
return
|
|
285
291
|
}
|
|
286
292
|
|
|
287
|
-
// Generate definition data
|
|
288
|
-
const
|
|
293
|
+
// Generate definition data and include triggers
|
|
294
|
+
const graphDefinition = graphToDefinition(nodes, edges, { includePositions: true })
|
|
295
|
+
const definitionData = {
|
|
296
|
+
...graphDefinition,
|
|
297
|
+
triggers: triggers.length > 0 ? triggers : undefined,
|
|
298
|
+
}
|
|
289
299
|
|
|
290
300
|
// Run Zod schema validation before saving
|
|
291
301
|
const schemaResult = workflowDefinitionDataSchema.safeParse(definitionData)
|
|
@@ -357,7 +367,7 @@ export default function VisualEditorPage() {
|
|
|
357
367
|
} finally {
|
|
358
368
|
setIsSaving(false)
|
|
359
369
|
}
|
|
360
|
-
}, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags, definitionId, router])
|
|
370
|
+
}, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags, triggers, definitionId, router])
|
|
361
371
|
|
|
362
372
|
// Test workflow
|
|
363
373
|
const handleTest = useCallback(() => {
|
|
@@ -475,6 +485,7 @@ export default function VisualEditorPage() {
|
|
|
475
485
|
setIcon('')
|
|
476
486
|
setEffectiveFrom('')
|
|
477
487
|
setEffectiveTo('')
|
|
488
|
+
setTriggers([])
|
|
478
489
|
setShowClearConfirm(false)
|
|
479
490
|
flash('Canvas cleared', 'success')
|
|
480
491
|
}, [])
|
|
@@ -709,6 +720,13 @@ export default function VisualEditorPage() {
|
|
|
709
720
|
</div>
|
|
710
721
|
</div>
|
|
711
722
|
</div>
|
|
723
|
+
|
|
724
|
+
{/* Event Triggers - Always visible, managed as part of definition */}
|
|
725
|
+
<DefinitionTriggersEditor
|
|
726
|
+
value={triggers}
|
|
727
|
+
onChange={setTriggers}
|
|
728
|
+
className="mt-4"
|
|
729
|
+
/>
|
|
712
730
|
</div>
|
|
713
731
|
)}
|
|
714
732
|
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Event Details',
|
|
5
5
|
pageTitleKey: 'workflows.events.detail.title',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
8
|
-
{ label: 'Events', labelKey: 'workflows.events.plural', href: '/backend/
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
+
{ label: 'Events', labelKey: 'workflows.events.plural', href: '/backend/events' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -212,7 +212,7 @@ export default function WorkflowEventDetailPage() {
|
|
|
212
212
|
</dt>
|
|
213
213
|
<dd className="mt-1">
|
|
214
214
|
<Link
|
|
215
|
-
href={`/backend/
|
|
215
|
+
href={`/backend/instances/${event.workflowInstance.id}`}
|
|
216
216
|
className="text-sm text-primary hover:underline font-mono"
|
|
217
217
|
>
|
|
218
218
|
{event.workflowInstance.id}
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Workflow Instance Details',
|
|
5
5
|
pageTitleKey: 'workflows.instances.singular',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
8
|
-
{ label: 'Instances', labelKey: 'workflows.instances.plural', href: '/backend/
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
+
{ label: 'Instances', labelKey: 'workflows.instances.plural', href: '/backend/instances' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Task Details',
|
|
5
5
|
pageTitleKey: 'workflows.tasks.singular',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/
|
|
8
|
-
{ label: 'Tasks', labelKey: 'workflows.tasks.plural', href: '/backend/
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
+
{ label: 'Tasks', labelKey: 'workflows.tasks.plural', href: '/backend/tasks' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -72,7 +72,6 @@ export default function UserTasksListPage() {
|
|
|
72
72
|
params.set('offset', offset.toString())
|
|
73
73
|
|
|
74
74
|
if (filterValues.status) params.set('status', filterValues.status as string)
|
|
75
|
-
if (filterValues.myTasks === 'true') params.set('myTasks', 'true')
|
|
76
75
|
if (filterValues.overdue === 'true') params.set('overdue', 'true')
|
|
77
76
|
if (filterValues.workflowInstanceId) params.set('workflowInstanceId', filterValues.workflowInstanceId as string)
|
|
78
77
|
|
|
@@ -155,10 +154,10 @@ export default function UserTasksListPage() {
|
|
|
155
154
|
label: t('workflows.tasks.filters.status'),
|
|
156
155
|
options: [
|
|
157
156
|
{ label: t('common.all'), value: '' },
|
|
158
|
-
{ label: t('workflows.tasks.
|
|
159
|
-
{ label: t('workflows.tasks.
|
|
160
|
-
{ label: t('workflows.tasks.
|
|
161
|
-
{ label: t('workflows.tasks.
|
|
157
|
+
{ label: t('workflows.tasks.statuses.PENDING'), value: 'PENDING' },
|
|
158
|
+
{ label: t('workflows.tasks.statuses.IN_PROGRESS'), value: 'IN_PROGRESS' },
|
|
159
|
+
{ label: t('workflows.tasks.statuses.COMPLETED'), value: 'COMPLETED' },
|
|
160
|
+
{ label: t('workflows.tasks.statuses.CANCELLED'), value: 'CANCELLED' },
|
|
162
161
|
],
|
|
163
162
|
},
|
|
164
163
|
{
|
|
@@ -214,7 +213,7 @@ export default function UserTasksListPage() {
|
|
|
214
213
|
accessorKey: 'status',
|
|
215
214
|
cell: ({ row }) => (
|
|
216
215
|
<span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>
|
|
217
|
-
{t(`workflows.tasks.
|
|
216
|
+
{t(`workflows.tasks.statuses.${row.original.status}`)}
|
|
218
217
|
</span>
|
|
219
218
|
),
|
|
220
219
|
},
|
|
@@ -2,6 +2,7 @@ import type { ModuleCli } from '@open-mercato/shared/modules/registry'
|
|
|
2
2
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
3
3
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
4
4
|
import { WorkflowDefinition } from './data/entities'
|
|
5
|
+
import { BusinessRule, type RuleType } from '@open-mercato/core/modules/business_rules/data/entities'
|
|
5
6
|
import * as fs from 'fs'
|
|
6
7
|
import * as path from 'path'
|
|
7
8
|
import { fileURLToPath } from 'url'
|
|
@@ -283,6 +284,111 @@ const seedSimpleApproval: ModuleCli = {
|
|
|
283
284
|
},
|
|
284
285
|
}
|
|
285
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Seed order approval example
|
|
289
|
+
*/
|
|
290
|
+
const seedOrderApproval: ModuleCli = {
|
|
291
|
+
command: 'seed-order-approval',
|
|
292
|
+
async run(rest: string[]) {
|
|
293
|
+
const args = parseArgs(rest)
|
|
294
|
+
const tenantId = String(args.tenantId ?? args.tenant ?? args.t ?? '')
|
|
295
|
+
const organizationId = String(args.organizationId ?? args.orgId ?? args.org ?? args.o ?? '')
|
|
296
|
+
|
|
297
|
+
if (!tenantId || !organizationId) {
|
|
298
|
+
console.error('Usage: mercato workflows seed-order-approval --tenant <tenantId> --org <organizationId>')
|
|
299
|
+
return
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
const { resolve } = await createRequestContainer()
|
|
304
|
+
const em = resolve<EntityManager>('em')
|
|
305
|
+
|
|
306
|
+
// 1. Seed order approval guard rules first
|
|
307
|
+
const guardRulesPath = path.join(__dirname, 'examples', 'order-approval-guard-rules.json')
|
|
308
|
+
const guardRulesData = JSON.parse(fs.readFileSync(guardRulesPath, 'utf8')) as Array<{
|
|
309
|
+
ruleId: string
|
|
310
|
+
ruleName: string
|
|
311
|
+
ruleType: RuleType
|
|
312
|
+
entityType: string
|
|
313
|
+
description?: string
|
|
314
|
+
eventType?: string
|
|
315
|
+
conditionExpression?: Record<string, unknown>
|
|
316
|
+
enabled?: boolean
|
|
317
|
+
priority?: number
|
|
318
|
+
}>
|
|
319
|
+
|
|
320
|
+
let rulesSeeded = 0
|
|
321
|
+
let rulesSkipped = 0
|
|
322
|
+
for (const rule of guardRulesData) {
|
|
323
|
+
const existingRule = await em.findOne(BusinessRule, {
|
|
324
|
+
ruleId: rule.ruleId,
|
|
325
|
+
tenantId,
|
|
326
|
+
organizationId,
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
if (existingRule) {
|
|
330
|
+
rulesSkipped++
|
|
331
|
+
continue
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const newRule = em.create(BusinessRule, {
|
|
335
|
+
...rule,
|
|
336
|
+
tenantId,
|
|
337
|
+
organizationId,
|
|
338
|
+
})
|
|
339
|
+
em.persist(newRule)
|
|
340
|
+
console.log(` ✓ Seeded guard rule: ${rule.ruleName}`)
|
|
341
|
+
rulesSeeded++
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (rulesSeeded > 0) {
|
|
345
|
+
await em.flush()
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// 2. Read the order approval workflow definition
|
|
349
|
+
const approvalPath = path.join(__dirname, 'examples', 'order-approval-definition.json')
|
|
350
|
+
const approvalData = JSON.parse(fs.readFileSync(approvalPath, 'utf8'))
|
|
351
|
+
|
|
352
|
+
// Check if it already exists
|
|
353
|
+
const existing = await em.findOne(WorkflowDefinition, {
|
|
354
|
+
workflowId: approvalData.workflowId,
|
|
355
|
+
tenantId,
|
|
356
|
+
organizationId,
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
if (existing) {
|
|
360
|
+
console.log(`✓ Order approval workflow '${approvalData.workflowId}' already exists (ID: ${existing.id})`)
|
|
361
|
+
console.log(` - Guard rules seeded: ${rulesSeeded}`)
|
|
362
|
+
console.log(` - Guard rules skipped: ${rulesSkipped}`)
|
|
363
|
+
return
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Create the workflow definition
|
|
367
|
+
const workflow = em.create(WorkflowDefinition, {
|
|
368
|
+
...approvalData,
|
|
369
|
+
tenantId,
|
|
370
|
+
organizationId,
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
await em.persistAndFlush(workflow)
|
|
374
|
+
|
|
375
|
+
console.log(`✓ Seeded order approval workflow: ${workflow.workflowName}`)
|
|
376
|
+
console.log(` - ID: ${workflow.id}`)
|
|
377
|
+
console.log(` - Workflow ID: ${workflow.workflowId}`)
|
|
378
|
+
console.log(` - Version: ${workflow.version}`)
|
|
379
|
+
console.log(` - Steps: ${workflow.definition.steps.length}`)
|
|
380
|
+
console.log(` - Transitions: ${workflow.definition.transitions.length}`)
|
|
381
|
+
console.log(` - Guard rules seeded: ${rulesSeeded}`)
|
|
382
|
+
console.log(` - Guard rules skipped: ${rulesSkipped}`)
|
|
383
|
+
console.log('')
|
|
384
|
+
console.log('Order approval workflow is ready!')
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.error('Error seeding order approval workflow:', error)
|
|
387
|
+
throw error
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
}
|
|
391
|
+
|
|
286
392
|
/**
|
|
287
393
|
* Start workflow activity worker
|
|
288
394
|
*/
|
|
@@ -366,6 +472,10 @@ const seedAll: ModuleCli = {
|
|
|
366
472
|
await seedSimpleApproval.run(rest)
|
|
367
473
|
console.log('')
|
|
368
474
|
|
|
475
|
+
// Seed order approval
|
|
476
|
+
await seedOrderApproval.run(rest)
|
|
477
|
+
console.log('')
|
|
478
|
+
|
|
369
479
|
console.log('✓ All example workflows seeded successfully!')
|
|
370
480
|
} catch (error) {
|
|
371
481
|
console.error('Error seeding workflows:', error)
|
|
@@ -444,6 +554,7 @@ const workflowsCliCommands = [
|
|
|
444
554
|
seedDemoWithRules,
|
|
445
555
|
seedSalesPipeline,
|
|
446
556
|
seedSimpleApproval,
|
|
557
|
+
seedOrderApproval,
|
|
447
558
|
seedAll,
|
|
448
559
|
]
|
|
449
560
|
|