@orchestrator-ui/orchestrator-ui-components 6.7.2 → 6.7.4
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/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +13 -13
- package/CHANGELOG.md +392 -379
- package/dist/index.d.ts +8339 -830
- package/dist/index.js +916 -561
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/src/components/WfoAgent/ExportButton/styles.ts +1 -1
- package/src/components/WfoAgent/ToolProgress/ToolProgress.tsx +16 -6
- package/src/components/WfoAgent/ToolProgress/styles.ts +2 -0
- package/src/components/WfoAgent/WfoAgent/WfoAgent.tsx +91 -87
- package/src/components/WfoAgent/WfoAgentChart/WfoAgentLineChart.tsx +60 -0
- package/src/components/WfoAgent/WfoAgentChart/WfoAgentPieChart.tsx +66 -0
- package/src/components/WfoAgent/WfoAgentChart/index.ts +2 -0
- package/src/components/WfoAgent/WfoAgentChart/styles.ts +6 -0
- package/src/components/WfoAgent/WfoAgentTable/WfoAgentTable.tsx +76 -0
- package/src/components/WfoAgent/WfoAgentTable/index.ts +1 -0
- package/src/components/WfoAgent/WfoAgentVisualization/WfoAgentVisualization.tsx +59 -0
- package/src/components/WfoAgent/WfoAgentVisualization/index.ts +1 -0
- package/src/components/WfoAgent/index.ts +4 -0
- package/src/components/WfoForms/UserInputForm.tsx +1 -0
- package/src/components/WfoForms/formFields/AcceptField.tsx +2 -2
- package/src/components/WfoForms/formFields/ListSelectField.tsx +1 -0
- package/src/components/WfoForms/formFields/deprecated/ImsNodeIdField.tsx +2 -2
- package/src/components/WfoForms/formFields/deprecated/ImsPortIdField.tsx +2 -2
- package/src/components/WfoForms/formFields/deprecated/VlanField.tsx +10 -10
- package/src/configuration/version.ts +1 -1
- package/src/hooks/usePathAutoComplete.ts +2 -2
- package/src/hooks/useSearch.ts +0 -1
- package/src/messages/en-GB.json +22 -2
- package/src/rtk/endpoints/search.ts +9 -8
- package/src/types/search.ts +27 -0
- package/src/utils/getEnvironmentVariables.ts +10 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orchestrator-ui/orchestrator-ui-components",
|
|
3
|
-
"version": "6.7.
|
|
3
|
+
"version": "6.7.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Library of UI Components used to display the workflow orchestrator frontend",
|
|
6
6
|
"author": {
|
|
@@ -35,9 +35,10 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@ag-ui/client": "0.0.39",
|
|
38
|
-
"@copilotkit/react-core": "
|
|
39
|
-
"@copilotkit/react-ui": "
|
|
40
|
-
"@copilotkit/runtime": "
|
|
38
|
+
"@copilotkit/react-core": "1.10.6",
|
|
39
|
+
"@copilotkit/react-ui": "1.10.6",
|
|
40
|
+
"@copilotkit/runtime": "1.10.6",
|
|
41
|
+
"@elastic/charts": "^64.1.0",
|
|
41
42
|
"@elastic/eui": "101.3.0",
|
|
42
43
|
"@emotion/css": "^11.11.2",
|
|
43
44
|
"@emotion/react": "^11.11.4",
|
|
@@ -47,13 +48,13 @@
|
|
|
47
48
|
"invariant": "^2.2.4",
|
|
48
49
|
"lodash": "^4.17.21",
|
|
49
50
|
"moment": "^2.29.4",
|
|
50
|
-
"moment-timezone": "^0.
|
|
51
|
+
"moment-timezone": "^0.5.32",
|
|
51
52
|
"next-auth": "^4.24.5",
|
|
52
53
|
"next-intl": "^3.26.5",
|
|
53
54
|
"next-query-params": "^5.0.0",
|
|
54
55
|
"object-hash": "^3.0.0",
|
|
55
56
|
"prism-themes": "^1.9.0",
|
|
56
|
-
"pydantic-forms": "^0.
|
|
57
|
+
"pydantic-forms": "^0.10.0",
|
|
57
58
|
"react-diff-view": "^3.2.0",
|
|
58
59
|
"react-draggable": "^4.4.6",
|
|
59
60
|
"react-redux": "^9.1.2",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
4
|
+
|
|
3
5
|
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
|
|
4
6
|
|
|
5
7
|
import { useWithOrchestratorTheme } from '@/hooks';
|
|
@@ -43,6 +45,7 @@ export const ToolProgress = ({
|
|
|
43
45
|
result,
|
|
44
46
|
}: ToolProgressProps) => {
|
|
45
47
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
48
|
+
const tPage = useTranslations('agent.page');
|
|
46
49
|
|
|
47
50
|
const {
|
|
48
51
|
containerStyle,
|
|
@@ -56,6 +59,13 @@ export const ToolProgress = ({
|
|
|
56
59
|
|
|
57
60
|
const { theme } = useOrchestratorTheme();
|
|
58
61
|
|
|
62
|
+
const getToolLabel = (toolName: string) => {
|
|
63
|
+
const toolKey = `tools.${toolName}`;
|
|
64
|
+
const translated = tPage(toolKey);
|
|
65
|
+
const fullKey = `agent.page.${toolKey}`;
|
|
66
|
+
return translated === fullKey ? toolName : translated;
|
|
67
|
+
};
|
|
68
|
+
|
|
59
69
|
const renderStatus = () => {
|
|
60
70
|
if (status === 'complete') {
|
|
61
71
|
return (
|
|
@@ -82,13 +92,13 @@ export const ToolProgress = ({
|
|
|
82
92
|
};
|
|
83
93
|
|
|
84
94
|
const DisplayComponent = TOOL_DISPLAY_COMPONENTS[name];
|
|
85
|
-
const
|
|
95
|
+
const hasContent = DisplayComponent && (args || result);
|
|
86
96
|
|
|
87
97
|
return (
|
|
88
98
|
<div css={containerStyle}>
|
|
89
99
|
<div
|
|
90
|
-
css={
|
|
91
|
-
onClick={() =>
|
|
100
|
+
css={hasContent && containerClickableStyle}
|
|
101
|
+
onClick={() => hasContent && setIsExpanded(!isExpanded)}
|
|
92
102
|
>
|
|
93
103
|
<EuiFlexGroup
|
|
94
104
|
gutterSize="m"
|
|
@@ -101,7 +111,7 @@ export const ToolProgress = ({
|
|
|
101
111
|
</div>
|
|
102
112
|
</EuiFlexItem>
|
|
103
113
|
<EuiFlexItem grow={true}>
|
|
104
|
-
<span css={nameStyle}>{name}</span>
|
|
114
|
+
<span css={nameStyle}>{getToolLabel(name)}</span>
|
|
105
115
|
</EuiFlexItem>
|
|
106
116
|
<EuiFlexItem
|
|
107
117
|
grow={false}
|
|
@@ -113,7 +123,7 @@ export const ToolProgress = ({
|
|
|
113
123
|
grow={false}
|
|
114
124
|
style={{ minWidth: `${iconSize}px` }}
|
|
115
125
|
>
|
|
116
|
-
{
|
|
126
|
+
{hasContent &&
|
|
117
127
|
(isExpanded ? (
|
|
118
128
|
<WfoChevronUp
|
|
119
129
|
width={iconSize}
|
|
@@ -128,7 +138,7 @@ export const ToolProgress = ({
|
|
|
128
138
|
</EuiFlexItem>
|
|
129
139
|
</EuiFlexGroup>
|
|
130
140
|
</div>
|
|
131
|
-
{
|
|
141
|
+
{hasContent && isExpanded && (
|
|
132
142
|
<div css={expandedContentStyle}>
|
|
133
143
|
<DisplayComponent parameters={args} result={result} />
|
|
134
144
|
</div>
|
|
@@ -8,6 +8,8 @@ export const getToolProgressStyles = ({ theme }: WfoTheme) => {
|
|
|
8
8
|
borderRadius: theme.border.radius.medium,
|
|
9
9
|
backgroundColor: theme.colors.emptyShade,
|
|
10
10
|
transition: `all ${theme.animation.normal} ease`,
|
|
11
|
+
maxWidth: '50%',
|
|
12
|
+
marginRight: 'auto',
|
|
11
13
|
});
|
|
12
14
|
|
|
13
15
|
const containerClickableStyle = css({
|
|
@@ -4,59 +4,68 @@ import { useTranslations } from 'next-intl';
|
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
CatchAllActionRenderProps,
|
|
7
|
-
useCoAgent,
|
|
8
|
-
useCoAgentStateRender,
|
|
9
7
|
useCopilotAction,
|
|
8
|
+
useRenderToolCall,
|
|
10
9
|
} from '@copilotkit/react-core';
|
|
11
|
-
import {
|
|
12
|
-
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui';
|
|
10
|
+
import { CopilotChat } from '@copilotkit/react-ui';
|
|
13
11
|
|
|
14
12
|
import { WfoAvailabilityCheck } from '@/components/WfoAvailabilityCheck';
|
|
15
|
-
import {
|
|
13
|
+
import { getPageTemplateStyles } from '@/components/WfoPageTemplate/WfoPageTemplate/styles';
|
|
14
|
+
import { useWithOrchestratorTheme } from '@/hooks';
|
|
16
15
|
import { useAgentAvailability } from '@/hooks/useBackendAvailability';
|
|
17
|
-
import {
|
|
16
|
+
import { AggregationResultsData } from '@/types';
|
|
18
17
|
|
|
19
18
|
import { ExportButton, ExportData } from '../ExportButton';
|
|
20
19
|
import { ToolProgress } from '../ToolProgress';
|
|
21
|
-
|
|
22
|
-
type SearchResultsData = {
|
|
23
|
-
action: string;
|
|
24
|
-
query_id: string;
|
|
25
|
-
results_url: string;
|
|
26
|
-
total_count: number;
|
|
27
|
-
message: string;
|
|
28
|
-
results: SearchResult[];
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
type SearchState = {
|
|
32
|
-
run_id: string | null;
|
|
33
|
-
query_id: string | null;
|
|
34
|
-
parameters: AnySearchParameters | null;
|
|
35
|
-
results_data: SearchResultsData | null;
|
|
36
|
-
export_data: ExportData | null;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const initialState: SearchState = {
|
|
40
|
-
run_id: null,
|
|
41
|
-
query_id: null,
|
|
42
|
-
parameters: null,
|
|
43
|
-
results_data: null,
|
|
44
|
-
export_data: null,
|
|
45
|
-
};
|
|
20
|
+
import { WfoAgentVisualization } from '../WfoAgentVisualization';
|
|
46
21
|
|
|
47
22
|
export function WfoAgent() {
|
|
48
|
-
const t = useTranslations('agent');
|
|
49
23
|
const tPage = useTranslations('agent.page');
|
|
50
24
|
|
|
25
|
+
const { NAVIGATION_HEIGHT } = useWithOrchestratorTheme(
|
|
26
|
+
getPageTemplateStyles,
|
|
27
|
+
);
|
|
51
28
|
const agentAvailability = useAgentAvailability();
|
|
52
29
|
|
|
53
|
-
|
|
54
|
-
name: '
|
|
55
|
-
|
|
30
|
+
useRenderToolCall({
|
|
31
|
+
name: 'run_search',
|
|
32
|
+
render: ({ result }) => {
|
|
33
|
+
if (!result) {
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
return (
|
|
37
|
+
<WfoAgentVisualization
|
|
38
|
+
aggregationData={result as AggregationResultsData}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
useRenderToolCall({
|
|
45
|
+
name: 'run_aggregation',
|
|
46
|
+
render: ({ result }) => {
|
|
47
|
+
if (!result) {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
return (
|
|
51
|
+
<WfoAgentVisualization
|
|
52
|
+
aggregationData={result as AggregationResultsData}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useRenderToolCall({
|
|
59
|
+
name: 'prepare_export',
|
|
60
|
+
render: ({ result }) => {
|
|
61
|
+
if (!result) {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
return <ExportButton exportData={result as ExportData} />;
|
|
65
|
+
},
|
|
56
66
|
});
|
|
57
|
-
const { results_data } = state;
|
|
58
67
|
|
|
59
|
-
// Automatically render all tool calls
|
|
68
|
+
// Automatically render all other tool calls
|
|
60
69
|
useCopilotAction({
|
|
61
70
|
name: '*',
|
|
62
71
|
render: ({
|
|
@@ -76,61 +85,56 @@ export function WfoAgent() {
|
|
|
76
85
|
},
|
|
77
86
|
});
|
|
78
87
|
|
|
79
|
-
// Render export button from state
|
|
80
|
-
useCoAgentStateRender<SearchState>({
|
|
81
|
-
name: 'query_agent',
|
|
82
|
-
render: ({ state }) => {
|
|
83
|
-
if (!state?.export_data || state.export_data.action !== 'export') {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
return <ExportButton exportData={state.export_data} />;
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
|
|
90
88
|
return (
|
|
91
89
|
<WfoAvailabilityCheck
|
|
92
90
|
featureType="agent"
|
|
93
91
|
availability={agentAvailability}
|
|
94
92
|
>
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
93
|
+
<div style={{ height: `calc(90vh - ${NAVIGATION_HEIGHT}px)` }}>
|
|
94
|
+
<style>{`
|
|
95
|
+
.copilotKitChat {
|
|
96
|
+
height: 100%;
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
}
|
|
100
|
+
`}</style>
|
|
101
|
+
<CopilotChat
|
|
102
|
+
labels={{
|
|
103
|
+
title: tPage('copilot.title'),
|
|
104
|
+
initial: tPage('copilot.initial'),
|
|
105
|
+
}}
|
|
106
|
+
suggestions={[
|
|
107
|
+
{
|
|
108
|
+
title: tPage('suggestions.findActiveSubscriptions'),
|
|
109
|
+
message: tPage(
|
|
110
|
+
'suggestions.findActiveSubscriptions',
|
|
111
|
+
),
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
title: tPage('suggestions.showTerminatedWorkflows'),
|
|
115
|
+
message: tPage(
|
|
116
|
+
'suggestions.showTerminatedWorkflows',
|
|
117
|
+
),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
title: tPage(
|
|
121
|
+
'suggestions.listAllSubscriptionsAndExport',
|
|
122
|
+
),
|
|
123
|
+
message: tPage(
|
|
124
|
+
'suggestions.listAllSubscriptionsAndExport',
|
|
125
|
+
),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
title: tPage(
|
|
129
|
+
'suggestions.showActiveSubscriptionsPerMonth',
|
|
130
|
+
),
|
|
131
|
+
message: tPage(
|
|
132
|
+
'suggestions.showActiveSubscriptionsPerMonth',
|
|
133
|
+
),
|
|
134
|
+
},
|
|
135
|
+
]}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
134
138
|
</WfoAvailabilityCheck>
|
|
135
139
|
);
|
|
136
140
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Axis,
|
|
5
|
+
Chart,
|
|
6
|
+
DARK_THEME,
|
|
7
|
+
LIGHT_THEME,
|
|
8
|
+
LineSeries,
|
|
9
|
+
Position,
|
|
10
|
+
Settings,
|
|
11
|
+
} from '@elastic/charts';
|
|
12
|
+
|
|
13
|
+
import { useOrchestratorTheme } from '@/hooks';
|
|
14
|
+
import { AggregationResultsData } from '@/types';
|
|
15
|
+
|
|
16
|
+
export type WfoAgentLineChartProps = {
|
|
17
|
+
aggregationData: AggregationResultsData;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function WfoAgentLineChart({ aggregationData }: WfoAgentLineChartProps) {
|
|
21
|
+
const { results } = aggregationData;
|
|
22
|
+
const { isDarkThemeActive, multiplyByBaseUnit } = useOrchestratorTheme();
|
|
23
|
+
const chartBaseTheme = isDarkThemeActive ? DARK_THEME : LIGHT_THEME;
|
|
24
|
+
|
|
25
|
+
const firstResult = results[0];
|
|
26
|
+
const groupKeys = Object.keys(firstResult.group_values);
|
|
27
|
+
const aggKeys = Object.keys(firstResult.aggregations);
|
|
28
|
+
|
|
29
|
+
const xKey = groupKeys[0];
|
|
30
|
+
const chartData = results.map((result, index) => ({
|
|
31
|
+
x: index,
|
|
32
|
+
xLabel: result.group_values[xKey],
|
|
33
|
+
...result.aggregations,
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Chart size={{ height: multiplyByBaseUnit(30) }}>
|
|
38
|
+
<Settings showLegend baseTheme={chartBaseTheme} />
|
|
39
|
+
<Axis
|
|
40
|
+
id="bottom"
|
|
41
|
+
position={Position.Bottom}
|
|
42
|
+
title={xKey.replace(/_/g, ' ')}
|
|
43
|
+
tickFormat={(d) => chartData[d]?.xLabel?.split(' ')[0] || d}
|
|
44
|
+
/>
|
|
45
|
+
<Axis id="left" position={Position.Left} title="Count" />
|
|
46
|
+
{aggKeys.map((aggKey) => (
|
|
47
|
+
<LineSeries
|
|
48
|
+
key={aggKey}
|
|
49
|
+
id={aggKey}
|
|
50
|
+
name={aggKey
|
|
51
|
+
.replace(/_/g, ' ')
|
|
52
|
+
.replace(/\b\w/g, (l) => l.toUpperCase())}
|
|
53
|
+
data={chartData}
|
|
54
|
+
xAccessor="x"
|
|
55
|
+
yAccessors={[aggKey]}
|
|
56
|
+
/>
|
|
57
|
+
))}
|
|
58
|
+
</Chart>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Chart,
|
|
5
|
+
DARK_THEME,
|
|
6
|
+
LIGHT_THEME,
|
|
7
|
+
Partition,
|
|
8
|
+
PartitionLayout,
|
|
9
|
+
Position,
|
|
10
|
+
Settings,
|
|
11
|
+
} from '@elastic/charts';
|
|
12
|
+
|
|
13
|
+
import { AggregationResultsData } from '@/types';
|
|
14
|
+
|
|
15
|
+
import { useOrchestratorTheme } from '../../../hooks';
|
|
16
|
+
import { containerStyle } from './styles';
|
|
17
|
+
|
|
18
|
+
export type WfoAgentPieChartProps = {
|
|
19
|
+
aggregationData: AggregationResultsData;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function WfoAgentPieChart({ aggregationData }: WfoAgentPieChartProps) {
|
|
23
|
+
const { results } = aggregationData;
|
|
24
|
+
const { isDarkThemeActive, multiplyByBaseUnit } = useOrchestratorTheme();
|
|
25
|
+
const chartBaseTheme = isDarkThemeActive ? DARK_THEME : LIGHT_THEME;
|
|
26
|
+
|
|
27
|
+
const firstResult = results[0];
|
|
28
|
+
const groupKeys = Object.keys(firstResult.group_values);
|
|
29
|
+
const aggKeys = Object.keys(firstResult.aggregations);
|
|
30
|
+
|
|
31
|
+
// Use the first group key for labels and first aggregation for values
|
|
32
|
+
const groupKey = groupKeys[0];
|
|
33
|
+
const aggKey = aggKeys[0];
|
|
34
|
+
const pieData = results.map((result) => ({
|
|
35
|
+
label: result.group_values[groupKey],
|
|
36
|
+
value: result.aggregations[aggKey],
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div css={containerStyle}>
|
|
41
|
+
<Chart size={{ height: multiplyByBaseUnit(25) }}>
|
|
42
|
+
<Settings
|
|
43
|
+
showLegend
|
|
44
|
+
legendPosition={Position.Right}
|
|
45
|
+
baseTheme={chartBaseTheme}
|
|
46
|
+
/>
|
|
47
|
+
<Partition
|
|
48
|
+
id="pieByPR"
|
|
49
|
+
data={pieData}
|
|
50
|
+
layout={PartitionLayout.sunburst}
|
|
51
|
+
valueAccessor={(d) => d.value}
|
|
52
|
+
layers={[
|
|
53
|
+
{
|
|
54
|
+
groupByRollup: (d: (typeof pieData)[0]) => d.label,
|
|
55
|
+
shape: {
|
|
56
|
+
fillColor: (_, sortIndex) =>
|
|
57
|
+
chartBaseTheme.colors.vizColors![sortIndex],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
]}
|
|
61
|
+
clockwiseSectors={false}
|
|
62
|
+
/>
|
|
63
|
+
</Chart>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
|
4
|
+
|
|
5
|
+
import { AggregationResult, AggregationResultsData } from '@/types';
|
|
6
|
+
|
|
7
|
+
export type WfoAgentTableProps = {
|
|
8
|
+
aggregationData: AggregationResultsData;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const formatColumnName = (key: string) =>
|
|
12
|
+
key.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase());
|
|
13
|
+
|
|
14
|
+
export function WfoAgentTable({ aggregationData }: WfoAgentTableProps) {
|
|
15
|
+
const { results } = aggregationData;
|
|
16
|
+
const [pageIndex, setPageIndex] = React.useState(0);
|
|
17
|
+
const [pageSize, setPageSize] = React.useState(5);
|
|
18
|
+
|
|
19
|
+
const columns: EuiBasicTableColumn<AggregationResult>[] =
|
|
20
|
+
React.useMemo(() => {
|
|
21
|
+
if (results.length === 0) return [];
|
|
22
|
+
|
|
23
|
+
const firstResult = results[0];
|
|
24
|
+
const groupKeys = Object.keys(firstResult.group_values);
|
|
25
|
+
const aggKeys = Object.keys(firstResult.aggregations);
|
|
26
|
+
|
|
27
|
+
const groupColumns: EuiBasicTableColumn<AggregationResult>[] =
|
|
28
|
+
groupKeys.map((key) => ({
|
|
29
|
+
field: 'group_values' as keyof AggregationResult,
|
|
30
|
+
name: formatColumnName(key),
|
|
31
|
+
render: (_: unknown, record: AggregationResult) =>
|
|
32
|
+
record.group_values[key],
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
const aggColumns: EuiBasicTableColumn<AggregationResult>[] =
|
|
36
|
+
aggKeys.map((key) => ({
|
|
37
|
+
field: 'aggregations' as keyof AggregationResult,
|
|
38
|
+
name: formatColumnName(key),
|
|
39
|
+
render: (_: unknown, record: AggregationResult) =>
|
|
40
|
+
record.aggregations[key],
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
return [...groupColumns, ...aggColumns];
|
|
44
|
+
}, [results]);
|
|
45
|
+
|
|
46
|
+
const startIndex = pageIndex * pageSize;
|
|
47
|
+
const paginatedItems = results.slice(startIndex, startIndex + pageSize);
|
|
48
|
+
|
|
49
|
+
const pagination = {
|
|
50
|
+
pageIndex,
|
|
51
|
+
pageSize,
|
|
52
|
+
totalItemCount: results.length,
|
|
53
|
+
pageSizeOptions: [5, 10, 25, 50],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const onTableChange = ({
|
|
57
|
+
page,
|
|
58
|
+
}: {
|
|
59
|
+
page?: { index: number; size: number };
|
|
60
|
+
}) => {
|
|
61
|
+
if (page) {
|
|
62
|
+
setPageIndex(page.index);
|
|
63
|
+
setPageSize(page.size);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<EuiBasicTable
|
|
69
|
+
items={paginatedItems}
|
|
70
|
+
columns={columns}
|
|
71
|
+
tableLayout="auto"
|
|
72
|
+
pagination={pagination}
|
|
73
|
+
onChange={onTableChange}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './WfoAgentTable';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from 'next-intl';
|
|
4
|
+
|
|
5
|
+
import { EuiText } from '@elastic/eui';
|
|
6
|
+
|
|
7
|
+
import { AggregationResultsData, VisualizationType } from '@/types';
|
|
8
|
+
|
|
9
|
+
import { WfoAgentLineChart } from '../WfoAgentChart/WfoAgentLineChart';
|
|
10
|
+
import { WfoAgentPieChart } from '../WfoAgentChart/WfoAgentPieChart';
|
|
11
|
+
import { WfoAgentTable } from '../WfoAgentTable';
|
|
12
|
+
|
|
13
|
+
export type WfoAgentVisualizationProps = {
|
|
14
|
+
aggregationData: AggregationResultsData;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function WfoAgentVisualization({
|
|
18
|
+
aggregationData,
|
|
19
|
+
}: WfoAgentVisualizationProps) {
|
|
20
|
+
const { visualization_type, results } = aggregationData;
|
|
21
|
+
const t = useTranslations('agent.page.visualization');
|
|
22
|
+
|
|
23
|
+
if (!results || results.length === 0) {
|
|
24
|
+
return (
|
|
25
|
+
<EuiText size="s">
|
|
26
|
+
<p>{t('noDataAvailable')}</p>
|
|
27
|
+
</EuiText>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// For charts (pie/line), validate data structure
|
|
32
|
+
const visualizationType = visualization_type?.type;
|
|
33
|
+
if (
|
|
34
|
+
visualizationType === VisualizationType.PIE ||
|
|
35
|
+
visualizationType === VisualizationType.LINE
|
|
36
|
+
) {
|
|
37
|
+
const firstResult = results[0];
|
|
38
|
+
const groupKeys = Object.keys(firstResult.group_values);
|
|
39
|
+
const aggKeys = Object.keys(firstResult.aggregations);
|
|
40
|
+
|
|
41
|
+
if (groupKeys.length === 0 || aggKeys.length === 0) {
|
|
42
|
+
return (
|
|
43
|
+
<EuiText size="s">
|
|
44
|
+
<p>{t('invalidDataStructure')}</p>
|
|
45
|
+
</EuiText>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
switch (visualizationType) {
|
|
51
|
+
case VisualizationType.PIE:
|
|
52
|
+
return <WfoAgentPieChart aggregationData={aggregationData} />;
|
|
53
|
+
case VisualizationType.LINE:
|
|
54
|
+
return <WfoAgentLineChart aggregationData={aggregationData} />;
|
|
55
|
+
case VisualizationType.TABLE:
|
|
56
|
+
default:
|
|
57
|
+
return <WfoAgentTable aggregationData={aggregationData} />;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './WfoAgentVisualization';
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* limitations under the License.
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
|
+
|
|
15
16
|
/* NOTE: This component is only needed to avoid the circular import that started to be a problem
|
|
16
17
|
after the upgrade to react-script 5.0. The original SelectField would import itself to handle the list:
|
|
17
18
|
that seems to be impossible with the new webpack.
|
|
@@ -80,8 +80,8 @@ function ImsNodeId({
|
|
|
80
80
|
isLoading && locationCode
|
|
81
81
|
? t('widgets.node_select.nodes_loading')
|
|
82
82
|
: nodes.length
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
? t('widgets.node_select.select_node')
|
|
84
|
+
: t('forms.widgets.node_select.no_nodes_placeholder');
|
|
85
85
|
|
|
86
86
|
const imsNodeIdLabelLookup =
|
|
87
87
|
nodes?.reduce<{ [index: string]: string }>(function (mapping, node) {
|