@contractspec/example.workflow-system 3.7.6 → 3.8.2
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/README.md +72 -119
- package/dist/approval/approval.event.js +1 -1
- package/dist/approval/approval.handler.d.ts +1 -1
- package/dist/approval/index.d.ts +4 -4
- package/dist/approval/index.js +1 -1
- package/dist/browser/approval/approval.event.js +1 -1
- package/dist/browser/approval/index.js +1 -1
- package/dist/browser/entities/index.js +166 -166
- package/dist/browser/handlers/index.js +43 -43
- package/dist/browser/handlers/workflow.handlers.js +43 -43
- package/dist/browser/index.js +1935 -1548
- package/dist/browser/instance/index.js +210 -210
- package/dist/browser/instance/instance.event.js +1 -1
- package/dist/browser/shared/demo-scenario.js +213 -0
- package/dist/browser/ui/WorkflowDashboard.visualizations.js +239 -0
- package/dist/browser/ui/hooks/index.js +0 -47
- package/dist/browser/ui/hooks/useWorkflowList.js +6 -4
- package/dist/browser/ui/index.js +6 -4
- package/dist/browser/ui/renderers/index.js +409 -73
- package/dist/browser/ui/renderers/workflow.markdown.js +409 -73
- package/dist/browser/visualizations/catalog.js +132 -0
- package/dist/browser/visualizations/index.js +133 -0
- package/dist/browser/visualizations/selectors.js +195 -0
- package/dist/entities/index.d.ts +53 -53
- package/dist/entities/index.js +166 -166
- package/dist/example.test.d.ts +1 -0
- package/dist/handlers/index.js +43 -43
- package/dist/handlers/workflow.handlers.js +43 -43
- package/dist/index.d.ts +6 -5
- package/dist/index.js +1935 -1548
- package/dist/instance/index.d.ts +3 -3
- package/dist/instance/index.js +210 -210
- package/dist/instance/instance.event.js +1 -1
- package/dist/instance/instance.handler.d.ts +1 -1
- package/dist/shared/demo-scenario.d.ts +43 -0
- package/dist/shared/demo-scenario.js +214 -0
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/mock-data.d.ts +1 -1
- package/dist/ui/WorkflowDashboard.visualizations.d.ts +4 -0
- package/dist/ui/WorkflowDashboard.visualizations.js +240 -0
- package/dist/ui/hooks/index.js +0 -47
- package/dist/ui/hooks/useWorkflowList.d.ts +2 -1
- package/dist/ui/hooks/useWorkflowList.js +6 -4
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +6 -4
- package/dist/ui/renderers/index.js +409 -73
- package/dist/ui/renderers/workflow.markdown.js +409 -73
- package/dist/visualizations/catalog.d.ts +11 -0
- package/dist/visualizations/catalog.js +133 -0
- package/dist/visualizations/index.d.ts +2 -0
- package/dist/visualizations/index.js +134 -0
- package/dist/visualizations/selectors.d.ts +11 -0
- package/dist/visualizations/selectors.js +196 -0
- package/dist/visualizations/selectors.test.d.ts +1 -0
- package/dist/workflow/index.d.ts +4 -4
- package/dist/workflow/workflow.handler.d.ts +1 -1
- package/package.json +71 -10
|
@@ -1,113 +1,448 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// src/
|
|
3
|
-
var
|
|
2
|
+
// src/shared/demo-scenario.ts
|
|
3
|
+
var WORKFLOW_SYSTEM_DEMO_PROJECT_ID = "workflow-system-demo";
|
|
4
|
+
var WORKFLOW_SYSTEM_DEMO_ORGANIZATION_ID = "org_demo";
|
|
5
|
+
var WORKFLOW_SYSTEM_DEMO_DEFINITIONS = [
|
|
4
6
|
{
|
|
5
|
-
id: "
|
|
6
|
-
name: "
|
|
7
|
+
id: "wf_expense",
|
|
8
|
+
name: "Expense Approval",
|
|
9
|
+
description: "Approve non-trivial spend before finance releases budget.",
|
|
7
10
|
type: "APPROVAL",
|
|
11
|
+
status: "ACTIVE",
|
|
12
|
+
createdAt: "2026-03-10T09:00:00.000Z",
|
|
13
|
+
updatedAt: "2026-03-20T08:15:00.000Z",
|
|
8
14
|
steps: [
|
|
9
15
|
{
|
|
10
|
-
id: "
|
|
16
|
+
id: "wfstep_expense_manager",
|
|
11
17
|
name: "Manager Review",
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
description: "Validate business value and team budget.",
|
|
19
|
+
stepOrder: 1,
|
|
20
|
+
type: "APPROVAL",
|
|
21
|
+
requiredRoles: ["manager"],
|
|
22
|
+
createdAt: "2026-03-10T09:00:00.000Z"
|
|
14
23
|
},
|
|
15
24
|
{
|
|
16
|
-
id: "
|
|
25
|
+
id: "wfstep_expense_finance",
|
|
17
26
|
name: "Finance Review",
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
description: "Confirm ledger coding and spending threshold.",
|
|
28
|
+
stepOrder: 2,
|
|
29
|
+
type: "APPROVAL",
|
|
30
|
+
requiredRoles: ["finance"],
|
|
31
|
+
createdAt: "2026-03-10T09:10:00.000Z"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
24
34
|
},
|
|
25
35
|
{
|
|
26
|
-
id: "
|
|
27
|
-
name: "
|
|
28
|
-
|
|
36
|
+
id: "wf_vendor",
|
|
37
|
+
name: "Vendor Onboarding",
|
|
38
|
+
description: "Sequence security, procurement, and legal before activation.",
|
|
39
|
+
type: "SEQUENTIAL",
|
|
40
|
+
status: "ACTIVE",
|
|
41
|
+
createdAt: "2026-03-08T11:00:00.000Z",
|
|
42
|
+
updatedAt: "2026-03-19T13:10:00.000Z",
|
|
29
43
|
steps: [
|
|
30
44
|
{
|
|
31
|
-
id: "
|
|
32
|
-
name: "
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
id: "wfstep_vendor_security",
|
|
46
|
+
name: "Security Check",
|
|
47
|
+
description: "Review data access and integration scope.",
|
|
48
|
+
stepOrder: 1,
|
|
49
|
+
type: "APPROVAL",
|
|
50
|
+
requiredRoles: ["security"],
|
|
51
|
+
createdAt: "2026-03-08T11:00:00.000Z"
|
|
35
52
|
},
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
53
|
+
{
|
|
54
|
+
id: "wfstep_vendor_procurement",
|
|
55
|
+
name: "Procurement Check",
|
|
56
|
+
description: "Validate pricing, procurement policy, and owner.",
|
|
57
|
+
stepOrder: 2,
|
|
58
|
+
type: "APPROVAL",
|
|
59
|
+
requiredRoles: ["procurement"],
|
|
60
|
+
createdAt: "2026-03-08T11:05:00.000Z"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "wfstep_vendor_legal",
|
|
64
|
+
name: "Legal Sign-off",
|
|
65
|
+
description: "Approve terms before the vendor goes live.",
|
|
66
|
+
stepOrder: 3,
|
|
67
|
+
type: "APPROVAL",
|
|
68
|
+
requiredRoles: ["legal"],
|
|
69
|
+
createdAt: "2026-03-08T11:10:00.000Z"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
39
72
|
},
|
|
40
73
|
{
|
|
41
|
-
id: "
|
|
42
|
-
name: "
|
|
43
|
-
|
|
74
|
+
id: "wf_policy_exception",
|
|
75
|
+
name: "Policy Exception",
|
|
76
|
+
description: "Escalate a temporary exception through team lead and compliance.",
|
|
77
|
+
type: "APPROVAL",
|
|
78
|
+
status: "DRAFT",
|
|
79
|
+
createdAt: "2026-03-15T07:30:00.000Z",
|
|
80
|
+
updatedAt: "2026-03-18T11:20:00.000Z",
|
|
44
81
|
steps: [
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
82
|
+
{
|
|
83
|
+
id: "wfstep_policy_lead",
|
|
84
|
+
name: "Team Lead Review",
|
|
85
|
+
description: "Check urgency and expected blast radius.",
|
|
86
|
+
stepOrder: 1,
|
|
87
|
+
type: "APPROVAL",
|
|
88
|
+
requiredRoles: ["team-lead"],
|
|
89
|
+
createdAt: "2026-03-15T07:30:00.000Z"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "wfstep_policy_compliance",
|
|
93
|
+
name: "Compliance Review",
|
|
94
|
+
description: "Accept or reject the exception request.",
|
|
95
|
+
stepOrder: 2,
|
|
96
|
+
type: "APPROVAL",
|
|
97
|
+
requiredRoles: ["compliance"],
|
|
98
|
+
createdAt: "2026-03-15T07:40:00.000Z"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
50
101
|
}
|
|
51
102
|
];
|
|
52
|
-
var
|
|
103
|
+
var WORKFLOW_SYSTEM_DEMO_INSTANCES = [
|
|
53
104
|
{
|
|
54
|
-
id: "
|
|
55
|
-
definitionId: "
|
|
56
|
-
definitionName: "Purchase Approval",
|
|
105
|
+
id: "wfinst_expense_open",
|
|
106
|
+
definitionId: "wf_expense",
|
|
57
107
|
status: "IN_PROGRESS",
|
|
58
|
-
currentStepId: "
|
|
59
|
-
|
|
60
|
-
|
|
108
|
+
currentStepId: "wfstep_expense_finance",
|
|
109
|
+
data: {
|
|
110
|
+
amount: 4200,
|
|
111
|
+
currency: "EUR",
|
|
112
|
+
vendor: "Nimbus AI"
|
|
113
|
+
},
|
|
114
|
+
requestedBy: "sarah@contractspec.io",
|
|
115
|
+
startedAt: "2026-03-20T08:00:00.000Z",
|
|
116
|
+
approvals: [
|
|
117
|
+
{
|
|
118
|
+
id: "wfappr_expense_manager",
|
|
119
|
+
stepId: "wfstep_expense_manager",
|
|
120
|
+
status: "APPROVED",
|
|
121
|
+
actorId: "manager.demo",
|
|
122
|
+
comment: "Approved for the Q2 automation budget.",
|
|
123
|
+
decidedAt: "2026-03-20T08:15:00.000Z",
|
|
124
|
+
createdAt: "2026-03-20T08:05:00.000Z"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: "wfappr_expense_finance",
|
|
128
|
+
stepId: "wfstep_expense_finance",
|
|
129
|
+
status: "PENDING",
|
|
130
|
+
createdAt: "2026-03-20T08:15:00.000Z"
|
|
131
|
+
}
|
|
132
|
+
]
|
|
61
133
|
},
|
|
62
134
|
{
|
|
63
|
-
id: "
|
|
64
|
-
definitionId: "
|
|
65
|
-
definitionName: "Purchase Approval",
|
|
135
|
+
id: "wfinst_vendor_done",
|
|
136
|
+
definitionId: "wf_vendor",
|
|
66
137
|
status: "COMPLETED",
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
138
|
+
data: {
|
|
139
|
+
vendor: "Acme Cloud",
|
|
140
|
+
riskTier: "medium"
|
|
141
|
+
},
|
|
142
|
+
requestedBy: "leo@contractspec.io",
|
|
143
|
+
startedAt: "2026-03-19T09:30:00.000Z",
|
|
144
|
+
completedAt: "2026-03-19T13:10:00.000Z",
|
|
145
|
+
approvals: [
|
|
146
|
+
{
|
|
147
|
+
id: "wfappr_vendor_security",
|
|
148
|
+
stepId: "wfstep_vendor_security",
|
|
149
|
+
status: "APPROVED",
|
|
150
|
+
actorId: "security.demo",
|
|
151
|
+
comment: "SOC2 scope is acceptable.",
|
|
152
|
+
decidedAt: "2026-03-19T10:10:00.000Z",
|
|
153
|
+
createdAt: "2026-03-19T09:35:00.000Z"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "wfappr_vendor_procurement",
|
|
157
|
+
stepId: "wfstep_vendor_procurement",
|
|
158
|
+
status: "APPROVED",
|
|
159
|
+
actorId: "procurement.demo",
|
|
160
|
+
comment: "Commercial terms match the preferred vendor tier.",
|
|
161
|
+
decidedAt: "2026-03-19T11:25:00.000Z",
|
|
162
|
+
createdAt: "2026-03-19T10:15:00.000Z"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: "wfappr_vendor_legal",
|
|
166
|
+
stepId: "wfstep_vendor_legal",
|
|
167
|
+
status: "APPROVED",
|
|
168
|
+
actorId: "legal.demo",
|
|
169
|
+
comment: "MSA redlines are complete.",
|
|
170
|
+
decidedAt: "2026-03-19T13:05:00.000Z",
|
|
171
|
+
createdAt: "2026-03-19T11:30:00.000Z"
|
|
172
|
+
}
|
|
173
|
+
]
|
|
71
174
|
},
|
|
72
175
|
{
|
|
73
|
-
id: "
|
|
74
|
-
definitionId: "
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
176
|
+
id: "wfinst_policy_rejected",
|
|
177
|
+
definitionId: "wf_policy_exception",
|
|
178
|
+
status: "REJECTED",
|
|
179
|
+
currentStepId: "wfstep_policy_compliance",
|
|
180
|
+
data: {
|
|
181
|
+
policy: "Model rollout freeze",
|
|
182
|
+
durationDays: 14
|
|
183
|
+
},
|
|
184
|
+
requestedBy: "maya@contractspec.io",
|
|
185
|
+
startedAt: "2026-03-18T10:00:00.000Z",
|
|
186
|
+
completedAt: "2026-03-18T11:20:00.000Z",
|
|
187
|
+
approvals: [
|
|
188
|
+
{
|
|
189
|
+
id: "wfappr_policy_lead",
|
|
190
|
+
stepId: "wfstep_policy_lead",
|
|
191
|
+
status: "APPROVED",
|
|
192
|
+
actorId: "lead.demo",
|
|
193
|
+
comment: "Escalation justified for the release train.",
|
|
194
|
+
decidedAt: "2026-03-18T10:30:00.000Z",
|
|
195
|
+
createdAt: "2026-03-18T10:05:00.000Z"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: "wfappr_policy_compliance",
|
|
199
|
+
stepId: "wfstep_policy_compliance",
|
|
200
|
+
status: "REJECTED",
|
|
201
|
+
actorId: "compliance.demo",
|
|
202
|
+
comment: "Exception exceeds the allowed blast radius.",
|
|
203
|
+
decidedAt: "2026-03-18T11:15:00.000Z",
|
|
204
|
+
createdAt: "2026-03-18T10:35:00.000Z"
|
|
205
|
+
}
|
|
206
|
+
]
|
|
80
207
|
}
|
|
81
208
|
];
|
|
209
|
+
|
|
210
|
+
// src/visualizations/catalog.ts
|
|
211
|
+
import {
|
|
212
|
+
defineVisualization,
|
|
213
|
+
VisualizationRegistry
|
|
214
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
215
|
+
var INSTANCE_LIST_REF = {
|
|
216
|
+
key: "workflow.instance.list",
|
|
217
|
+
version: "1.0.0"
|
|
218
|
+
};
|
|
219
|
+
var META = {
|
|
220
|
+
version: "1.0.0",
|
|
221
|
+
domain: "workflow",
|
|
222
|
+
stability: "experimental",
|
|
223
|
+
owners: ["@example.workflow-system"],
|
|
224
|
+
tags: ["workflow", "visualization", "operations"]
|
|
225
|
+
};
|
|
226
|
+
var WorkflowInstanceStatusVisualization = defineVisualization({
|
|
227
|
+
meta: {
|
|
228
|
+
...META,
|
|
229
|
+
key: "workflow-system.visualization.instance-status",
|
|
230
|
+
title: "Instance Status Breakdown",
|
|
231
|
+
description: "Distribution of workflow instance states.",
|
|
232
|
+
goal: "Surface the current workload mix.",
|
|
233
|
+
context: "Workflow operations overview."
|
|
234
|
+
},
|
|
235
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
236
|
+
visualization: {
|
|
237
|
+
kind: "pie",
|
|
238
|
+
nameDimension: "status",
|
|
239
|
+
valueMeasure: "instances",
|
|
240
|
+
dimensions: [
|
|
241
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
242
|
+
],
|
|
243
|
+
measures: [
|
|
244
|
+
{
|
|
245
|
+
key: "instances",
|
|
246
|
+
label: "Instances",
|
|
247
|
+
dataPath: "instances",
|
|
248
|
+
format: "number"
|
|
249
|
+
}
|
|
250
|
+
],
|
|
251
|
+
table: { caption: "Workflow instance counts by status." }
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
var WorkflowThroughputVisualization = defineVisualization({
|
|
255
|
+
meta: {
|
|
256
|
+
...META,
|
|
257
|
+
key: "workflow-system.visualization.throughput",
|
|
258
|
+
title: "Run Throughput",
|
|
259
|
+
description: "Daily workflow instance starts.",
|
|
260
|
+
goal: "Show operational throughput over time.",
|
|
261
|
+
context: "Workflow trend monitoring."
|
|
262
|
+
},
|
|
263
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
264
|
+
visualization: {
|
|
265
|
+
kind: "cartesian",
|
|
266
|
+
variant: "line",
|
|
267
|
+
xDimension: "day",
|
|
268
|
+
yMeasures: ["instances"],
|
|
269
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
270
|
+
measures: [
|
|
271
|
+
{
|
|
272
|
+
key: "instances",
|
|
273
|
+
label: "Instances",
|
|
274
|
+
dataPath: "instances",
|
|
275
|
+
format: "number",
|
|
276
|
+
color: "#0f766e"
|
|
277
|
+
}
|
|
278
|
+
],
|
|
279
|
+
table: { caption: "Daily workflow instance starts." }
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
var WorkflowActiveMetricVisualization = defineVisualization({
|
|
283
|
+
meta: {
|
|
284
|
+
...META,
|
|
285
|
+
key: "workflow-system.visualization.active-work",
|
|
286
|
+
title: "Active Work",
|
|
287
|
+
description: "Current in-flight or pending workflow instances.",
|
|
288
|
+
goal: "Expose active operational workload.",
|
|
289
|
+
context: "Workflow workload comparison."
|
|
290
|
+
},
|
|
291
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
292
|
+
visualization: {
|
|
293
|
+
kind: "metric",
|
|
294
|
+
measure: "value",
|
|
295
|
+
measures: [
|
|
296
|
+
{ key: "value", label: "Instances", dataPath: "value", format: "number" }
|
|
297
|
+
],
|
|
298
|
+
table: { caption: "Active workflow count." }
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
var WorkflowCompletedMetricVisualization = defineVisualization({
|
|
302
|
+
meta: {
|
|
303
|
+
...META,
|
|
304
|
+
key: "workflow-system.visualization.completed-work",
|
|
305
|
+
title: "Completed Work",
|
|
306
|
+
description: "Completed workflow instances in the current sample.",
|
|
307
|
+
goal: "Show output against active workload.",
|
|
308
|
+
context: "Workflow workload comparison."
|
|
309
|
+
},
|
|
310
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
311
|
+
visualization: {
|
|
312
|
+
kind: "metric",
|
|
313
|
+
measure: "value",
|
|
314
|
+
measures: [
|
|
315
|
+
{ key: "value", label: "Instances", dataPath: "value", format: "number" }
|
|
316
|
+
],
|
|
317
|
+
table: { caption: "Completed workflow count." }
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
var WorkflowVisualizationSpecs = [
|
|
321
|
+
WorkflowInstanceStatusVisualization,
|
|
322
|
+
WorkflowThroughputVisualization,
|
|
323
|
+
WorkflowActiveMetricVisualization,
|
|
324
|
+
WorkflowCompletedMetricVisualization
|
|
325
|
+
];
|
|
326
|
+
var WorkflowVisualizationRegistry = new VisualizationRegistry([
|
|
327
|
+
...WorkflowVisualizationSpecs
|
|
328
|
+
]);
|
|
329
|
+
var WorkflowVisualizationRefs = WorkflowVisualizationSpecs.map((spec) => ({
|
|
330
|
+
key: spec.meta.key,
|
|
331
|
+
version: spec.meta.version
|
|
332
|
+
}));
|
|
333
|
+
|
|
334
|
+
// src/visualizations/selectors.ts
|
|
335
|
+
function toDayKey(value) {
|
|
336
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
337
|
+
return date.toISOString().slice(0, 10);
|
|
338
|
+
}
|
|
339
|
+
function createWorkflowVisualizationSections(instances) {
|
|
340
|
+
const statusCounts = new Map;
|
|
341
|
+
const throughput = new Map;
|
|
342
|
+
let activeCount = 0;
|
|
343
|
+
let completedCount = 0;
|
|
344
|
+
for (const instance of instances) {
|
|
345
|
+
statusCounts.set(instance.status, (statusCounts.get(instance.status) ?? 0) + 1);
|
|
346
|
+
const day = toDayKey(instance.startedAt);
|
|
347
|
+
throughput.set(day, (throughput.get(day) ?? 0) + 1);
|
|
348
|
+
if (instance.status === "PENDING" || instance.status === "IN_PROGRESS") {
|
|
349
|
+
activeCount += 1;
|
|
350
|
+
}
|
|
351
|
+
if (instance.status === "COMPLETED") {
|
|
352
|
+
completedCount += 1;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const primaryItems = [
|
|
356
|
+
{
|
|
357
|
+
key: "workflow-status",
|
|
358
|
+
spec: WorkflowInstanceStatusVisualization,
|
|
359
|
+
data: {
|
|
360
|
+
data: Array.from(statusCounts.entries()).map(([status, count]) => ({
|
|
361
|
+
status,
|
|
362
|
+
instances: count
|
|
363
|
+
}))
|
|
364
|
+
},
|
|
365
|
+
title: "Instance Status Breakdown",
|
|
366
|
+
description: "Status mix across workflow instances.",
|
|
367
|
+
height: 260
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
key: "workflow-throughput",
|
|
371
|
+
spec: WorkflowThroughputVisualization,
|
|
372
|
+
data: {
|
|
373
|
+
data: Array.from(throughput.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, instances: count }))
|
|
374
|
+
},
|
|
375
|
+
title: "Run Throughput",
|
|
376
|
+
description: "Daily workflow starts from current instances."
|
|
377
|
+
}
|
|
378
|
+
];
|
|
379
|
+
const comparisonItems = [
|
|
380
|
+
{
|
|
381
|
+
key: "workflow-active",
|
|
382
|
+
spec: WorkflowActiveMetricVisualization,
|
|
383
|
+
data: { data: [{ value: activeCount }] },
|
|
384
|
+
title: "Active Work",
|
|
385
|
+
description: "Pending and in-progress workflows.",
|
|
386
|
+
height: 200
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
key: "workflow-completed",
|
|
390
|
+
spec: WorkflowCompletedMetricVisualization,
|
|
391
|
+
data: { data: [{ value: completedCount }] },
|
|
392
|
+
title: "Completed Work",
|
|
393
|
+
description: "Completed workflows in the current sample.",
|
|
394
|
+
height: 200
|
|
395
|
+
}
|
|
396
|
+
];
|
|
397
|
+
return {
|
|
398
|
+
primaryItems,
|
|
399
|
+
comparisonItems
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
// src/ui/renderers/workflow.markdown.ts
|
|
403
|
+
var workflowDefinitions = WORKFLOW_SYSTEM_DEMO_DEFINITIONS;
|
|
404
|
+
var workflowInstances = WORKFLOW_SYSTEM_DEMO_INSTANCES;
|
|
405
|
+
var workflowDefinitionById = new Map(workflowDefinitions.map((definition) => [definition.id, definition]));
|
|
406
|
+
function formatDate(value) {
|
|
407
|
+
return new Date(value).toISOString().slice(0, 10);
|
|
408
|
+
}
|
|
82
409
|
var workflowDashboardMarkdownRenderer = {
|
|
83
410
|
target: "markdown",
|
|
84
411
|
render: async (desc) => {
|
|
85
412
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDashboard") {
|
|
86
413
|
throw new Error("workflowDashboardMarkdownRenderer: not WorkflowDashboard");
|
|
87
414
|
}
|
|
88
|
-
const definitions =
|
|
89
|
-
const instances =
|
|
415
|
+
const definitions = workflowDefinitions;
|
|
416
|
+
const instances = workflowInstances;
|
|
417
|
+
const visualizations = createWorkflowVisualizationSections(instances);
|
|
90
418
|
const activeDefinitions = definitions.filter((d) => d.status === "ACTIVE");
|
|
91
|
-
const
|
|
92
|
-
const inProgressInstances = instances.filter((i) => i.status === "IN_PROGRESS");
|
|
93
|
-
const completedInstances = instances.filter((i) => i.status === "COMPLETED");
|
|
419
|
+
const awaitingActionInstances = instances.filter((i) => i.status === "PENDING" || i.status === "IN_PROGRESS");
|
|
94
420
|
const lines = [
|
|
95
421
|
"# Workflow Dashboard",
|
|
96
422
|
"",
|
|
97
|
-
">
|
|
423
|
+
"> Seeded workflow and approval overview for the sandbox demo.",
|
|
98
424
|
"",
|
|
99
425
|
"## Summary",
|
|
100
426
|
"",
|
|
101
427
|
"| Metric | Value |",
|
|
102
428
|
"|--------|-------|",
|
|
103
429
|
`| Active Workflows | ${activeDefinitions.length} |`,
|
|
104
|
-
`|
|
|
105
|
-
`|
|
|
106
|
-
`|
|
|
107
|
-
"",
|
|
108
|
-
"## Active Workflow Definitions",
|
|
430
|
+
`| Awaiting Action | ${awaitingActionInstances.length} |`,
|
|
431
|
+
`| Completed | ${instances.filter((i) => i.status === "COMPLETED").length} |`,
|
|
432
|
+
`| Rejected | ${instances.filter((i) => i.status === "REJECTED").length} |`,
|
|
109
433
|
""
|
|
110
434
|
];
|
|
435
|
+
lines.push("## Visualization Overview");
|
|
436
|
+
lines.push("");
|
|
437
|
+
for (const item of [
|
|
438
|
+
...visualizations.primaryItems,
|
|
439
|
+
...visualizations.comparisonItems
|
|
440
|
+
]) {
|
|
441
|
+
lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
|
|
442
|
+
}
|
|
443
|
+
lines.push("");
|
|
444
|
+
lines.push("## Active Workflow Definitions");
|
|
445
|
+
lines.push("");
|
|
111
446
|
if (activeDefinitions.length === 0) {
|
|
112
447
|
lines.push("_No active workflow definitions._");
|
|
113
448
|
} else {
|
|
@@ -126,8 +461,9 @@ var workflowDashboardMarkdownRenderer = {
|
|
|
126
461
|
lines.push("| Workflow | Requested By | Status | Started |");
|
|
127
462
|
lines.push("|----------|--------------|--------|---------|");
|
|
128
463
|
for (const inst of instances.slice(0, 10)) {
|
|
129
|
-
const startedDate =
|
|
130
|
-
|
|
464
|
+
const startedDate = formatDate(inst.startedAt);
|
|
465
|
+
const definitionName = workflowDefinitionById.get(inst.definitionId)?.name ?? inst.definitionId;
|
|
466
|
+
lines.push(`| ${definitionName} | ${inst.requestedBy} | ${inst.status} | ${startedDate} |`);
|
|
131
467
|
}
|
|
132
468
|
}
|
|
133
469
|
return {
|
|
@@ -143,7 +479,7 @@ var workflowDefinitionListMarkdownRenderer = {
|
|
|
143
479
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDefinitionList") {
|
|
144
480
|
throw new Error("workflowDefinitionListMarkdownRenderer: not WorkflowDefinitionList");
|
|
145
481
|
}
|
|
146
|
-
const definitions =
|
|
482
|
+
const definitions = workflowDefinitions;
|
|
147
483
|
const lines = [
|
|
148
484
|
"# Workflow Definitions",
|
|
149
485
|
"",
|
|
@@ -158,7 +494,7 @@ var workflowDefinitionListMarkdownRenderer = {
|
|
|
158
494
|
lines.push("### Steps");
|
|
159
495
|
lines.push("");
|
|
160
496
|
for (const step of def.steps) {
|
|
161
|
-
lines.push(`${step.
|
|
497
|
+
lines.push(`${step.stepOrder}. **${step.name}** - Roles: ${step.requiredRoles.join(", ")}`);
|
|
162
498
|
}
|
|
163
499
|
lines.push("");
|
|
164
500
|
}
|
|
@@ -175,7 +511,7 @@ var workflowInstanceDetailMarkdownRenderer = {
|
|
|
175
511
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowInstanceDetail") {
|
|
176
512
|
throw new Error("workflowInstanceDetailMarkdownRenderer: not WorkflowInstanceDetail");
|
|
177
513
|
}
|
|
178
|
-
const instance =
|
|
514
|
+
const instance = workflowInstances.find((workflowInstance) => workflowInstance.status === "IN_PROGRESS") ?? workflowInstances[0];
|
|
179
515
|
if (!instance) {
|
|
180
516
|
return {
|
|
181
517
|
mimeType: "text/markdown",
|
|
@@ -184,14 +520,14 @@ var workflowInstanceDetailMarkdownRenderer = {
|
|
|
184
520
|
No workflow instances available.`
|
|
185
521
|
};
|
|
186
522
|
}
|
|
187
|
-
const definition =
|
|
523
|
+
const definition = workflowDefinitions.find((d) => d.id === instance.definitionId);
|
|
188
524
|
const lines = [
|
|
189
|
-
`# Workflow: ${instance.
|
|
525
|
+
`# Workflow: ${definition?.name ?? instance.definitionId}`,
|
|
190
526
|
"",
|
|
191
527
|
`**Instance ID:** ${instance.id}`,
|
|
192
528
|
`**Status:** ${instance.status}`,
|
|
193
529
|
`**Requested By:** ${instance.requestedBy}`,
|
|
194
|
-
`**Started:** ${
|
|
530
|
+
`**Started:** ${formatDate(instance.startedAt)}`,
|
|
195
531
|
"",
|
|
196
532
|
"## Steps Progress",
|
|
197
533
|
""
|
|
@@ -212,7 +548,7 @@ No workflow instances available.`
|
|
|
212
548
|
lines.push("## Actions");
|
|
213
549
|
lines.push("");
|
|
214
550
|
lines.push("- **Approve** - Move to next step");
|
|
215
|
-
lines.push("- **Reject** -
|
|
551
|
+
lines.push("- **Reject** - End the workflow with a rejection outcome");
|
|
216
552
|
lines.push("- **Delegate** - Assign to another approver");
|
|
217
553
|
return {
|
|
218
554
|
mimeType: "text/markdown",
|