@bpmnkit/operate 0.0.5

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.
Files changed (72) hide show
  1. package/README.md +131 -0
  2. package/dist/components/badge.d.ts +2 -0
  3. package/dist/components/badge.js +2 -0
  4. package/dist/components/card.d.ts +2 -0
  5. package/dist/components/card.js +2 -0
  6. package/dist/components/chart.d.ts +6 -0
  7. package/dist/components/chart.js +161 -0
  8. package/dist/components/filter-table.d.ts +20 -0
  9. package/dist/components/filter-table.js +215 -0
  10. package/dist/components/table.d.ts +2 -0
  11. package/dist/components/table.js +2 -0
  12. package/dist/css.d.ts +2 -0
  13. package/dist/css.js +1071 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +2 -0
  16. package/dist/mock-data.d.ts +18 -0
  17. package/dist/mock-data.js +509 -0
  18. package/dist/operate.d.ts +3 -0
  19. package/dist/operate.js +308 -0
  20. package/dist/router.d.ts +9 -0
  21. package/dist/router.js +49 -0
  22. package/dist/stores/base.d.ts +20 -0
  23. package/dist/stores/base.js +32 -0
  24. package/dist/stores/dashboard.d.ts +6 -0
  25. package/dist/stores/dashboard.js +19 -0
  26. package/dist/stores/decisions.d.ts +9 -0
  27. package/dist/stores/decisions.js +19 -0
  28. package/dist/stores/definitions.d.ts +9 -0
  29. package/dist/stores/definitions.js +19 -0
  30. package/dist/stores/incidents.d.ts +10 -0
  31. package/dist/stores/incidents.js +27 -0
  32. package/dist/stores/instances.d.ts +15 -0
  33. package/dist/stores/instances.js +33 -0
  34. package/dist/stores/jobs.d.ts +10 -0
  35. package/dist/stores/jobs.js +19 -0
  36. package/dist/stores/tasks.d.ts +10 -0
  37. package/dist/stores/tasks.js +19 -0
  38. package/dist/stream.d.ts +12 -0
  39. package/dist/stream.js +42 -0
  40. package/dist/types.d.ts +48 -0
  41. package/dist/types.js +2 -0
  42. package/dist/views/dashboard.d.ts +6 -0
  43. package/dist/views/dashboard.js +98 -0
  44. package/dist/views/decision-detail.d.ts +15 -0
  45. package/dist/views/decision-detail.js +167 -0
  46. package/dist/views/decisions.d.ts +7 -0
  47. package/dist/views/decisions.js +78 -0
  48. package/dist/views/definition-detail.d.ts +15 -0
  49. package/dist/views/definition-detail.js +339 -0
  50. package/dist/views/definitions.d.ts +7 -0
  51. package/dist/views/definitions.js +70 -0
  52. package/dist/views/header.d.ts +9 -0
  53. package/dist/views/header.js +49 -0
  54. package/dist/views/incident-detail.d.ts +14 -0
  55. package/dist/views/incident-detail.js +540 -0
  56. package/dist/views/incidents.d.ts +7 -0
  57. package/dist/views/incidents.js +108 -0
  58. package/dist/views/instance-detail.d.ts +16 -0
  59. package/dist/views/instance-detail.js +728 -0
  60. package/dist/views/instances.d.ts +7 -0
  61. package/dist/views/instances.js +249 -0
  62. package/dist/views/jobs.d.ts +6 -0
  63. package/dist/views/jobs.js +60 -0
  64. package/dist/views/messages.d.ts +11 -0
  65. package/dist/views/messages.js +431 -0
  66. package/dist/views/nav.d.ts +10 -0
  67. package/dist/views/nav.js +60 -0
  68. package/dist/views/task-detail.d.ts +13 -0
  69. package/dist/views/task-detail.js +187 -0
  70. package/dist/views/tasks.d.ts +7 -0
  71. package/dist/views/tasks.js +72 -0
  72. package/package.json +46 -0
