@things-factory/labeling 9.1.19
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/CHANGELOG.md +87 -0
- package/ENTITY_IMPLEMENTATION.md +351 -0
- package/INTEGRATION_COMPLETE.md +531 -0
- package/MIGRATION_GUIDE.md +310 -0
- package/README.md +551 -0
- package/REFACTORING_SUMMARY.md +212 -0
- package/UI_DOCUMENTATION.md +552 -0
- package/dist-client/index.d.ts +3 -0
- package/dist-client/index.js +9 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/pages/labeling-workflow-builder.d.ts +26 -0
- package/dist-client/pages/labeling-workflow-builder.js +636 -0
- package/dist-client/pages/labeling-workflow-builder.js.map +1 -0
- package/dist-client/pages/labeling-workflow-list.d.ts +24 -0
- package/dist-client/pages/labeling-workflow-list.js +495 -0
- package/dist-client/pages/labeling-workflow-list.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +47 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/entities/index.d.ts +5 -0
- package/dist-server/entities/index.js +11 -0
- package/dist-server/entities/index.js.map +1 -0
- package/dist-server/index.d.ts +3 -0
- package/dist-server/index.js +7 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/route.d.ts +2 -0
- package/dist-server/route.js +6 -0
- package/dist-server/route.js.map +1 -0
- package/dist-server/service/index.d.ts +8 -0
- package/dist-server/service/index.js +21 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/labeling-workflow-service.d.ts +69 -0
- package/dist-server/service/labeling-workflow-service.js +521 -0
- package/dist-server/service/labeling-workflow-service.js.map +1 -0
- package/dist-server/service/labeling-workflow.d.ts +30 -0
- package/dist-server/service/labeling-workflow.js +119 -0
- package/dist-server/service/labeling-workflow.js.map +1 -0
- package/dist-server/service/workflow-execution-step.d.ts +28 -0
- package/dist-server/service/workflow-execution-step.js +115 -0
- package/dist-server/service/workflow-execution-step.js.map +1 -0
- package/dist-server/service/workflow-execution.d.ts +27 -0
- package/dist-server/service/workflow-execution.js +110 -0
- package/dist-server/service/workflow-execution.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/dist-server/types/workflow-types.d.ts +141 -0
- package/dist-server/types/workflow-types.js +488 -0
- package/dist-server/types/workflow-types.js.map +1 -0
- package/package.json +51 -0
- package/things-factory.config.js +11 -0
- package/translations/en.json +6 -0
- package/translations/ja.json +6 -0
- package/translations/ko.json +6 -0
- package/translations/ms.json +6 -0
- package/translations/zh.json +6 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PageView } from '@operato/shell';
|
|
2
|
+
/**
|
|
3
|
+
* Workflow List Page
|
|
4
|
+
*
|
|
5
|
+
* Displays all labeling workflows with CRUD operations
|
|
6
|
+
*/
|
|
7
|
+
export declare class LabelingWorkflowListPage extends PageView {
|
|
8
|
+
static styles: import("lit").CSSResult[];
|
|
9
|
+
workflows: any[];
|
|
10
|
+
loading: boolean;
|
|
11
|
+
filterStatus: string;
|
|
12
|
+
filterProjectId: string;
|
|
13
|
+
firstUpdated(): Promise<void>;
|
|
14
|
+
loadWorkflows(): Promise<void>;
|
|
15
|
+
createWorkflow(): void;
|
|
16
|
+
editWorkflow(workflowId: string, event: Event): void;
|
|
17
|
+
executeWorkflow(workflowId: string, event: Event): Promise<void>;
|
|
18
|
+
pauseWorkflow(workflowId: string, event: Event): Promise<void>;
|
|
19
|
+
resumeWorkflow(workflowId: string, event: Event): Promise<void>;
|
|
20
|
+
deleteWorkflow(workflowId: string, event: Event): Promise<void>;
|
|
21
|
+
getStatusClass(status: string): "status-active" | "status-draft" | "status-paused" | "status-completed" | "status-failed" | "";
|
|
22
|
+
get filteredWorkflows(): any[];
|
|
23
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LabelingWorkflowListPage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const lit_1 = require("lit");
|
|
6
|
+
const decorators_js_1 = require("lit/decorators.js");
|
|
7
|
+
const shell_1 = require("@operato/shell");
|
|
8
|
+
const graphql_1 = require("@operato/graphql");
|
|
9
|
+
const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
|
|
10
|
+
const shell_2 = require("@operato/shell");
|
|
11
|
+
/**
|
|
12
|
+
* Workflow List Page
|
|
13
|
+
*
|
|
14
|
+
* Displays all labeling workflows with CRUD operations
|
|
15
|
+
*/
|
|
16
|
+
let LabelingWorkflowListPage = class LabelingWorkflowListPage extends shell_1.PageView {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.workflows = [];
|
|
20
|
+
this.loading = true;
|
|
21
|
+
this.filterStatus = 'all';
|
|
22
|
+
this.filterProjectId = '';
|
|
23
|
+
}
|
|
24
|
+
static { this.styles = [
|
|
25
|
+
(0, lit_1.css) `
|
|
26
|
+
:host {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
padding: 20px;
|
|
30
|
+
background-color: var(--md-sys-color-surface);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.header {
|
|
34
|
+
display: flex;
|
|
35
|
+
justify-content: space-between;
|
|
36
|
+
align-items: center;
|
|
37
|
+
margin-bottom: 20px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
h1 {
|
|
41
|
+
font-size: 24px;
|
|
42
|
+
margin: 0;
|
|
43
|
+
color: var(--md-sys-color-on-surface);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.toolbar {
|
|
47
|
+
display: flex;
|
|
48
|
+
gap: 10px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
button {
|
|
52
|
+
padding: 10px 20px;
|
|
53
|
+
background-color: var(--md-sys-color-primary);
|
|
54
|
+
color: var(--md-sys-color-on-primary);
|
|
55
|
+
border: none;
|
|
56
|
+
border-radius: 4px;
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
button:hover {
|
|
61
|
+
opacity: 0.9;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
button.secondary {
|
|
65
|
+
background-color: var(--md-sys-color-secondary);
|
|
66
|
+
color: var(--md-sys-color-on-secondary);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.workflow-list {
|
|
70
|
+
display: grid;
|
|
71
|
+
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
72
|
+
gap: 20px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.workflow-card {
|
|
76
|
+
background-color: var(--md-sys-color-surface-variant);
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
padding: 20px;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
transition:
|
|
81
|
+
transform 0.2s,
|
|
82
|
+
box-shadow 0.2s;
|
|
83
|
+
border: 1px solid var(--md-sys-color-outline);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.workflow-card:hover {
|
|
87
|
+
transform: translateY(-4px);
|
|
88
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.workflow-header {
|
|
92
|
+
display: flex;
|
|
93
|
+
justify-content: space-between;
|
|
94
|
+
align-items: start;
|
|
95
|
+
margin-bottom: 10px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.workflow-name {
|
|
99
|
+
font-size: 18px;
|
|
100
|
+
font-weight: bold;
|
|
101
|
+
margin-bottom: 5px;
|
|
102
|
+
color: var(--md-sys-color-on-surface);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.workflow-status {
|
|
106
|
+
display: inline-block;
|
|
107
|
+
padding: 4px 8px;
|
|
108
|
+
border-radius: 4px;
|
|
109
|
+
font-size: 12px;
|
|
110
|
+
font-weight: 500;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.status-active {
|
|
114
|
+
background-color: #4caf50;
|
|
115
|
+
color: white;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.status-draft {
|
|
119
|
+
background-color: #9e9e9e;
|
|
120
|
+
color: white;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.status-paused {
|
|
124
|
+
background-color: #ff9800;
|
|
125
|
+
color: white;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.status-completed {
|
|
129
|
+
background-color: #2196f3;
|
|
130
|
+
color: white;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.status-failed {
|
|
134
|
+
background-color: #f44336;
|
|
135
|
+
color: white;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.workflow-description {
|
|
139
|
+
font-size: 14px;
|
|
140
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
141
|
+
margin-bottom: 10px;
|
|
142
|
+
overflow: hidden;
|
|
143
|
+
text-overflow: ellipsis;
|
|
144
|
+
display: -webkit-box;
|
|
145
|
+
-webkit-line-clamp: 2;
|
|
146
|
+
-webkit-box-orient: vertical;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.workflow-info {
|
|
150
|
+
font-size: 12px;
|
|
151
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
152
|
+
margin-bottom: 5px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.workflow-steps {
|
|
156
|
+
font-size: 12px;
|
|
157
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
158
|
+
margin-top: 10px;
|
|
159
|
+
padding-top: 10px;
|
|
160
|
+
border-top: 1px solid var(--md-sys-color-outline);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.workflow-actions {
|
|
164
|
+
display: flex;
|
|
165
|
+
gap: 5px;
|
|
166
|
+
margin-top: 15px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.workflow-actions button {
|
|
170
|
+
flex: 1;
|
|
171
|
+
padding: 8px;
|
|
172
|
+
font-size: 12px;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.loading {
|
|
176
|
+
text-align: center;
|
|
177
|
+
padding: 40px;
|
|
178
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.empty-state {
|
|
182
|
+
text-align: center;
|
|
183
|
+
padding: 60px 20px;
|
|
184
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.empty-state h2 {
|
|
188
|
+
font-size: 20px;
|
|
189
|
+
margin-bottom: 10px;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.empty-state p {
|
|
193
|
+
font-size: 14px;
|
|
194
|
+
margin-bottom: 20px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.filter-bar {
|
|
198
|
+
display: flex;
|
|
199
|
+
gap: 10px;
|
|
200
|
+
margin-bottom: 20px;
|
|
201
|
+
align-items: center;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.filter-bar select,
|
|
205
|
+
.filter-bar input {
|
|
206
|
+
padding: 8px 12px;
|
|
207
|
+
border: 1px solid var(--md-sys-color-outline);
|
|
208
|
+
border-radius: 4px;
|
|
209
|
+
background-color: var(--md-sys-color-surface);
|
|
210
|
+
color: var(--md-sys-color-on-surface);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.filter-bar label {
|
|
214
|
+
font-size: 14px;
|
|
215
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
216
|
+
}
|
|
217
|
+
`
|
|
218
|
+
]; }
|
|
219
|
+
async firstUpdated() {
|
|
220
|
+
await this.loadWorkflows();
|
|
221
|
+
}
|
|
222
|
+
async loadWorkflows() {
|
|
223
|
+
this.loading = true;
|
|
224
|
+
try {
|
|
225
|
+
const response = await graphql_1.client.query({
|
|
226
|
+
query: (0, graphql_tag_1.default) `
|
|
227
|
+
query GetWorkflows($projectId: Int) {
|
|
228
|
+
labelingWorkflows(projectId: $projectId) {
|
|
229
|
+
items {
|
|
230
|
+
id
|
|
231
|
+
name
|
|
232
|
+
description
|
|
233
|
+
projectId
|
|
234
|
+
status
|
|
235
|
+
triggerType
|
|
236
|
+
steps {
|
|
237
|
+
name
|
|
238
|
+
type
|
|
239
|
+
}
|
|
240
|
+
createdAt
|
|
241
|
+
lastExecutedAt
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
`,
|
|
246
|
+
variables: this.filterProjectId ? { projectId: parseInt(this.filterProjectId) } : {}
|
|
247
|
+
});
|
|
248
|
+
this.workflows = response.data.labelingWorkflows.items || [];
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
console.error('Failed to load workflows:', error);
|
|
252
|
+
alert('Failed to load workflows');
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
this.loading = false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
createWorkflow() {
|
|
259
|
+
(0, shell_2.navigate)('workflow-builder');
|
|
260
|
+
}
|
|
261
|
+
editWorkflow(workflowId, event) {
|
|
262
|
+
event.stopPropagation();
|
|
263
|
+
(0, shell_2.navigate)(`workflow-builder/${workflowId}`);
|
|
264
|
+
}
|
|
265
|
+
async executeWorkflow(workflowId, event) {
|
|
266
|
+
event.stopPropagation();
|
|
267
|
+
if (!confirm('Execute this workflow?'))
|
|
268
|
+
return;
|
|
269
|
+
try {
|
|
270
|
+
const response = await graphql_1.client.mutate({
|
|
271
|
+
mutation: (0, graphql_tag_1.default) `
|
|
272
|
+
mutation ExecuteWorkflow($workflowId: String!) {
|
|
273
|
+
executeLabelingWorkflow(input: { workflowId: $workflowId }) {
|
|
274
|
+
executionId
|
|
275
|
+
status
|
|
276
|
+
summary
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
`,
|
|
280
|
+
variables: { workflowId }
|
|
281
|
+
});
|
|
282
|
+
const result = response.data.executeLabelingWorkflow;
|
|
283
|
+
alert(`Workflow execution started!\nExecution ID: ${result.executionId}`);
|
|
284
|
+
await this.loadWorkflows();
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
console.error('Failed to execute workflow:', error);
|
|
288
|
+
alert('Failed to execute workflow');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async pauseWorkflow(workflowId, event) {
|
|
292
|
+
event.stopPropagation();
|
|
293
|
+
if (!confirm('Pause this workflow?'))
|
|
294
|
+
return;
|
|
295
|
+
try {
|
|
296
|
+
await graphql_1.client.mutate({
|
|
297
|
+
mutation: (0, graphql_tag_1.default) `
|
|
298
|
+
mutation PauseWorkflow($workflowId: String!) {
|
|
299
|
+
pauseLabelingWorkflow(workflowId: $workflowId) {
|
|
300
|
+
id
|
|
301
|
+
status
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
`,
|
|
305
|
+
variables: { workflowId }
|
|
306
|
+
});
|
|
307
|
+
alert('Workflow paused successfully');
|
|
308
|
+
await this.loadWorkflows();
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
console.error('Failed to pause workflow:', error);
|
|
312
|
+
alert('Failed to pause workflow');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
async resumeWorkflow(workflowId, event) {
|
|
316
|
+
event.stopPropagation();
|
|
317
|
+
if (!confirm('Resume this workflow?'))
|
|
318
|
+
return;
|
|
319
|
+
try {
|
|
320
|
+
await graphql_1.client.mutate({
|
|
321
|
+
mutation: (0, graphql_tag_1.default) `
|
|
322
|
+
mutation ResumeWorkflow($workflowId: String!) {
|
|
323
|
+
resumeLabelingWorkflow(workflowId: $workflowId) {
|
|
324
|
+
id
|
|
325
|
+
status
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
`,
|
|
329
|
+
variables: { workflowId }
|
|
330
|
+
});
|
|
331
|
+
alert('Workflow resumed successfully');
|
|
332
|
+
await this.loadWorkflows();
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
console.error('Failed to resume workflow:', error);
|
|
336
|
+
alert('Failed to resume workflow');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async deleteWorkflow(workflowId, event) {
|
|
340
|
+
event.stopPropagation();
|
|
341
|
+
if (!confirm('Are you sure you want to delete this workflow? This action cannot be undone.'))
|
|
342
|
+
return;
|
|
343
|
+
try {
|
|
344
|
+
await graphql_1.client.mutate({
|
|
345
|
+
mutation: (0, graphql_tag_1.default) `
|
|
346
|
+
mutation DeleteWorkflow($workflowId: String!) {
|
|
347
|
+
deleteLabelingWorkflow(workflowId: $workflowId)
|
|
348
|
+
}
|
|
349
|
+
`,
|
|
350
|
+
variables: { workflowId }
|
|
351
|
+
});
|
|
352
|
+
alert('Workflow deleted successfully');
|
|
353
|
+
await this.loadWorkflows();
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
console.error('Failed to delete workflow:', error);
|
|
357
|
+
alert('Failed to delete workflow');
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
getStatusClass(status) {
|
|
361
|
+
switch (status?.toLowerCase()) {
|
|
362
|
+
case 'active':
|
|
363
|
+
return 'status-active';
|
|
364
|
+
case 'draft':
|
|
365
|
+
return 'status-draft';
|
|
366
|
+
case 'paused':
|
|
367
|
+
return 'status-paused';
|
|
368
|
+
case 'completed':
|
|
369
|
+
return 'status-completed';
|
|
370
|
+
case 'failed':
|
|
371
|
+
return 'status-failed';
|
|
372
|
+
default:
|
|
373
|
+
return '';
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
get filteredWorkflows() {
|
|
377
|
+
return this.workflows.filter(workflow => {
|
|
378
|
+
if (this.filterStatus !== 'all' && workflow.status !== this.filterStatus) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
render() {
|
|
385
|
+
if (this.loading) {
|
|
386
|
+
return (0, lit_1.html) `<div class="loading">Loading workflows...</div>`;
|
|
387
|
+
}
|
|
388
|
+
return (0, lit_1.html) `
|
|
389
|
+
<div class="header">
|
|
390
|
+
<h1>Labeling Workflows</h1>
|
|
391
|
+
<div class="toolbar">
|
|
392
|
+
<button @click=${this.createWorkflow}>Create Workflow</button>
|
|
393
|
+
<button class="secondary" @click=${this.loadWorkflows}>Refresh</button>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
|
|
397
|
+
<div class="filter-bar">
|
|
398
|
+
<label>Status:</label>
|
|
399
|
+
<select
|
|
400
|
+
.value=${this.filterStatus}
|
|
401
|
+
@change=${(e) => {
|
|
402
|
+
this.filterStatus = e.target.value;
|
|
403
|
+
this.requestUpdate();
|
|
404
|
+
}}
|
|
405
|
+
>
|
|
406
|
+
<option value="all">All</option>
|
|
407
|
+
<option value="draft">Draft</option>
|
|
408
|
+
<option value="active">Active</option>
|
|
409
|
+
<option value="paused">Paused</option>
|
|
410
|
+
<option value="completed">Completed</option>
|
|
411
|
+
<option value="failed">Failed</option>
|
|
412
|
+
</select>
|
|
413
|
+
|
|
414
|
+
<label>Project ID:</label>
|
|
415
|
+
<input
|
|
416
|
+
type="number"
|
|
417
|
+
.value=${this.filterProjectId}
|
|
418
|
+
@input=${(e) => (this.filterProjectId = e.target.value)}
|
|
419
|
+
placeholder="Filter by project"
|
|
420
|
+
/>
|
|
421
|
+
<button class="secondary" @click=${this.loadWorkflows}>Apply Filter</button>
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
${this.filteredWorkflows.length === 0
|
|
425
|
+
? (0, lit_1.html) `
|
|
426
|
+
<div class="empty-state">
|
|
427
|
+
<h2>No workflows found</h2>
|
|
428
|
+
<p>Create your first labeling workflow to get started</p>
|
|
429
|
+
<button @click=${this.createWorkflow}>Create Workflow</button>
|
|
430
|
+
</div>
|
|
431
|
+
`
|
|
432
|
+
: (0, lit_1.html) `
|
|
433
|
+
<div class="workflow-list">
|
|
434
|
+
${this.filteredWorkflows.map(workflow => (0, lit_1.html) `
|
|
435
|
+
<div class="workflow-card">
|
|
436
|
+
<div class="workflow-header">
|
|
437
|
+
<div class="workflow-name">${workflow.name}</div>
|
|
438
|
+
<span class="workflow-status ${this.getStatusClass(workflow.status)}">${workflow.status}</span>
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<div class="workflow-description">${workflow.description || 'No description'}</div>
|
|
442
|
+
|
|
443
|
+
<div class="workflow-info">Project ID: ${workflow.projectId}</div>
|
|
444
|
+
<div class="workflow-info">Trigger: ${workflow.triggerType}</div>
|
|
445
|
+
<div class="workflow-info">Created: ${new Date(workflow.createdAt).toLocaleDateString()}</div>
|
|
446
|
+
${workflow.lastExecutedAt
|
|
447
|
+
? (0, lit_1.html) `<div class="workflow-info">
|
|
448
|
+
Last executed: ${new Date(workflow.lastExecutedAt).toLocaleDateString()}
|
|
449
|
+
</div>`
|
|
450
|
+
: ''}
|
|
451
|
+
|
|
452
|
+
<div class="workflow-steps">${workflow.steps.length} steps configured</div>
|
|
453
|
+
|
|
454
|
+
<div class="workflow-actions">
|
|
455
|
+
<button @click=${(e) => this.editWorkflow(workflow.id, e)}>Edit</button>
|
|
456
|
+
<button @click=${(e) => this.executeWorkflow(workflow.id, e)}>Execute</button>
|
|
457
|
+
${workflow.status === 'active'
|
|
458
|
+
? (0, lit_1.html) `<button class="secondary" @click=${(e) => this.pauseWorkflow(workflow.id, e)}>
|
|
459
|
+
Pause
|
|
460
|
+
</button>`
|
|
461
|
+
: workflow.status === 'paused'
|
|
462
|
+
? (0, lit_1.html) `<button @click=${(e) => this.resumeWorkflow(workflow.id, e)}>Resume</button>`
|
|
463
|
+
: ''}
|
|
464
|
+
<button class="secondary" @click=${(e) => this.deleteWorkflow(workflow.id, e)}>
|
|
465
|
+
Delete
|
|
466
|
+
</button>
|
|
467
|
+
</div>
|
|
468
|
+
</div>
|
|
469
|
+
`)}
|
|
470
|
+
</div>
|
|
471
|
+
`}
|
|
472
|
+
`;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
exports.LabelingWorkflowListPage = LabelingWorkflowListPage;
|
|
476
|
+
tslib_1.__decorate([
|
|
477
|
+
(0, decorators_js_1.state)(),
|
|
478
|
+
tslib_1.__metadata("design:type", Array)
|
|
479
|
+
], LabelingWorkflowListPage.prototype, "workflows", void 0);
|
|
480
|
+
tslib_1.__decorate([
|
|
481
|
+
(0, decorators_js_1.state)(),
|
|
482
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
483
|
+
], LabelingWorkflowListPage.prototype, "loading", void 0);
|
|
484
|
+
tslib_1.__decorate([
|
|
485
|
+
(0, decorators_js_1.state)(),
|
|
486
|
+
tslib_1.__metadata("design:type", String)
|
|
487
|
+
], LabelingWorkflowListPage.prototype, "filterStatus", void 0);
|
|
488
|
+
tslib_1.__decorate([
|
|
489
|
+
(0, decorators_js_1.state)(),
|
|
490
|
+
tslib_1.__metadata("design:type", String)
|
|
491
|
+
], LabelingWorkflowListPage.prototype, "filterProjectId", void 0);
|
|
492
|
+
exports.LabelingWorkflowListPage = LabelingWorkflowListPage = tslib_1.__decorate([
|
|
493
|
+
(0, decorators_js_1.customElement)('labeling-workflow-list-page')
|
|
494
|
+
], LabelingWorkflowListPage);
|
|
495
|
+
//# sourceMappingURL=labeling-workflow-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labeling-workflow-list.js","sourceRoot":"","sources":["../../client/pages/labeling-workflow-list.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport gql from 'graphql-tag'\nimport { navigate } from '@operato/shell'\n\n/**\n * Workflow List Page\n *\n * Displays all labeling workflows with CRUD operations\n */\n@customElement('labeling-workflow-list-page')\nexport class LabelingWorkflowListPage extends PageView {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n padding: 20px;\n background-color: var(--md-sys-color-surface);\n }\n\n .header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n }\n\n h1 {\n font-size: 24px;\n margin: 0;\n color: var(--md-sys-color-on-surface);\n }\n\n .toolbar {\n display: flex;\n gap: 10px;\n }\n\n button {\n padding: 10px 20px;\n background-color: var(--md-sys-color-primary);\n color: var(--md-sys-color-on-primary);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n }\n\n button:hover {\n opacity: 0.9;\n }\n\n button.secondary {\n background-color: var(--md-sys-color-secondary);\n color: var(--md-sys-color-on-secondary);\n }\n\n .workflow-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 20px;\n }\n\n .workflow-card {\n background-color: var(--md-sys-color-surface-variant);\n border-radius: 8px;\n padding: 20px;\n cursor: pointer;\n transition:\n transform 0.2s,\n box-shadow 0.2s;\n border: 1px solid var(--md-sys-color-outline);\n }\n\n .workflow-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n .workflow-header {\n display: flex;\n justify-content: space-between;\n align-items: start;\n margin-bottom: 10px;\n }\n\n .workflow-name {\n font-size: 18px;\n font-weight: bold;\n margin-bottom: 5px;\n color: var(--md-sys-color-on-surface);\n }\n\n .workflow-status {\n display: inline-block;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n .status-active {\n background-color: #4caf50;\n color: white;\n }\n\n .status-draft {\n background-color: #9e9e9e;\n color: white;\n }\n\n .status-paused {\n background-color: #ff9800;\n color: white;\n }\n\n .status-completed {\n background-color: #2196f3;\n color: white;\n }\n\n .status-failed {\n background-color: #f44336;\n color: white;\n }\n\n .workflow-description {\n font-size: 14px;\n color: var(--md-sys-color-on-surface-variant);\n margin-bottom: 10px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n\n .workflow-info {\n font-size: 12px;\n color: var(--md-sys-color-on-surface-variant);\n margin-bottom: 5px;\n }\n\n .workflow-steps {\n font-size: 12px;\n color: var(--md-sys-color-on-surface-variant);\n margin-top: 10px;\n padding-top: 10px;\n border-top: 1px solid var(--md-sys-color-outline);\n }\n\n .workflow-actions {\n display: flex;\n gap: 5px;\n margin-top: 15px;\n }\n\n .workflow-actions button {\n flex: 1;\n padding: 8px;\n font-size: 12px;\n }\n\n .loading {\n text-align: center;\n padding: 40px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .empty-state {\n text-align: center;\n padding: 60px 20px;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n .empty-state h2 {\n font-size: 20px;\n margin-bottom: 10px;\n }\n\n .empty-state p {\n font-size: 14px;\n margin-bottom: 20px;\n }\n\n .filter-bar {\n display: flex;\n gap: 10px;\n margin-bottom: 20px;\n align-items: center;\n }\n\n .filter-bar select,\n .filter-bar input {\n padding: 8px 12px;\n border: 1px solid var(--md-sys-color-outline);\n border-radius: 4px;\n background-color: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n }\n\n .filter-bar label {\n font-size: 14px;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @state() workflows: any[] = []\n @state() loading: boolean = true\n @state() filterStatus: string = 'all'\n @state() filterProjectId: string = ''\n\n async firstUpdated() {\n await this.loadWorkflows()\n }\n\n async loadWorkflows() {\n this.loading = true\n try {\n const response = await client.query({\n query: gql`\n query GetWorkflows($projectId: Int) {\n labelingWorkflows(projectId: $projectId) {\n items {\n id\n name\n description\n projectId\n status\n triggerType\n steps {\n name\n type\n }\n createdAt\n lastExecutedAt\n }\n }\n }\n `,\n variables: this.filterProjectId ? { projectId: parseInt(this.filterProjectId) } : {}\n })\n\n this.workflows = response.data.labelingWorkflows.items || []\n } catch (error) {\n console.error('Failed to load workflows:', error)\n alert('Failed to load workflows')\n } finally {\n this.loading = false\n }\n }\n\n createWorkflow() {\n navigate('workflow-builder')\n }\n\n editWorkflow(workflowId: string, event: Event) {\n event.stopPropagation()\n navigate(`workflow-builder/${workflowId}`)\n }\n\n async executeWorkflow(workflowId: string, event: Event) {\n event.stopPropagation()\n\n if (!confirm('Execute this workflow?')) return\n\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ExecuteWorkflow($workflowId: String!) {\n executeLabelingWorkflow(input: { workflowId: $workflowId }) {\n executionId\n status\n summary\n }\n }\n `,\n variables: { workflowId }\n })\n\n const result = response.data.executeLabelingWorkflow\n alert(`Workflow execution started!\\nExecution ID: ${result.executionId}`)\n await this.loadWorkflows()\n } catch (error) {\n console.error('Failed to execute workflow:', error)\n alert('Failed to execute workflow')\n }\n }\n\n async pauseWorkflow(workflowId: string, event: Event) {\n event.stopPropagation()\n\n if (!confirm('Pause this workflow?')) return\n\n try {\n await client.mutate({\n mutation: gql`\n mutation PauseWorkflow($workflowId: String!) {\n pauseLabelingWorkflow(workflowId: $workflowId) {\n id\n status\n }\n }\n `,\n variables: { workflowId }\n })\n\n alert('Workflow paused successfully')\n await this.loadWorkflows()\n } catch (error) {\n console.error('Failed to pause workflow:', error)\n alert('Failed to pause workflow')\n }\n }\n\n async resumeWorkflow(workflowId: string, event: Event) {\n event.stopPropagation()\n\n if (!confirm('Resume this workflow?')) return\n\n try {\n await client.mutate({\n mutation: gql`\n mutation ResumeWorkflow($workflowId: String!) {\n resumeLabelingWorkflow(workflowId: $workflowId) {\n id\n status\n }\n }\n `,\n variables: { workflowId }\n })\n\n alert('Workflow resumed successfully')\n await this.loadWorkflows()\n } catch (error) {\n console.error('Failed to resume workflow:', error)\n alert('Failed to resume workflow')\n }\n }\n\n async deleteWorkflow(workflowId: string, event: Event) {\n event.stopPropagation()\n\n if (!confirm('Are you sure you want to delete this workflow? This action cannot be undone.')) return\n\n try {\n await client.mutate({\n mutation: gql`\n mutation DeleteWorkflow($workflowId: String!) {\n deleteLabelingWorkflow(workflowId: $workflowId)\n }\n `,\n variables: { workflowId }\n })\n\n alert('Workflow deleted successfully')\n await this.loadWorkflows()\n } catch (error) {\n console.error('Failed to delete workflow:', error)\n alert('Failed to delete workflow')\n }\n }\n\n getStatusClass(status: string) {\n switch (status?.toLowerCase()) {\n case 'active':\n return 'status-active'\n case 'draft':\n return 'status-draft'\n case 'paused':\n return 'status-paused'\n case 'completed':\n return 'status-completed'\n case 'failed':\n return 'status-failed'\n default:\n return ''\n }\n }\n\n get filteredWorkflows() {\n return this.workflows.filter(workflow => {\n if (this.filterStatus !== 'all' && workflow.status !== this.filterStatus) {\n return false\n }\n return true\n })\n }\n\n render() {\n if (this.loading) {\n return html`<div class=\"loading\">Loading workflows...</div>`\n }\n\n return html`\n <div class=\"header\">\n <h1>Labeling Workflows</h1>\n <div class=\"toolbar\">\n <button @click=${this.createWorkflow}>Create Workflow</button>\n <button class=\"secondary\" @click=${this.loadWorkflows}>Refresh</button>\n </div>\n </div>\n\n <div class=\"filter-bar\">\n <label>Status:</label>\n <select\n .value=${this.filterStatus}\n @change=${(e: any) => {\n this.filterStatus = e.target.value\n this.requestUpdate()\n }}\n >\n <option value=\"all\">All</option>\n <option value=\"draft\">Draft</option>\n <option value=\"active\">Active</option>\n <option value=\"paused\">Paused</option>\n <option value=\"completed\">Completed</option>\n <option value=\"failed\">Failed</option>\n </select>\n\n <label>Project ID:</label>\n <input\n type=\"number\"\n .value=${this.filterProjectId}\n @input=${(e: any) => (this.filterProjectId = e.target.value)}\n placeholder=\"Filter by project\"\n />\n <button class=\"secondary\" @click=${this.loadWorkflows}>Apply Filter</button>\n </div>\n\n ${this.filteredWorkflows.length === 0\n ? html`\n <div class=\"empty-state\">\n <h2>No workflows found</h2>\n <p>Create your first labeling workflow to get started</p>\n <button @click=${this.createWorkflow}>Create Workflow</button>\n </div>\n `\n : html`\n <div class=\"workflow-list\">\n ${this.filteredWorkflows.map(\n workflow => html`\n <div class=\"workflow-card\">\n <div class=\"workflow-header\">\n <div class=\"workflow-name\">${workflow.name}</div>\n <span class=\"workflow-status ${this.getStatusClass(workflow.status)}\">${workflow.status}</span>\n </div>\n\n <div class=\"workflow-description\">${workflow.description || 'No description'}</div>\n\n <div class=\"workflow-info\">Project ID: ${workflow.projectId}</div>\n <div class=\"workflow-info\">Trigger: ${workflow.triggerType}</div>\n <div class=\"workflow-info\">Created: ${new Date(workflow.createdAt).toLocaleDateString()}</div>\n ${workflow.lastExecutedAt\n ? html`<div class=\"workflow-info\">\n Last executed: ${new Date(workflow.lastExecutedAt).toLocaleDateString()}\n </div>`\n : ''}\n\n <div class=\"workflow-steps\">${workflow.steps.length} steps configured</div>\n\n <div class=\"workflow-actions\">\n <button @click=${(e: Event) => this.editWorkflow(workflow.id, e)}>Edit</button>\n <button @click=${(e: Event) => this.executeWorkflow(workflow.id, e)}>Execute</button>\n ${workflow.status === 'active'\n ? html`<button class=\"secondary\" @click=${(e: Event) => this.pauseWorkflow(workflow.id, e)}>\n Pause\n </button>`\n : workflow.status === 'paused'\n ? html`<button @click=${(e: Event) => this.resumeWorkflow(workflow.id, e)}>Resume</button>`\n : ''}\n <button class=\"secondary\" @click=${(e: Event) => this.deleteWorkflow(workflow.id, e)}>\n Delete\n </button>\n </div>\n </div>\n `\n )}\n </div>\n `}\n `\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function route(page: string): "labeling-workflows" | "labeling-workflow-builder";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = route;
|
|
37
|
+
function route(page) {
|
|
38
|
+
switch (page) {
|
|
39
|
+
case 'labeling-workflows':
|
|
40
|
+
Promise.resolve().then(() => __importStar(require('./pages/labeling-workflow-list.js')));
|
|
41
|
+
return page;
|
|
42
|
+
case 'labeling-workflow-builder':
|
|
43
|
+
Promise.resolve().then(() => __importStar(require('./pages/labeling-workflow-builder.js')));
|
|
44
|
+
return page;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../client/route.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBAUC;AAVD,SAAwB,KAAK,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,oBAAoB;YACvB,kDAAO,mCAAmC,IAAC;YAC3C,OAAO,IAAI,CAAA;QAEb,KAAK,2BAA2B;YAC9B,kDAAO,sCAAsC,IAAC;YAC9C,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC","sourcesContent":["export default function route(page: string) {\n switch (page) {\n case 'labeling-workflows':\n import('./pages/labeling-workflow-list.js')\n return page\n\n case 'labeling-workflow-builder':\n import('./pages/labeling-workflow-builder.js')\n return page\n }\n}\n"]}
|