Skip to content

Commit e9996cb

Browse files
committed
chore: extract OutputVariables into separate file
1 parent ca43b4c commit e9996cb

File tree

3 files changed

+184
-185
lines changed

3 files changed

+184
-185
lines changed

lib/components/Output/Output.jsx

Lines changed: 1 addition & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
import React, { useMemo } from 'react';
22

33
import {
4-
CodeSnippetSkeleton,
54
Link,
65
InlineLoading,
7-
Tabs,
8-
TabList,
9-
Tab,
10-
TabPanels,
11-
TabPanel,
126
Tooltip
137
} from '@carbon/react';
148

@@ -20,12 +14,8 @@ import {
2014

2115
import classNames from 'classnames';
2216

23-
import { isObject, has } from 'min-dash';
24-
25-
import OutputEditor from './OutputEditor';
26-
27-
import { SCOPES } from '../../TaskExecution';
2817
import { Fill, Slot } from '../shared/SlotFill';
18+
import { OutputVariables } from './OutputVariables';
2919

3020
export const TASK_EXECUTION_STATUS_LABEL = {
3121
deploying: 'Deploying...',
@@ -178,109 +168,6 @@ function ResetButton() {
178168
} />;
179169
}
180170

181-
function OutputVariables({
182-
isTaskExecuting,
183-
output,
184-
element
185-
}) {
186-
187-
if (isTaskExecuting) {
188-
return <CodeSnippetSkeleton className="output__variables--skeleton" type="multi" />;
189-
}
190-
191-
if (!output) {
192-
return <div className="output__variables--empty">
193-
<div>
194-
Enter process variables, then click <span className="output__variables--empty-action">Test task</span> to see how they change once the task has executed.
195-
</div>
196-
</div>;
197-
}
198-
199-
if (output?.error) {
200-
return <OutputEditor
201-
value={ output?.error.response || 'No error details available' }
202-
/>;
203-
}
204-
205-
206-
return (<>
207-
<ProcessVariablesTab />
208-
<LocalVariablesTab />
209-
<IncidentTab />
210-
<Slot name="output" element={ element } output={ output } isTaskExecuting={ isTaskExecuting } RenderIn={ OutputTabs } />
211-
</>
212-
);
213-
}
214-
215-
const OutputTabs = ({ fills }) => {
216-
return (
217-
<Tabs>
218-
<TabList>
219-
{ fills.map((fill, index) => (
220-
<Tab key={ index }>{ fill.label }</Tab>
221-
)) }
222-
</TabList>
223-
<TabPanels>
224-
{ fills.map((fill, index) => (
225-
<TabPanel key={ index }>
226-
{ fill.content }
227-
</TabPanel>
228-
)) }
229-
</TabPanels>
230-
</Tabs>
231-
);
232-
};
233-
234-
const IncidentTab = () => (
235-
<Fill
236-
priority={ 300 }
237-
slot="output"
238-
getFill={ ({ output }) => {
239-
if (!output?.incident) {
240-
return;
241-
}
242-
243-
return {
244-
label: 'Incident',
245-
content: <IncidentDetails incident={ output.incident } />
246-
};
247-
} }
248-
/>
249-
);
250-
251-
const ProcessVariablesTab = () => (
252-
<Fill
253-
priority={ 200 }
254-
slot="output"
255-
getFill={ ({ output }) => {
256-
if (!output || (!output.success && !output.incident)) {
257-
return;
258-
}
259-
260-
return {
261-
label: 'Process Variables',
262-
content: <OutputEditor value={ JSON.stringify(pickVariables(output.variables, SCOPES.PROCESS), null, 2) } />
263-
};
264-
} }
265-
/>
266-
);
267-
268-
const LocalVariablesTab = () => (
269-
<Fill
270-
priority={ 100 }
271-
slot="output"
272-
getFill={ ({ output }) => {
273-
if (!output || (!output.success && !output.incident)) {
274-
return;
275-
}
276-
277-
return {
278-
label: 'Local Variables',
279-
content: <OutputEditor value={ JSON.stringify(pickVariables(output.variables, SCOPES.LOCAL), null, 2) } />
280-
};
281-
} }
282-
/>
283-
);
284171

285172
/**
286173
*
@@ -316,73 +203,3 @@ function ErrorBanner({
316203
</div>
317204
);
318205
}
319-
320-
function IncidentDetails({ incident }) {
321-
const {
322-
errorType,
323-
errorMessage,
324-
creationTime,
325-
...rest
326-
} = incident;
327-
328-
return (
329-
<div className="output__incident--details">
330-
<div>
331-
<span className="bold">Type: </span>
332-
{errorType}
333-
</div>
334-
<div>
335-
<span className="bold">Creation Time: </span>
336-
{new Date(creationTime).toLocaleString()}
337-
</div>
338-
<div>
339-
<pre>
340-
<span className="bold">Message: </span>
341-
{errorMessage}
342-
</pre>
343-
</div>
344-
345-
{ Object.entries(rest).map(([ key, value ]) => (
346-
<div key={ key }>
347-
<span className="bold">{capitalize(key)}:</span> {value}
348-
</div>
349-
)) }
350-
</div>
351-
);
352-
}
353-
354-
/**
355-
* Capitalize a string, adding spaces before capital letters.
356-
*
357-
* @example
358-
*
359-
* capitalize('fooBar'); // Foo Bar
360-
*
361-
* @param {string} string
362-
*
363-
* @returns {string}
364-
*/
365-
function capitalize(string) {
366-
return string.replace(/([A-Z])/g, ' $1').replace(/^./, (match) => match.toUpperCase());
367-
}
368-
369-
/**
370-
* Pick variables for a given scope. Variables in legacy format are ignored.
371-
*
372-
* @param {import('../../types').ElementOutputVariables} variables
373-
* @param {string} scope
374-
*
375-
* @returns {Object}
376-
*/
377-
export function pickVariables(variables, scope) {
378-
return Object.values(variables).reduce((acc, variable) => {
379-
380-
// Ignore variables in legacy formats
381-
// see https://github.com/camunda/task-testing/issues/12 and https://github.com/camunda/task-testing/issues/48 for legacy format
382-
if (isObject(variable) && has(variable, 'name') && scope === variable.scope) {
383-
acc[variable.name] = variable.value;
384-
}
385-
386-
return acc;
387-
}, {});
388-
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { CodeSnippetSkeleton, Tab, TabList, TabPanel, TabPanels, Tabs } from '@carbon/react';
2+
import { Fill, Slot } from '../shared/SlotFill';
3+
import OutputEditor from './OutputEditor';
4+
import { has, isObject } from 'min-dash';
5+
import { SCOPES } from '../../TaskExecution';
6+
7+
export function OutputVariables({
8+
isTaskExecuting,
9+
output,
10+
element
11+
}) {
12+
13+
if (isTaskExecuting) {
14+
return <CodeSnippetSkeleton className="output__variables--skeleton" type="multi" />;
15+
}
16+
17+
if (!output) {
18+
return <div className="output__variables--empty">
19+
<div>
20+
Enter process variables, then click <span className="output__variables--empty-action">Test task</span> to see how they change once the task has executed.
21+
</div>
22+
</div>;
23+
}
24+
25+
if (output?.error) {
26+
return <OutputEditor
27+
value={ output?.error.response || 'No error details available' }
28+
/>;
29+
}
30+
31+
32+
return (<>
33+
<ProcessVariablesTab />
34+
<LocalVariablesTab />
35+
<IncidentTab />
36+
<Slot name="output" element={ element } output={ output } isTaskExecuting={ isTaskExecuting } RenderIn={ OutputTabs } />
37+
</>
38+
);
39+
}
40+
41+
const OutputTabs = ({ fills }) => {
42+
return (
43+
<Tabs>
44+
<TabList>
45+
{ fills.map((fill, index) => (
46+
<Tab key={ index }>{ fill.label }</Tab>
47+
)) }
48+
</TabList>
49+
<TabPanels>
50+
{ fills.map((fill, index) => (
51+
<TabPanel key={ index }>
52+
{ fill.content }
53+
</TabPanel>
54+
)) }
55+
</TabPanels>
56+
</Tabs>
57+
);
58+
};
59+
60+
const IncidentTab = () => (
61+
<Fill
62+
priority={ 300 }
63+
slot="output"
64+
getFill={ ({ output }) => {
65+
if (!output?.incident) {
66+
return;
67+
}
68+
69+
return {
70+
label: 'Incident',
71+
content: <IncidentDetails incident={ output.incident } />
72+
};
73+
} }
74+
/>
75+
);
76+
77+
const ProcessVariablesTab = () => (
78+
<Fill
79+
priority={ 200 }
80+
slot="output"
81+
getFill={ ({ output }) => {
82+
if (!output || (!output.success && !output.incident)) {
83+
return;
84+
}
85+
86+
return {
87+
label: 'Process Variables',
88+
content: <OutputEditor value={ JSON.stringify(pickVariables(output.variables, SCOPES.PROCESS), null, 2) } />
89+
};
90+
} }
91+
/>
92+
);
93+
94+
const LocalVariablesTab = () => (
95+
<Fill
96+
priority={ 100 }
97+
slot="output"
98+
getFill={ ({ output }) => {
99+
if (!output || (!output.success && !output.incident)) {
100+
return;
101+
}
102+
103+
return {
104+
label: 'Local Variables',
105+
content: <OutputEditor value={ JSON.stringify(pickVariables(output.variables, SCOPES.LOCAL), null, 2) } />
106+
};
107+
} }
108+
/>
109+
);
110+
111+
112+
function IncidentDetails({ incident }) {
113+
const {
114+
errorType,
115+
errorMessage,
116+
creationTime,
117+
...rest
118+
} = incident;
119+
120+
return (
121+
<div className="output__incident--details">
122+
<div>
123+
<span className="bold">Type: </span>
124+
{errorType}
125+
</div>
126+
<div>
127+
<span className="bold">Creation Time: </span>
128+
{new Date(creationTime).toLocaleString()}
129+
</div>
130+
<div>
131+
<pre>
132+
<span className="bold">Message: </span>
133+
{errorMessage}
134+
</pre>
135+
</div>
136+
137+
{ Object.entries(rest).map(([ key, value ]) => (
138+
<div key={ key }>
139+
<span className="bold">{capitalize(key)}:</span> {value}
140+
</div>
141+
)) }
142+
</div>
143+
);
144+
}
145+
146+
147+
/**
148+
* Capitalize a string, adding spaces before capital letters.
149+
*
150+
* @example
151+
*
152+
* capitalize('fooBar'); // Foo Bar
153+
*
154+
* @param {string} string
155+
*
156+
* @returns {string}
157+
*/
158+
function capitalize(string) {
159+
return string.replace(/([A-Z])/g, ' $1').replace(/^./, (match) => match.toUpperCase());
160+
}
161+
162+
/**
163+
* Pick variables for a given scope. Variables in legacy format are ignored.
164+
*
165+
* @param {import('../../types').ElementOutputVariables} variables
166+
* @param {string} scope
167+
*
168+
* @returns {Object}
169+
*/
170+
export function pickVariables(variables, scope) {
171+
return Object.values(variables).reduce((acc, variable) => {
172+
173+
// Ignore variables in legacy formats
174+
// see https://github.com/camunda/task-testing/issues/12 and https://github.com/camunda/task-testing/issues/48 for legacy format
175+
if (isObject(variable) && has(variable, 'name') && scope === variable.scope) {
176+
acc[variable.name] = variable.value;
177+
}
178+
179+
return acc;
180+
}, {});
181+
}

0 commit comments

Comments
 (0)