@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.
Files changed (34) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +13 -13
  4. package/CHANGELOG.md +392 -379
  5. package/dist/index.d.ts +8339 -830
  6. package/dist/index.js +916 -561
  7. package/dist/index.js.map +1 -1
  8. package/package.json +7 -6
  9. package/src/components/WfoAgent/ExportButton/styles.ts +1 -1
  10. package/src/components/WfoAgent/ToolProgress/ToolProgress.tsx +16 -6
  11. package/src/components/WfoAgent/ToolProgress/styles.ts +2 -0
  12. package/src/components/WfoAgent/WfoAgent/WfoAgent.tsx +91 -87
  13. package/src/components/WfoAgent/WfoAgentChart/WfoAgentLineChart.tsx +60 -0
  14. package/src/components/WfoAgent/WfoAgentChart/WfoAgentPieChart.tsx +66 -0
  15. package/src/components/WfoAgent/WfoAgentChart/index.ts +2 -0
  16. package/src/components/WfoAgent/WfoAgentChart/styles.ts +6 -0
  17. package/src/components/WfoAgent/WfoAgentTable/WfoAgentTable.tsx +76 -0
  18. package/src/components/WfoAgent/WfoAgentTable/index.ts +1 -0
  19. package/src/components/WfoAgent/WfoAgentVisualization/WfoAgentVisualization.tsx +59 -0
  20. package/src/components/WfoAgent/WfoAgentVisualization/index.ts +1 -0
  21. package/src/components/WfoAgent/index.ts +4 -0
  22. package/src/components/WfoForms/UserInputForm.tsx +1 -0
  23. package/src/components/WfoForms/formFields/AcceptField.tsx +2 -2
  24. package/src/components/WfoForms/formFields/ListSelectField.tsx +1 -0
  25. package/src/components/WfoForms/formFields/deprecated/ImsNodeIdField.tsx +2 -2
  26. package/src/components/WfoForms/formFields/deprecated/ImsPortIdField.tsx +2 -2
  27. package/src/components/WfoForms/formFields/deprecated/VlanField.tsx +10 -10
  28. package/src/configuration/version.ts +1 -1
  29. package/src/hooks/usePathAutoComplete.ts +2 -2
  30. package/src/hooks/useSearch.ts +0 -1
  31. package/src/messages/en-GB.json +22 -2
  32. package/src/rtk/endpoints/search.ts +9 -8
  33. package/src/types/search.ts +27 -0
  34. 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.2",
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": "^1.3.18",
39
- "@copilotkit/react-ui": "^1.3.18",
40
- "@copilotkit/runtime": "^1.3.18",
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.6.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.9.4",
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",
@@ -6,7 +6,7 @@ export const getExportButtonStyles = ({ theme }: WfoTheme) => {
6
6
  const containerStyle = css({
7
7
  marginTop: theme.size.xl,
8
8
  marginBottom: theme.size.xl,
9
- width: '100%',
9
+ width: '50%',
10
10
  });
11
11
 
12
12
  const buttonWrapperStyle = css({
@@ -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 hasArgs = DisplayComponent && args;
95
+ const hasContent = DisplayComponent && (args || result);
86
96
 
87
97
  return (
88
98
  <div css={containerStyle}>
89
99
  <div
90
- css={hasArgs && containerClickableStyle}
91
- onClick={() => hasArgs && setIsExpanded(!isExpanded)}
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
- {hasArgs &&
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
- {hasArgs && isExpanded && (
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 { CopilotSidebar } from '@copilotkit/react-ui';
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 { WfoSearchResults } from '@/components/WfoSearchPage/WfoSearchResults';
13
+ import { getPageTemplateStyles } from '@/components/WfoPageTemplate/WfoPageTemplate/styles';
14
+ import { useWithOrchestratorTheme } from '@/hooks';
16
15
  import { useAgentAvailability } from '@/hooks/useBackendAvailability';
17
- import { AnySearchParameters, SearchResult } from '@/types';
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
- const { state } = useCoAgent<SearchState>({
54
- name: 'query_agent',
55
- initialState,
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
- <EuiFlexGroup gutterSize="l" alignItems="stretch">
96
- <EuiFlexItem grow={2}>
97
- <EuiText>
98
- <h1>{t('title')}</h1>
99
- </EuiText>
100
-
101
- <EuiSpacer size="m" />
102
-
103
- {results_data && results_data.action === 'view_results' && (
104
- <>
105
- {results_data.message && (
106
- <>
107
- <EuiText size="s">
108
- <p>{results_data.message}</p>
109
- </EuiText>
110
- <EuiSpacer size="s" />
111
- </>
112
- )}
113
- <WfoSearchResults
114
- results={results_data.results}
115
- loading={false}
116
- selectedRecordIndex={-1}
117
- onRecordSelect={() => {}}
118
- />
119
- </>
120
- )}
121
- </EuiFlexItem>
122
-
123
- <EuiFlexItem grow={1}>
124
- <CopilotSidebar
125
- defaultOpen
126
- clickOutsideToClose={false}
127
- labels={{
128
- title: tPage('copilot.title'),
129
- initial: tPage('copilot.initial'),
130
- }}
131
- />
132
- </EuiFlexItem>
133
- </EuiFlexGroup>
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,2 @@
1
+ export * from './WfoAgentLineChart';
2
+ export * from './WfoAgentPieChart';
@@ -0,0 +1,6 @@
1
+ import { css } from '@emotion/react';
2
+
3
+ export const containerStyle = css({
4
+ maxWidth: '50%',
5
+ marginRight: 'auto',
6
+ });
@@ -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';
@@ -1 +1,5 @@
1
1
  export * from './WfoAgent';
2
+ export * from './WfoAgentTable';
3
+ export * from './WfoAgentChart/WfoAgentLineChart';
4
+ export * from './WfoAgentChart/WfoAgentPieChart';
5
+ export * from './WfoAgentVisualization';
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
2
3
  /*
3
4
  * Copyright 2019-2023 SURF.
4
5
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -114,8 +114,8 @@ function Accept({
114
114
  state.skip
115
115
  ? 'SKIPPED'
116
116
  : state.allChecked
117
- ? 'ACCEPTED'
118
- : 'INCOMPLETE',
117
+ ? 'ACCEPTED'
118
+ : 'INCOMPLETE',
119
119
  );
120
120
 
121
121
  return { ...state };
@@ -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
- ? t('widgets.node_select.select_node')
84
- : t('forms.widgets.node_select.no_nodes_placeholder');
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) {