@orchestrator-ui/orchestrator-ui-components 6.4.0 → 6.6.1

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 (45) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +2 -2
  3. package/.turbo/turbo-test.log +5 -5
  4. package/CHANGELOG.md +24 -0
  5. package/dist/index.d.ts +23 -93
  6. package/dist/index.js +1025 -640
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/components/WfoAgent/ExportButton/ExportButton.tsx +96 -0
  10. package/src/components/WfoAgent/ExportButton/index.ts +1 -0
  11. package/src/components/WfoAgent/ExportButton/styles.ts +69 -0
  12. package/src/components/WfoAgent/ToolProgress/DiscoverFilterPathsDisplay.tsx +114 -0
  13. package/src/components/WfoAgent/ToolProgress/RunSearchDisplay.tsx +34 -0
  14. package/src/components/WfoAgent/{FilterDisplay/FilterDisplay.tsx → ToolProgress/SetFilterTreeDisplay.tsx} +25 -72
  15. package/src/components/WfoAgent/ToolProgress/StartNewSearchDisplay.tsx +62 -0
  16. package/src/components/WfoAgent/ToolProgress/ToolProgress.tsx +138 -0
  17. package/src/components/WfoAgent/ToolProgress/index.ts +1 -0
  18. package/src/components/WfoAgent/ToolProgress/styles.ts +50 -0
  19. package/src/components/WfoAgent/WfoAgent/WfoAgent.tsx +78 -51
  20. package/src/components/WfoAgent/index.ts +0 -1
  21. package/src/components/WfoInlineEdit/WfoInlineEdit.tsx +5 -1
  22. package/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx +1 -1
  23. package/src/components/WfoMetadata/WfoMetadataDescriptionField.tsx +3 -1
  24. package/src/components/WfoPydanticForm/fields/WfoArrayField/WfoArrayField.tsx +15 -6
  25. package/src/components/WfoPydanticForm/fields/WfoReactSelect/styles.ts +5 -1
  26. package/src/components/WfoSearchPage/WfoSearch/WfoSearch.tsx +6 -10
  27. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchResultItem.tsx +4 -4
  28. package/src/components/WfoSearchPage/WfoSearchResults/WfoSearchResults.tsx +18 -34
  29. package/src/components/WfoSearchPage/WfoSearchResults/index.ts +0 -1
  30. package/src/components/WfoSearchPage/utils.ts +12 -112
  31. package/src/components/WfoSubscription/WfoCustomerDescriptionsField.tsx +1 -1
  32. package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActions.tsx +137 -46
  33. package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActionsMenuItem.tsx +27 -33
  34. package/src/components/WfoSubscription/WfoSubscriptionActions/styles.ts +3 -1
  35. package/src/components/WfoSubscription/WfoTargetTypeIcon.tsx +37 -6
  36. package/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +1 -0
  37. package/src/configuration/version.ts +1 -1
  38. package/src/hooks/useSearchPagination.ts +2 -2
  39. package/src/messages/en-GB.json +3 -3
  40. package/src/messages/nl-NL.json +2 -0
  41. package/src/rtk/endpoints/agentExport.ts +23 -0
  42. package/src/types/search.ts +8 -70
  43. package/src/components/WfoAgent/FilterDisplay/index.ts +0 -1
  44. package/src/components/WfoSearchPage/WfoSearchResults/WfoSubscriptionDetailModal.tsx +0 -55
  45. /package/src/components/WfoAgent/{FilterDisplay/styles.ts → ToolProgress/SetFilterTreeDisplay.styles.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "6.4.0",
3
+ "version": "6.6.1",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Library of UI Components used to display the workflow orchestrator frontend",
6
6
  "author": {
@@ -0,0 +1,96 @@
1
+ import React from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import { EuiIcon, EuiLoadingSpinner } from '@elastic/eui';
6
+
7
+ import { useShowToastMessage, useWithOrchestratorTheme } from '@/hooks';
8
+ import { useLazyGetAgentExportQuery } from '@/rtk/endpoints/agentExport';
9
+ import { GraphQLPageInfo } from '@/types';
10
+ import { getCsvFileNameWithDate } from '@/utils';
11
+ import { csvDownloadHandler } from '@/utils/csvDownload';
12
+
13
+ import { getExportButtonStyles } from './styles';
14
+
15
+ export type ExportData = {
16
+ action: string;
17
+ download_url: string;
18
+ message: string;
19
+ };
20
+
21
+ export type ExportButtonProps = {
22
+ exportData: ExportData;
23
+ };
24
+
25
+ type ExportApiResponse = {
26
+ page: object[];
27
+ pageInfo?: GraphQLPageInfo;
28
+ };
29
+
30
+ export function ExportButton({ exportData }: ExportButtonProps) {
31
+ const { showToastMessage } = useShowToastMessage();
32
+ const tError = useTranslations('errors');
33
+ const [triggerExport, { isFetching }] = useLazyGetAgentExportQuery();
34
+
35
+ const {
36
+ containerStyle,
37
+ buttonWrapperStyle,
38
+ titleStyle,
39
+ fileRowStyle,
40
+ fileInfoStyle,
41
+ filenameStyle,
42
+ downloadButtonStyle,
43
+ } = useWithOrchestratorTheme(getExportButtonStyles);
44
+
45
+ const filename = getCsvFileNameWithDate('export');
46
+
47
+ const onDownloadClick = async () => {
48
+ const data = await triggerExport(exportData.download_url).unwrap();
49
+
50
+ const keyOrder = data.page.length > 0 ? Object.keys(data.page[0]) : [];
51
+
52
+ const handleExport = csvDownloadHandler(
53
+ async () => data,
54
+ (data: ExportApiResponse) => data.page,
55
+ (data: ExportApiResponse) =>
56
+ data.pageInfo ?? {
57
+ totalItems: data.page.length,
58
+ startCursor: 0,
59
+ endCursor: data.page.length - 1,
60
+ hasNextPage: false,
61
+ hasPreviousPage: false,
62
+ sortFields: [],
63
+ filterFields: [],
64
+ },
65
+ keyOrder,
66
+ filename,
67
+ showToastMessage,
68
+ tError,
69
+ );
70
+
71
+ await handleExport();
72
+ };
73
+
74
+ return (
75
+ <div css={containerStyle}>
76
+ <div css={buttonWrapperStyle}>
77
+ {exportData.message && (
78
+ <div css={titleStyle}>{exportData.message}</div>
79
+ )}
80
+ <div css={fileRowStyle} onClick={onDownloadClick}>
81
+ <div css={fileInfoStyle}>
82
+ <EuiIcon type="document" size="m" />
83
+ <span css={filenameStyle}>{filename}</span>
84
+ </div>
85
+ <div css={downloadButtonStyle}>
86
+ {isFetching ? (
87
+ <EuiLoadingSpinner size="m" />
88
+ ) : (
89
+ <EuiIcon type="download" size="m" />
90
+ )}
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ );
96
+ }
@@ -0,0 +1 @@
1
+ export * from './ExportButton';
@@ -0,0 +1,69 @@
1
+ import { css } from '@emotion/react';
2
+
3
+ import { WfoTheme } from '@/hooks';
4
+
5
+ export const getExportButtonStyles = ({ theme }: WfoTheme) => {
6
+ const containerStyle = css({
7
+ marginTop: theme.size.xl,
8
+ marginBottom: theme.size.xl,
9
+ width: '100%',
10
+ });
11
+
12
+ const buttonWrapperStyle = css({
13
+ backgroundColor: theme.colors.lightestShade,
14
+ padding: `${theme.size.xl} ${theme.size.xl}`,
15
+ border: `${theme.border.width.thin} solid transparent`,
16
+ display: 'flex',
17
+ flexDirection: 'column',
18
+ gap: theme.size.l,
19
+ });
20
+
21
+ const titleStyle = css({
22
+ fontSize: theme.size.m,
23
+ fontWeight: theme.font.weight.semiBold,
24
+ color: theme.colors.darkestShade,
25
+ });
26
+
27
+ const fileRowStyle = css({
28
+ display: 'flex',
29
+ alignItems: 'center',
30
+ justifyContent: 'space-between',
31
+ gap: theme.size.m,
32
+ border: `${theme.border.width.thin} solid ${theme.colors.lightShade}`,
33
+ borderRadius: theme.border.radius.medium,
34
+ padding: `${theme.size.m} ${theme.size.l}`,
35
+ backgroundColor: theme.colors.emptyShade,
36
+ cursor: 'pointer',
37
+ });
38
+
39
+ const fileInfoStyle = css({
40
+ display: 'flex',
41
+ alignItems: 'center',
42
+ gap: theme.size.m,
43
+ flex: 1,
44
+ color: theme.colors.darkestShade,
45
+ });
46
+
47
+ const filenameStyle = css({
48
+ fontSize: theme.size.m,
49
+ fontWeight: theme.font.weight.medium,
50
+ color: theme.colors.darkestShade,
51
+ });
52
+
53
+ const downloadButtonStyle = css({
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
57
+ color: theme.colors.darkestShade,
58
+ });
59
+
60
+ return {
61
+ containerStyle,
62
+ buttonWrapperStyle,
63
+ titleStyle,
64
+ fileRowStyle,
65
+ fileInfoStyle,
66
+ filenameStyle,
67
+ downloadButtonStyle,
68
+ };
69
+ };
@@ -0,0 +1,114 @@
1
+ import React from 'react';
2
+
3
+ import { EuiSpacer, EuiText } from '@elastic/eui';
4
+
5
+ import { WfoBadge } from '@/components/WfoBadges';
6
+ import { WfoPathBreadcrumb } from '@/components/WfoSearchPage/WfoSearchResults/WfoPathBreadcrumb';
7
+
8
+ interface DiscoverFilterPathsResult {
9
+ status?: string;
10
+ leaves?: Array<{
11
+ paths?: string[];
12
+ name?: string;
13
+ }>;
14
+ }
15
+
16
+ type DiscoverFilterPathsDisplayProps = {
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ result?: any;
19
+ parameters: {
20
+ field_names?: string[];
21
+ entity_type?: string;
22
+ };
23
+ };
24
+
25
+ export const DiscoverFilterPathsDisplay = ({
26
+ parameters,
27
+ result,
28
+ }: DiscoverFilterPathsDisplayProps) => {
29
+ const { field_names = [] } = parameters;
30
+
31
+ const foundFields: [string, DiscoverFilterPathsResult][] = result
32
+ ? Object.entries(
33
+ result as Record<string, DiscoverFilterPathsResult>,
34
+ ).filter(([, fieldResult]) => fieldResult.status !== 'NOT_FOUND')
35
+ : [];
36
+
37
+ // Count total paths across all found fields
38
+ const totalPaths = foundFields.reduce((count, [, fieldResult]) => {
39
+ const pathCount =
40
+ fieldResult.leaves?.reduce((leafCount: number, leaf) => {
41
+ return leafCount + (leaf.paths?.length || 1);
42
+ }, 0) || 0;
43
+ return count + pathCount;
44
+ }, 0);
45
+
46
+ return (
47
+ <div>
48
+ {field_names.length > 0 && (
49
+ <>
50
+ <EuiText size="xs" color="subdued">
51
+ Looking for{' '}
52
+ {field_names.map((name, idx) => (
53
+ <React.Fragment key={name}>
54
+ {idx > 0 && ', '}
55
+ <WfoBadge color="hollow" textColor="default">
56
+ {name}
57
+ </WfoBadge>
58
+ </React.Fragment>
59
+ ))}
60
+ </EuiText>
61
+ <EuiSpacer size="s" />
62
+ </>
63
+ )}
64
+
65
+ {result && totalPaths > 0 && (
66
+ <div>
67
+ <EuiText size="xs" color="subdued">
68
+ <strong>
69
+ Found {totalPaths} path
70
+ {totalPaths > 1 ? 's' : ''}:
71
+ </strong>
72
+ </EuiText>
73
+ <EuiSpacer size="xs" />
74
+ {foundFields.map(([fieldName, fieldResult]) => (
75
+ <div key={fieldName} style={{ marginBottom: '8px' }}>
76
+ {fieldResult.leaves &&
77
+ fieldResult.leaves.length > 0 &&
78
+ fieldResult.leaves.map(
79
+ (leaf, leafIdx: number) => {
80
+ const paths =
81
+ leaf.paths ||
82
+ (leaf.name ? [leaf.name] : []);
83
+ return (
84
+ <React.Fragment key={leafIdx}>
85
+ {paths.map(
86
+ (
87
+ path: string,
88
+ pathIdx: number,
89
+ ) => (
90
+ <div
91
+ key={pathIdx}
92
+ style={{
93
+ marginBottom:
94
+ '4px',
95
+ }}
96
+ >
97
+ <WfoPathBreadcrumb
98
+ path={path}
99
+ size="s"
100
+ />
101
+ </div>
102
+ ),
103
+ )}
104
+ </React.Fragment>
105
+ );
106
+ },
107
+ )}
108
+ </div>
109
+ ))}
110
+ </div>
111
+ )}
112
+ </div>
113
+ );
114
+ };
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+
3
+ import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
4
+
5
+ import { WfoBadge } from '@/components/WfoBadges';
6
+
7
+ type RunSearchDisplayProps = {
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ result?: any;
10
+ parameters: {
11
+ limit?: number;
12
+ };
13
+ };
14
+
15
+ export const RunSearchDisplay = ({ parameters }: RunSearchDisplayProps) => {
16
+ const { limit = 10 } = parameters;
17
+
18
+ return (
19
+ <div>
20
+ <EuiFlexGroup gutterSize="s" alignItems="center">
21
+ <EuiFlexItem grow={false}>
22
+ <EuiText size="xs" color="subdued">
23
+ <strong>Results Limit</strong>
24
+ </EuiText>
25
+ </EuiFlexItem>
26
+ <EuiFlexItem grow={false}>
27
+ <WfoBadge textColor="default" color="hollow">
28
+ {limit}
29
+ </WfoBadge>
30
+ </EuiFlexItem>
31
+ </EuiFlexGroup>
32
+ </div>
33
+ );
34
+ };
@@ -2,13 +2,7 @@ import React from 'react';
2
2
 
3
3
  import { useTranslations } from 'next-intl';
4
4
 
5
- import {
6
- EuiFlexGroup,
7
- EuiFlexItem,
8
- EuiPanel,
9
- EuiSpacer,
10
- EuiText,
11
- } from '@elastic/eui';
5
+ import { EuiText } from '@elastic/eui';
12
6
 
13
7
  import { WfoBadge } from '@/components/WfoBadges';
14
8
  import { WfoPathBreadcrumb } from '@/components/WfoSearchPage/WfoSearchResults/WfoPathBreadcrumb';
@@ -16,22 +10,13 @@ import {
16
10
  getOperatorDisplay,
17
11
  isCondition,
18
12
  } from '@/components/WfoSearchPage/utils';
19
- import { useWithOrchestratorTheme } from '@/index';
20
- import { AnySearchParameters, Condition, Group, PathDataType } from '@/types';
13
+ import { useWithOrchestratorTheme } from '@/hooks';
14
+ import { Condition, Group, PathDataType } from '@/types';
21
15
 
22
- import { getFilterDisplayStyles } from './styles';
16
+ import { getFilterDisplayStyles } from './SetFilterTreeDisplay.styles';
23
17
 
24
18
  const DEPTH_INDENT = 16;
25
19
 
26
- type FilterDisplayProps = {
27
- parameters: {
28
- action?: AnySearchParameters['action'] | string;
29
- entity_type?: AnySearchParameters['entity_type'] | string;
30
- filters?: Group | null;
31
- query?: string | null;
32
- };
33
- };
34
-
35
20
  interface BetweenValue {
36
21
  start?: string | number;
37
22
  end?: string | number;
@@ -39,9 +24,17 @@ interface BetweenValue {
39
24
  to?: string | number;
40
25
  }
41
26
 
42
- export function FilterDisplay({ parameters }: FilterDisplayProps) {
43
- const t = useTranslations('agent.page');
27
+ type SetFilterTreeDisplayProps = {
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ result?: any;
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ parameters: any;
32
+ };
44
33
 
34
+ export const SetFilterTreeDisplay = ({
35
+ parameters,
36
+ }: SetFilterTreeDisplayProps) => {
37
+ const t = useTranslations('agent.page');
45
38
  const {
46
39
  wrapStyle,
47
40
  columnGroupWrapStyle,
@@ -50,15 +43,9 @@ export function FilterDisplay({ parameters }: FilterDisplayProps) {
50
43
  operatorStyle,
51
44
  valueStyle,
52
45
  } = useWithOrchestratorTheme(getFilterDisplayStyles);
53
- const { action, entity_type, filters, query } = parameters ?? {};
54
46
 
55
- if (!parameters || Object.keys(parameters).length === 0) return null;
56
-
57
- const sectionTitle = (text: string) => (
58
- <EuiText size="xs" color="subdued">
59
- <strong>{text}</strong>
60
- </EuiText>
61
- );
47
+ // Parameters might be the Group directly, or wrapped in a filters property
48
+ const filters = (parameters?.filters || parameters) as Group;
62
49
 
63
50
  const formatFilterValue = (condition: Condition['condition']): string => {
64
51
  if ('value' in condition && condition.value !== undefined) {
@@ -136,47 +123,13 @@ export function FilterDisplay({ parameters }: FilterDisplayProps) {
136
123
  );
137
124
  };
138
125
 
139
- return (
140
- <EuiPanel hasBorder paddingSize="m">
141
- <EuiFlexGroup gutterSize="m" wrap responsive>
142
- <EuiFlexItem grow={false}>
143
- {sectionTitle(t('action'))}
144
- <EuiSpacer size="xs" />
145
- <WfoBadge textColor="default" color="hollow">
146
- {action || 'N/A'}
147
- </WfoBadge>
148
- </EuiFlexItem>
149
-
150
- <EuiFlexItem grow={false}>
151
- {sectionTitle(t('entityType'))}
152
- <EuiSpacer size="xs" />
153
- <WfoBadge textColor="default" color="hollow">
154
- {entity_type || 'N/A'}
155
- </WfoBadge>
156
- </EuiFlexItem>
157
-
158
- {query ? (
159
- <EuiFlexItem grow={false}>
160
- {sectionTitle(t('searchQuery'))}
161
- <EuiSpacer size="xs" />
162
- <EuiText size="s">
163
- <em>"{query}"</em>
164
- </EuiText>
165
- </EuiFlexItem>
166
- ) : null}
167
- </EuiFlexGroup>
168
-
169
- <EuiSpacer size="m" />
170
- {sectionTitle(t('activeFilters'))}
171
- <EuiSpacer size="s" />
126
+ if (!filters || !filters.children || filters.children.length === 0) {
127
+ return (
128
+ <EuiText size="s" color="subdued">
129
+ <em>{t('noFiltersApplied')}</em>
130
+ </EuiText>
131
+ );
132
+ }
172
133
 
173
- {filters && filters.children && filters.children.length > 0 ? (
174
- renderFilterGroup(filters)
175
- ) : (
176
- <EuiText size="s" color="subdued">
177
- <em>{t('noFiltersApplied')}</em>
178
- </EuiText>
179
- )}
180
- </EuiPanel>
181
- );
182
- }
134
+ return <div>{renderFilterGroup(filters)}</div>;
135
+ };
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+
3
+ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui';
4
+
5
+ import { WfoBadge } from '@/components/WfoBadges';
6
+
7
+ type StartNewSearchDisplayProps = {
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ result?: any;
10
+ parameters: {
11
+ entity_type?: string;
12
+ action?: string;
13
+ query?: string;
14
+ };
15
+ };
16
+
17
+ export const StartNewSearchDisplay = ({
18
+ parameters,
19
+ }: StartNewSearchDisplayProps) => {
20
+ const { entity_type, action, query } = parameters;
21
+
22
+ return (
23
+ <div>
24
+ <EuiFlexGroup gutterSize="s" wrap>
25
+ {entity_type && (
26
+ <EuiFlexItem grow={false}>
27
+ <EuiText size="xs" color="subdued">
28
+ <strong>Entity Type</strong>
29
+ </EuiText>
30
+ <EuiSpacer size="xs" />
31
+ <WfoBadge textColor="default" color="hollow">
32
+ {entity_type}
33
+ </WfoBadge>
34
+ </EuiFlexItem>
35
+ )}
36
+ {action && (
37
+ <EuiFlexItem grow={false}>
38
+ <EuiText size="xs" color="subdued">
39
+ <strong>Action</strong>
40
+ </EuiText>
41
+ <EuiSpacer size="xs" />
42
+ <WfoBadge textColor="default" color="hollow">
43
+ {action}
44
+ </WfoBadge>
45
+ </EuiFlexItem>
46
+ )}
47
+ </EuiFlexGroup>
48
+ {query && (
49
+ <>
50
+ <EuiSpacer size="s" />
51
+ <EuiText size="xs" color="subdued">
52
+ <strong>Query</strong>
53
+ </EuiText>
54
+ <EuiSpacer size="xs" />
55
+ <EuiText size="s">
56
+ <em>"{query}"</em>
57
+ </EuiText>
58
+ </>
59
+ )}
60
+ </div>
61
+ );
62
+ };
@@ -0,0 +1,138 @@
1
+ import React, { useState } from 'react';
2
+
3
+ import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
4
+
5
+ import { useWithOrchestratorTheme } from '@/hooks';
6
+ import { useOrchestratorTheme } from '@/hooks/useOrchestratorTheme';
7
+ import {
8
+ WfoCheckmarkCircleFill,
9
+ WfoChevronDown,
10
+ WfoChevronUp,
11
+ WfoXCircleFill,
12
+ } from '@/icons';
13
+ import { WfoWrench } from '@/icons/heroicons';
14
+
15
+ import { DiscoverFilterPathsDisplay } from './DiscoverFilterPathsDisplay';
16
+ import { RunSearchDisplay } from './RunSearchDisplay';
17
+ import { SetFilterTreeDisplay } from './SetFilterTreeDisplay';
18
+ import { StartNewSearchDisplay } from './StartNewSearchDisplay';
19
+ import { getToolProgressStyles } from './styles';
20
+
21
+ type ToolProgressProps = {
22
+ name: string;
23
+ status: 'executing' | 'inProgress' | 'complete' | 'failed';
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ args?: any;
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ result?: any;
28
+ };
29
+
30
+ // Mapping of tool names to their display components
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ const TOOL_DISPLAY_COMPONENTS: Record<string, React.ComponentType<any>> = {
33
+ set_filter_tree: SetFilterTreeDisplay,
34
+ start_new_search: StartNewSearchDisplay,
35
+ run_search: RunSearchDisplay,
36
+ discover_filter_paths: DiscoverFilterPathsDisplay,
37
+ };
38
+
39
+ export const ToolProgress = ({
40
+ name,
41
+ status,
42
+ args,
43
+ result,
44
+ }: ToolProgressProps) => {
45
+ const [isExpanded, setIsExpanded] = useState(false);
46
+
47
+ const {
48
+ containerStyle,
49
+ containerClickableStyle,
50
+ headerStyle,
51
+ nameStyle,
52
+ expandedContentStyle,
53
+ iconSize,
54
+ iconStyle,
55
+ } = useWithOrchestratorTheme(getToolProgressStyles);
56
+
57
+ const { theme } = useOrchestratorTheme();
58
+
59
+ const renderStatus = () => {
60
+ if (status === 'complete') {
61
+ return (
62
+ <WfoCheckmarkCircleFill
63
+ color={theme.colors.success}
64
+ width={iconSize}
65
+ height={iconSize}
66
+ />
67
+ );
68
+ }
69
+ if (status === 'inProgress' || status === 'executing') {
70
+ return <EuiLoadingSpinner size="s" />;
71
+ }
72
+ if (status === 'failed') {
73
+ return (
74
+ <WfoXCircleFill
75
+ color={theme.colors.danger}
76
+ width={iconSize}
77
+ height={iconSize}
78
+ />
79
+ );
80
+ }
81
+ return null;
82
+ };
83
+
84
+ const DisplayComponent = TOOL_DISPLAY_COMPONENTS[name];
85
+ const hasArgs = DisplayComponent && args;
86
+
87
+ return (
88
+ <div css={containerStyle}>
89
+ <div
90
+ css={hasArgs && containerClickableStyle}
91
+ onClick={() => hasArgs && setIsExpanded(!isExpanded)}
92
+ >
93
+ <EuiFlexGroup
94
+ gutterSize="m"
95
+ alignItems="center"
96
+ css={headerStyle}
97
+ >
98
+ <EuiFlexItem grow={false}>
99
+ <div css={iconStyle}>
100
+ <WfoWrench width={iconSize} height={iconSize} />
101
+ </div>
102
+ </EuiFlexItem>
103
+ <EuiFlexItem grow={true}>
104
+ <span css={nameStyle}>{name}</span>
105
+ </EuiFlexItem>
106
+ <EuiFlexItem
107
+ grow={false}
108
+ style={{ minWidth: `${iconSize}px` }}
109
+ >
110
+ {renderStatus()}
111
+ </EuiFlexItem>
112
+ <EuiFlexItem
113
+ grow={false}
114
+ style={{ minWidth: `${iconSize}px` }}
115
+ >
116
+ {hasArgs &&
117
+ (isExpanded ? (
118
+ <WfoChevronUp
119
+ width={iconSize}
120
+ height={iconSize}
121
+ />
122
+ ) : (
123
+ <WfoChevronDown
124
+ width={iconSize}
125
+ height={iconSize}
126
+ />
127
+ ))}
128
+ </EuiFlexItem>
129
+ </EuiFlexGroup>
130
+ </div>
131
+ {hasArgs && isExpanded && (
132
+ <div css={expandedContentStyle}>
133
+ <DisplayComponent parameters={args} result={result} />
134
+ </div>
135
+ )}
136
+ </div>
137
+ );
138
+ };
@@ -0,0 +1 @@
1
+ export { ToolProgress } from './ToolProgress';