@@ -0,0 +1,7 @@
1
+ import type { InstancesStore } from "../stores/instances.js";
2
+ import type { ProcessInstanceResult } from "../types.js";
3
+ export declare function createInstancesView(store: InstancesStore, onSelect: (inst: ProcessInstanceResult) => void, onFilterChange?: (state: string) => void): {
4
+ el: HTMLElement;
5
+ destroy(): void;
6
+ };
7
+ //# sourceMappingURL=instances.d.ts.map
@@ -0,0 +1,249 @@
1
+ import { badge } from "../components/badge.js";
2
+ import { createFilterTable } from "../components/filter-table.js";
3
+ function relTime(iso) {
4
+ if (!iso)
5
+ return "—";
6
+ const diff = Date.now() - new Date(iso).getTime();
7
+ const m = Math.floor(diff / 60_000);
8
+ if (m < 1)
9
+ return "just now";
10
+ if (m < 60)
11
+ return `${m}m ago`;
12
+ const h = Math.floor(m / 60);
13
+ if (h < 24)
14
+ return `${h}h ago`;
15
+ return `${Math.floor(h / 24)}d ago`;
16
+ }
17
+ function buildInstMap(items) {
18
+ const m = new Map();
19
+ for (const inst of items)
20
+ m.set(inst.processInstanceKey, inst);
21
+ return m;
22
+ }
23
+ /** Walk up the parent chain and return an ordered array of process definition names. */
24
+ function getChain(inst, map) {
25
+ const chain = [];
26
+ let cur = inst;
27
+ const visited = new Set();
28
+ while (cur && !visited.has(cur.processInstanceKey)) {
29
+ visited.add(cur.processInstanceKey);
30
+ chain.unshift(cur.processDefinitionName ?? cur.processDefinitionId ?? "?");
31
+ if (!cur.parentProcessInstanceKey)
32
+ break;
33
+ const parent = map.get(cur.parentProcessInstanceKey);
34
+ if (!parent) {
35
+ // Parent exists but not loaded — prefix with ellipsis
36
+ chain.unshift("…");
37
+ break;
38
+ }
39
+ cur = parent;
40
+ }
41
+ return chain;
42
+ }
43
+ /**
44
+ * Returns the processDefinitionId of the root (top-level) process for this instance.
45
+ * Uses rootProcessInstanceKey (8.9+) as a shortcut; falls back to walking the chain.
46
+ */
47
+ function getRootDefId(inst, map) {
48
+ // 8.9+ shortcut
49
+ if (inst.rootProcessInstanceKey && inst.rootProcessInstanceKey !== inst.processInstanceKey) {
50
+ const root = map.get(inst.rootProcessInstanceKey);
51
+ if (root)
52
+ return root.processDefinitionId;
53
+ }
54
+ // Walk up
55
+ let cur = inst;
56
+ const visited = new Set();
57
+ while (cur && !visited.has(cur.processInstanceKey)) {
58
+ visited.add(cur.processInstanceKey);
59
+ if (!cur.parentProcessInstanceKey)
60
+ return cur.processDefinitionId;
61
+ const parent = map.get(cur.parentProcessInstanceKey);
62
+ if (!parent)
63
+ return cur.processDefinitionId;
64
+ cur = parent;
65
+ }
66
+ return inst.processDefinitionId;
67
+ }
68
+ /** Collect unique {id, name} pairs for all root-level process definitions. */
69
+ function getRootDefs(items) {
70
+ const seen = new Set();
71
+ const result = [];
72
+ for (const inst of items) {
73
+ if (inst.parentProcessInstanceKey)
74
+ continue; // skip sub-processes
75
+ const id = inst.processDefinitionId;
76
+ if (!id || seen.has(id))
77
+ continue;
78
+ seen.add(id);
79
+ result.push({ id, name: inst.processDefinitionName ?? id });
80
+ }
81
+ return result.sort((a, b) => a.name.localeCompare(b.name));
82
+ }
83
+ /** Render a breadcrumb element for the Process column. */
84
+ function renderBreadcrumb(chain) {
85
+ const el = document.createElement("span");
86
+ el.className = "op-proc-breadcrumb";
87
+ if (chain.length === 0) {
88
+ el.textContent = "—";
89
+ return el;
90
+ }
91
+ for (let i = 0; i < chain.length; i++) {
92
+ if (i > 0) {
93
+ const sep = document.createElement("span");
94
+ sep.className = "op-proc-sep";
95
+ sep.textContent = " / ";
96
+ el.appendChild(sep);
97
+ }
98
+ const part = document.createElement("span");
99
+ part.className = i === chain.length - 1 ? "op-proc-leaf" : "op-proc-root";
100
+ part.textContent = chain[i] ?? "";
101
+ el.appendChild(part);
102
+ }
103
+ return el;
104
+ }
105
+ export function createInstancesView(store, onSelect, onFilterChange) {
106
+ const el = document.createElement("div");
107
+ el.className = "op-view";
108
+ // ── State filter bar ────────────────────────────────────────────────────
109
+ const filterBar = document.createElement("div");
110
+ filterBar.className = "op-filter-bar";
111
+ const stateFilters = [
112
+ { label: "All", value: "" },
113
+ { label: "Active", value: "ACTIVE" },
114
+ { label: "Completed", value: "COMPLETED" },
115
+ { label: "Terminated", value: "TERMINATED" },
116
+ ];
117
+ let activeStateFilter = "";
118
+ for (const f of stateFilters) {
119
+ const btn = document.createElement("button");
120
+ btn.className = `op-filter-btn${f.value === activeStateFilter ? " op-filter-btn--active" : ""}`;
121
+ btn.textContent = f.label;
122
+ btn.addEventListener("click", () => {
123
+ activeStateFilter = f.value;
124
+ for (const b of Array.from(filterBar.querySelectorAll(".op-filter-btn"))) {
125
+ b.classList.remove("op-filter-btn--active");
126
+ }
127
+ btn.classList.add("op-filter-btn--active");
128
+ onFilterChange?.(f.value);
129
+ });
130
+ filterBar.appendChild(btn);
131
+ }
132
+ // ── Main process filter ─────────────────────────────────────────────────
133
+ const procFilterWrap = document.createElement("div");
134
+ procFilterWrap.className = "op-proc-filter-wrap";
135
+ const procFilterLabel = document.createElement("span");
136
+ procFilterLabel.className = "op-proc-filter-label";
137
+ procFilterLabel.textContent = "Process:";
138
+ procFilterWrap.appendChild(procFilterLabel);
139
+ const procSelect = document.createElement("select");
140
+ procSelect.className = "op-proc-filter-select";
141
+ // "All" option is always first
142
+ const allOpt = document.createElement("option");
143
+ allOpt.value = "";
144
+ allOpt.textContent = "All";
145
+ procSelect.appendChild(allOpt);
146
+ procFilterWrap.appendChild(procSelect);
147
+ filterBar.appendChild(procFilterWrap);
148
+ el.appendChild(filterBar);
149
+ let mainProcessFilter = "";
150
+ procSelect.addEventListener("change", () => {
151
+ mainProcessFilter = procSelect.value;
152
+ render();
153
+ });
154
+ // ── Table ───────────────────────────────────────────────────────────────
155
+ let instMap = new Map();
156
+ const { el: tableEl, setRows } = createFilterTable({
157
+ columns: [
158
+ {
159
+ label: "Key",
160
+ width: "140px",
161
+ render: (row) => row.processInstanceKey,
162
+ sortValue: (row) => row.processInstanceKey,
163
+ },
164
+ {
165
+ label: "Process",
166
+ render: (row) => renderBreadcrumb(getChain(row, instMap)),
167
+ sortValue: (row) => {
168
+ const chain = getChain(row, instMap);
169
+ return chain.join(" / ");
170
+ },
171
+ },
172
+ {
173
+ label: "Business ID",
174
+ width: "140px",
175
+ render: (row) => row.businessId || "—",
176
+ sortValue: (row) => row.businessId ?? "",
177
+ },
178
+ {
179
+ label: "State",
180
+ width: "120px",
181
+ render: (row) => {
182
+ const wrap = document.createElement("div");
183
+ wrap.className = "bpmnkit-badge-wrap";
184
+ wrap.appendChild(badge(row.state));
185
+ if (row.hasIncident) {
186
+ const inc = document.createElement("span");
187
+ inc.className = "bpmnkit-badge bpmnkit-badge--incident-dot";
188
+ inc.title = "Has incident";
189
+ inc.textContent = "⚠";
190
+ wrap.appendChild(inc);
191
+ }
192
+ return wrap;
193
+ },
194
+ sortValue: (row) => row.state,
195
+ },
196
+ {
197
+ label: "Started",
198
+ width: "100px",
199
+ render: (row) => relTime(row.startDate),
200
+ sortValue: (row) => row.startDate ?? "",
201
+ },
202
+ {
203
+ label: "Ended",
204
+ width: "100px",
205
+ render: (row) => relTime(row.endDate),
206
+ sortValue: (row) => row.endDate ?? "",
207
+ },
208
+ ],
209
+ searchFn: (row) => {
210
+ const chain = getChain(row, instMap);
211
+ return [row.processInstanceKey, ...chain, row.businessId, row.state].filter(Boolean).join(" ");
212
+ },
213
+ onRowClick: onSelect,
214
+ emptyText: "No process instances found",
215
+ });
216
+ el.appendChild(tableEl);
217
+ function updateProcFilter(items) {
218
+ const defs = getRootDefs(items);
219
+ // Rebuild options after the "All" entry, preserving current selection
220
+ while (procSelect.options.length > 1)
221
+ procSelect.remove(1);
222
+ for (const def of defs) {
223
+ const opt = document.createElement("option");
224
+ opt.value = def.id;
225
+ opt.textContent = def.name;
226
+ procSelect.appendChild(opt);
227
+ }
228
+ // Restore selection if still valid
229
+ procSelect.value = mainProcessFilter;
230
+ if (!procSelect.value) {
231
+ mainProcessFilter = "";
232
+ procSelect.value = "";
233
+ }
234
+ }
235
+ function render() {
236
+ const items = store.state.data?.items ?? [];
237
+ instMap = buildInstMap(items);
238
+ updateProcFilter(items);
239
+ let rows = items;
240
+ if (mainProcessFilter) {
241
+ rows = rows.filter((inst) => getRootDefId(inst, instMap) === mainProcessFilter);
242
+ }
243
+ setRows(rows);
244
+ }
245
+ const unsub = store.subscribe(render);
246
+ render();
247
+ return { el, destroy: unsub };
248
+ }
249
+ //# sourceMappingURL=instances.js.map
@@ -0,0 +1,6 @@
1
+ import type { JobsStore } from "../stores/jobs.js";
2
+ export declare function createJobsView(store: JobsStore): {
3
+ el: HTMLElement;
4
+ destroy(): void;
5
+ };
6
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1,60 @@
1
+ import { badge } from "../components/badge.js";
2
+ import { createFilterTable } from "../components/filter-table.js";
3
+ export function createJobsView(store) {
4
+ const el = document.createElement("div");
5
+ el.className = "op-view";
6
+ const { el: tableEl, setRows } = createFilterTable({
7
+ columns: [
8
+ {
9
+ label: "Key",
10
+ width: "120px",
11
+ render: (row) => row.jobKey,
12
+ sortValue: (row) => row.jobKey,
13
+ },
14
+ {
15
+ label: "Type",
16
+ render: (row) => row.type,
17
+ sortValue: (row) => row.type,
18
+ },
19
+ {
20
+ label: "Worker",
21
+ width: "160px",
22
+ render: (row) => row.worker || "—",
23
+ sortValue: (row) => row.worker ?? "",
24
+ },
25
+ {
26
+ label: "Retries",
27
+ width: "70px",
28
+ render: (row) => String(row.retries),
29
+ sortValue: (row) => row.retries,
30
+ },
31
+ {
32
+ label: "State",
33
+ width: "120px",
34
+ render: (row) => badge(row.state),
35
+ sortValue: (row) => row.state,
36
+ },
37
+ {
38
+ label: "Error",
39
+ width: "200px",
40
+ render: (row) => {
41
+ const span = document.createElement("span");
42
+ span.className = "op-cell-error";
43
+ span.title = row.errorMessage ?? "";
44
+ span.textContent = row.errorMessage ?? "—";
45
+ return span;
46
+ },
47
+ },
48
+ ],
49
+ searchFn: (row) => [row.jobKey, row.type, row.worker, row.state, row.errorMessage].filter(Boolean).join(" "),
50
+ emptyText: "No jobs found",
51
+ });
52
+ el.appendChild(tableEl);
53
+ function render() {
54
+ setRows(store.state.data?.items ?? []);
55
+ }
56
+ const unsub = store.subscribe(render);
57
+ render();
58
+ return { el, destroy: unsub };
59
+ }
60
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1,11 @@
1
+ interface Config {
2
+ proxyUrl: string;
3
+ profile: string | null;
4
+ mock: boolean;
5
+ }
6
+ export declare function createMessagesView(cfg: Config): {
7
+ el: HTMLElement;
8
+ destroy(): void;
9
+ };
10
+ export {};
11
+ //# sourceMappingURL=messages.d.ts.map