Skip to content

Commit 85d77ab

Browse files
committed
WIP refactor
1 parent 35f315f commit 85d77ab

File tree

11 files changed

+923
-725
lines changed

11 files changed

+923
-725
lines changed

lib/ExecutionLogModel.js

Lines changed: 728 additions & 0 deletions
Large diffs are not rendered by default.

lib/TaskExecution.js

Lines changed: 27 additions & 413 deletions
Large diffs are not rendered by default.

lib/components/Input/InputEditor.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import theme from '../shared/CodeMirrorTheme';
1717

1818
import { getAutocompletionExtensions } from '../../utils/autocompletion';
1919

20-
import { SCOPES } from '../../TaskExecution';
20+
import { SCOPES } from '../../utils/variables';
2121

2222
const fromPropAnnotation = Annotation.define();
2323

lib/components/Output/ExecutionLog.jsx

Lines changed: 21 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
/**
2+
* ExecutionLog — pure rendering component for the execution timeline.
3+
*
4+
* All log state management, entry merge semantics, display projection,
5+
* and item helper logic live in {@link ../../ExecutionLogModel.js}.
6+
* This file is exclusively concerned with rendering.
7+
*/
8+
19
import React, { useState } from 'react';
210

311
import {
@@ -12,206 +20,17 @@ import { Link } from '@carbon/react';
1220

1321
import OutputEditor from './OutputEditor';
1422

15-
const STATUS_LABELS = {
16-
deploying: 'Process deployed',
17-
'starting-instance': 'Process instance created',
18-
executing: null,
19-
completed: 'Process instance completed',
20-
incident: 'Incident',
21-
canceled: 'Test canceled'
22-
};
23-
24-
const WAITING_ITEM_LABELS = {
25-
'job-active': 'Job is active',
26-
'job-completed': 'Job completed',
27-
'job-inactive': 'Job waiting to be activated',
28-
'user-task-form': 'User task waiting for completion',
29-
'message-subscription': 'Waiting for message',
30-
'boundary-event': 'Boundary event triggered',
31-
'event-sub-process': 'Event sub-process triggered'
32-
};
33-
34-
const WAITING_ITEM_FINISHED_LABELS = {
35-
'user-task-form': 'User task completed'
36-
};
37-
38-
/**
39-
* Get display label for a waiting item.
40-
*
41-
* @param {import('../../types').WaitingItem} item
42-
* @param {boolean} [isFinished]
43-
* @returns {string}
44-
*/
45-
function getWaitingItemLabel(item, isFinished) {
46-
if (isFinished && WAITING_ITEM_FINISHED_LABELS[item.type]) {
47-
return WAITING_ITEM_FINISHED_LABELS[item.type];
48-
}
49-
50-
return WAITING_ITEM_LABELS[item.type] || item.type;
51-
}
52-
53-
/**
54-
* Get details for a waiting item to display in expanded view.
55-
*
56-
* @param {import('../../types').WaitingItem} item
57-
* @returns {{ label: string; value: string }[]}
58-
*/
59-
function getWaitingItemDetails(item) {
60-
if (!item.data) {
61-
return [];
62-
}
63-
64-
// Handle boundary events and event sub-processes
65-
if (item.type === 'boundary-event' || item.type === 'event-sub-process') {
66-
const details = [];
67-
68-
if (item.data.elementId) {
69-
details.push({ label: 'Element', value: item.data.elementId });
70-
}
71-
72-
if (item.data.elementName) {
73-
details.push({ label: 'Name', value: item.data.elementName });
74-
}
75-
76-
if (item.data.state) {
77-
details.push({ label: 'State', value: item.data.state });
78-
}
79-
80-
if (item.data.startDate) {
81-
details.push({ label: 'Started', value: new Date(item.data.startDate).toLocaleTimeString() });
82-
}
83-
84-
if (item.data.elementInstanceKey) {
85-
details.push({ label: 'Instance Key', value: item.data.elementInstanceKey });
86-
}
87-
88-
return details;
89-
}
90-
91-
// Handle job items
92-
if (!isJobItem(item)) {
93-
return [];
94-
}
95-
96-
const details = [];
97-
98-
if (item.data.type) {
99-
details.push({ label: 'Type', value: item.data.type });
100-
}
101-
102-
if (item.data.elementId) {
103-
details.push({ label: 'Element', value: item.data.elementId });
104-
}
105-
106-
const listenerLabel = getExecutionListenerLabel(item.data);
107-
if (listenerLabel) {
108-
details.push({ label: 'Kind', value: listenerLabel });
109-
}
110-
111-
if (item.data.state) {
112-
details.push({ label: 'State', value: item.data.state });
113-
}
114-
115-
if (item.data.jobKey) {
116-
details.push({ label: 'Job Key', value: item.data.jobKey });
117-
}
118-
119-
return details;
120-
}
121-
122-
/**
123-
* Get execution listener label if the job is an execution listener.
124-
*
125-
* @param {Object} jobData
126-
* @returns {string|null}
127-
*/
128-
function getExecutionListenerLabel(jobData) {
129-
if (!jobData || jobData.kind !== 'EXECUTION_LISTENER') {
130-
return null;
131-
}
132-
133-
const eventType = jobData.listenerEventType;
134-
135-
if (eventType === 'START') {
136-
return 'start execution listener';
137-
}
138-
139-
if (eventType === 'END') {
140-
return 'end execution listener';
141-
}
142-
143-
return 'execution listener';
144-
}
145-
146-
/**
147-
* @param {import('../../types').WaitingItem} item
148-
* @returns {boolean}
149-
*/
150-
function isJobItem(item) {
151-
return item.type === 'job-active'
152-
|| item.type === 'job-completed'
153-
|| item.type === 'job-inactive';
154-
}
155-
156-
/**
157-
* Determine if a waiting item is still pending (should show blue dot).
158-
* Completed/triggered items show green.
159-
*
160-
* @param {import('../../types').WaitingItem} item
161-
* @returns {boolean}
162-
*/
163-
function isPendingItem(item) {
164-
switch (item.type) {
165-
case 'job-active':
166-
case 'job-inactive':
167-
case 'user-task-form':
168-
case 'message-subscription':
169-
return true;
170-
default:
171-
return false;
172-
}
173-
}
174-
175-
/**
176-
* Get badge texts for waiting items.
177-
*
178-
* @param {import('../../types').WaitingItem} item
179-
* @returns {{ text: string, variant?: string }[]}
180-
*/
181-
function getWaitingItemBadges(item) {
182-
const badges = [];
183-
184-
// Execution listener start/end badge
185-
if (isJobItem(item) && item.data?.kind === 'EXECUTION_LISTENER' && item.data.listenerEventType) {
186-
badges.push({
187-
text: item.data.listenerEventType === 'START' ? 'start' : 'end',
188-
variant: item.data.listenerEventType === 'START' ? 'start' : 'end'
189-
});
190-
}
191-
192-
// Job type badge
193-
if (isJobItem(item) && item.data?.type) {
194-
badges.push({ text: item.data.type });
195-
}
196-
197-
// Boundary event or event sub-process badge - show element name or ID
198-
if ((item.type === 'boundary-event' || item.type === 'event-sub-process') && item.data) {
199-
const label = item.data.elementName || item.data.elementId;
200-
if (label) badges.push({ text: label });
201-
}
202-
203-
return badges;
204-
}
205-
206-
/**
207-
* Format a timestamp as a human-readable time string.
208-
*
209-
* @param {number} timestamp
210-
* @returns {string}
211-
*/
212-
function formatTime(timestamp) {
213-
return new Date(timestamp).toLocaleTimeString();
214-
}
23+
import {
24+
STATUS_LABELS,
25+
getDisplayEntries,
26+
getWaitingItemLabel,
27+
getWaitingItemDetails,
28+
getWaitingItemBadges,
29+
isPendingItem,
30+
formatTime,
31+
formatElementType,
32+
isFinished as checkIsFinished
33+
} from '../../ExecutionLogModel';
21534

21635
/**
21736
* Renders an execution log that builds up during task execution.
@@ -232,20 +51,8 @@ export function ExecutionLog({ entries, tasklistBaseUrl, currentOperateUrl, onSe
23251
}
23352

23453
const lastEntry = entries[entries.length - 1];
235-
236-
// Check if execution has finished (completed, incident, or canceled)
237-
const isFinished = entries.some(
238-
e => e.type === 'status' && (e.status === 'completed' || e.status === 'incident' || e.status === 'canceled')
239-
);
240-
241-
// Filter out 'executing' status once finished - it's just a temporary placeholder
242-
// During execution, move 'executing' to the end so it's always last
243-
const displayEntries = isFinished
244-
? entries.filter(e => !(e.type === 'status' && e.status === 'executing'))
245-
: [
246-
...entries.filter(e => !(e.type === 'status' && e.status === 'executing')),
247-
...entries.filter(e => e.type === 'status' && e.status === 'executing')
248-
];
54+
const isFinished = checkIsFinished(entries);
55+
const displayEntries = getDisplayEntries(entries);
24956

25057
return (
25158
<div className="execution-log">
@@ -355,19 +162,6 @@ function ChildElement({ child }) {
355162
);
356163
}
357164

358-
/**
359-
* Format an element type for display.
360-
*
361-
* @param {string} type
362-
* @returns {string}
363-
*/
364-
function formatElementType(type) {
365-
return (type || '')
366-
.toLowerCase()
367-
.replace(/_/g, ' ')
368-
.replace(/\b\w/g, c => c.toUpperCase());
369-
}
370-
371165
function WaitingEntry({ entry, isLast, isFinished, onSelectElement }) {
372166
if (!entry.items?.length) {
373167
return null;

lib/components/Output/Output.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { OutputVariables, pickVariables } from './OutputVariables';
2121
import OutputEditor from './OutputEditor';
2222
import { ExecutionLog } from './ExecutionLog';
2323
import { PluginContext } from '../shared/plugins';
24-
import { SCOPES } from '../../TaskExecution';
24+
import { SCOPES } from '../../utils/variables';
2525

2626
export const TASK_EXECUTION_STATUS_LABEL = {
2727
deploying: 'Deploying...',

0 commit comments

Comments
 (0)