@orchestrator-ui/orchestrator-ui-components 7.5.1 → 7.6.0
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 +7 -7
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-test.log +9 -9
- package/CHANGELOG.md +14 -0
- package/dist/index.d.ts +481 -10
- package/dist/index.js +550 -481
- package/dist/index.js.map +1 -1
- package/jest.config.cjs +4 -1
- package/package.json +6 -6
- package/src/components/WfoAgent/ExportButton/ExportButton.tsx +5 -11
- package/src/components/WfoAgent/WfoAgent/WfoAgent.tsx +79 -31
- package/src/components/WfoAgent/WfoAgentChart/WfoAgentLineChart.tsx +2 -2
- package/src/components/WfoAgent/WfoAgentChart/WfoAgentPieChart.tsx +2 -2
- package/src/components/WfoAgent/WfoAgentTable/WfoAgentTable.tsx +9 -9
- package/src/components/WfoAgent/WfoAgentVisualization/WfoAgentVisualization.tsx +2 -2
- package/src/components/WfoAgent/WfoPlanProgress/WfoPlanProgress.tsx +107 -0
- package/src/components/WfoAgent/WfoPlanProgress/index.ts +1 -0
- package/src/components/WfoAgent/WfoPlanProgress/styles.ts +62 -0
- package/src/components/WfoAgent/WfoQueryArtifact/WfoQueryArtifact.tsx +40 -0
- package/src/components/WfoAgent/WfoQueryArtifact/index.ts +1 -0
- package/src/components/WfoAgent/index.ts +2 -0
- package/src/components/WfoBadges/WfoVersionIncompatibleBadge/WfoVersionIncompatibleBadge.tsx +7 -6
- package/src/components/WfoKeyValueTable/WfoValueCell.tsx +1 -1
- package/src/components/WfoPydanticForm/fields/WfoInteger.tsx +22 -3
- package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActions.tsx +3 -2
- package/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +9 -9
- package/src/components/WfoTable/WfoAdvancedTable/WfoAdvancedTable.tsx +1 -1
- package/src/components/WfoTable/WfoFirstPartUUID/WfoFirstPartUUID.tsx +1 -1
- package/src/configuration/constants.ts +3 -0
- package/src/configuration/version.ts +1 -1
- package/src/hooks/useAgentPlanEvents.ts +188 -0
- package/src/messages/en-GB.json +5 -0
- package/src/rtk/endpoints/agentQueryResults.ts +19 -0
- package/src/rtk/endpoints/index.ts +1 -0
- package/src/types/search.ts +19 -4
- package/src/utils/compareVersions.spec.ts +5 -0
- package/src/utils/compareVersions.ts +55 -23
- package/src/components/WfoAgent/ToolProgress/DiscoverFilterPathsDisplay.tsx +0 -99
- package/src/components/WfoAgent/ToolProgress/RunSearchDisplay.tsx +0 -34
- package/src/components/WfoAgent/ToolProgress/SetFilterTreeDisplay.styles.ts +0 -62
- package/src/components/WfoAgent/ToolProgress/SetFilterTreeDisplay.tsx +0 -107
- package/src/components/WfoAgent/ToolProgress/StartNewSearchDisplay.tsx +0 -60
- package/src/components/WfoAgent/ToolProgress/ToolProgress.tsx +0 -98
- package/src/components/WfoAgent/ToolProgress/index.ts +0 -1
- package/src/components/WfoAgent/ToolProgress/styles.ts +0 -52
|
@@ -80,6 +80,11 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
|
|
|
80
80
|
const subscriptionList = mapGraphQlSubscriptionsResultToSubscriptionListItems(data);
|
|
81
81
|
|
|
82
82
|
const tableColumnConfig: WfoAdvancedTableColumnConfig<SubscriptionListItem> = {
|
|
83
|
+
actions: {
|
|
84
|
+
columnType: ColumnType.CONTROL,
|
|
85
|
+
width: '50px',
|
|
86
|
+
renderControl: (row) => <WfoSubscriptionActions compactMode={true} subscriptionId={row.subscriptionId} />,
|
|
87
|
+
},
|
|
83
88
|
subscriptionId: {
|
|
84
89
|
columnType: ColumnType.DATA,
|
|
85
90
|
label: t('id'),
|
|
@@ -104,11 +109,12 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
|
|
|
104
109
|
insync: {
|
|
105
110
|
columnType: ColumnType.DATA,
|
|
106
111
|
label: t('insync'),
|
|
107
|
-
width: '
|
|
112
|
+
width: '75px',
|
|
108
113
|
renderData: (value) => <WfoInsyncIcon inSync={value} />,
|
|
109
114
|
},
|
|
110
115
|
productName: {
|
|
111
116
|
columnType: ColumnType.DATA,
|
|
117
|
+
width: '260px',
|
|
112
118
|
label: t('product'),
|
|
113
119
|
},
|
|
114
120
|
tag: {
|
|
@@ -128,7 +134,7 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
|
|
|
128
134
|
startDate: {
|
|
129
135
|
columnType: ColumnType.DATA,
|
|
130
136
|
label: t('startDate'),
|
|
131
|
-
width: '
|
|
137
|
+
width: '100px',
|
|
132
138
|
renderData: (value) => <WfoDateTime dateOrIsoString={value} />,
|
|
133
139
|
renderDetails: parseDateToLocaleDateTimeString,
|
|
134
140
|
clipboardText: parseDateToLocaleDateTimeString,
|
|
@@ -137,7 +143,7 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
|
|
|
137
143
|
endDate: {
|
|
138
144
|
columnType: ColumnType.DATA,
|
|
139
145
|
label: t('endDate'),
|
|
140
|
-
width: '
|
|
146
|
+
width: '100px',
|
|
141
147
|
renderData: (value) => <WfoDateTime dateOrIsoString={value} />,
|
|
142
148
|
renderDetails: parseDateToLocaleDateTimeString,
|
|
143
149
|
clipboardText: parseDateToLocaleDateTimeString,
|
|
@@ -159,12 +165,6 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
|
|
|
159
165
|
);
|
|
160
166
|
},
|
|
161
167
|
},
|
|
162
|
-
actions: {
|
|
163
|
-
columnType: ColumnType.CONTROL,
|
|
164
|
-
label: t('actions'),
|
|
165
|
-
width: '80px',
|
|
166
|
-
renderControl: (row) => <WfoSubscriptionActions compactMode={true} subscriptionId={row.subscriptionId} />,
|
|
167
|
-
},
|
|
168
168
|
metadata: {
|
|
169
169
|
columnType: ColumnType.DATA,
|
|
170
170
|
label: t('metadata'),
|
|
@@ -81,7 +81,7 @@ export const WfoAdvancedTable = <T extends object>({
|
|
|
81
81
|
width: '36px',
|
|
82
82
|
renderControl: (row) => (
|
|
83
83
|
<EuiFlexItem css={{ cursor: 'pointer' }} onClick={() => setSelectedDataForDetailModal(row)}>
|
|
84
|
-
<WfoArrowsExpand color={theme.colors.
|
|
84
|
+
<WfoArrowsExpand color={theme.colors.textDisabled} />
|
|
85
85
|
</EuiFlexItem>
|
|
86
86
|
),
|
|
87
87
|
},
|
|
@@ -24,7 +24,7 @@ export const WfoFirstPartUUID: FC<WfoFirstUUIDPartProps> = ({ UUID, showCopyIcon
|
|
|
24
24
|
<EuiCopy textToCopy={UUID}>
|
|
25
25
|
{(copy) => (
|
|
26
26
|
<div className={COPY_ICON_CLASS} onClick={copy} css={clickable}>
|
|
27
|
-
<WfoClipboardCopy width={16} height={16} color={theme.colors.
|
|
27
|
+
<WfoClipboardCopy width={16} height={16} color={theme.colors.backgroundBaseAccent} />
|
|
28
28
|
</div>
|
|
29
29
|
)}
|
|
30
30
|
</EuiCopy>
|
|
@@ -35,3 +35,6 @@ export const METADATA_PRODUCT_BLOCK_ENDPOINT = 'product_blocks';
|
|
|
35
35
|
export const METADATA_RESOURCE_TYPE_ENDPOINT = 'resource_types';
|
|
36
36
|
export const METADATA_WORKFLOWS_ENDPOINT = 'workflows';
|
|
37
37
|
export const METADATA_SCHEDULES_ENDPOINT = 'schedules';
|
|
38
|
+
|
|
39
|
+
//search
|
|
40
|
+
export const SEARCH_QUERY_RESULTS_ENDPOINT = 'search/queries';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '7.
|
|
1
|
+
export const ORCHESTRATOR_UI_LIBRARY_VERSION = '7.6.0';
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { AgentSubscriber } from '@ag-ui/client';
|
|
4
|
+
// @ts-expect-error - v2 subpath exists but TypeScript moduleResolution doesn't recognize it
|
|
5
|
+
import { useAgent } from '@copilotkit/react-core/v2';
|
|
6
|
+
|
|
7
|
+
/** AG-UI custom event names emitted by the backend agent. */
|
|
8
|
+
enum AgentEvent {
|
|
9
|
+
PLAN_CREATED = 'PLAN_CREATED',
|
|
10
|
+
STEP_ACTIVE = 'AGENT_STEP_ACTIVE',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** The backend step name used for the planning phase (not a real task). */
|
|
14
|
+
const PLANNER_STEP_NAME = 'Planner';
|
|
15
|
+
|
|
16
|
+
export type ToolCallState = {
|
|
17
|
+
id: string;
|
|
18
|
+
name: string;
|
|
19
|
+
status: 'executing' | 'complete';
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type PlanStep = {
|
|
23
|
+
step_name: string;
|
|
24
|
+
reasoning: string | null;
|
|
25
|
+
status: 'pending' | 'active' | 'completed';
|
|
26
|
+
tool_calls: ToolCallState[];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type PlanExecutionState = {
|
|
30
|
+
planning: boolean;
|
|
31
|
+
steps: PlanStep[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const initialState: PlanExecutionState = {
|
|
35
|
+
planning: false,
|
|
36
|
+
steps: [],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const updateSteps = (
|
|
40
|
+
steps: PlanStep[],
|
|
41
|
+
predicate: (step: PlanStep) => boolean,
|
|
42
|
+
updater: (step: PlanStep) => PlanStep,
|
|
43
|
+
): PlanStep[] => steps.map((step) => (predicate(step) ? updater(step) : step));
|
|
44
|
+
|
|
45
|
+
export function useAgentPlanEvents(agentId: string = 'query_agent'): PlanExecutionState {
|
|
46
|
+
const { agent } = useAgent({ agentId });
|
|
47
|
+
const [executionState, setExecutionState] = useState<PlanExecutionState>(initialState);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!agent) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const subscriber: AgentSubscriber = {
|
|
55
|
+
onCustomEvent: (params) => {
|
|
56
|
+
const event = params?.event;
|
|
57
|
+
if (!event) return;
|
|
58
|
+
|
|
59
|
+
if (event.name === AgentEvent.PLAN_CREATED) {
|
|
60
|
+
const tasks = event.value as Array<{
|
|
61
|
+
skillName: string;
|
|
62
|
+
reasoning: string;
|
|
63
|
+
}>;
|
|
64
|
+
if (!Array.isArray(tasks)) return;
|
|
65
|
+
|
|
66
|
+
setExecutionState({
|
|
67
|
+
planning: false,
|
|
68
|
+
steps: tasks.map((task) => ({
|
|
69
|
+
step_name: task.skillName,
|
|
70
|
+
reasoning: task.reasoning,
|
|
71
|
+
status: 'pending' as const,
|
|
72
|
+
tool_calls: [],
|
|
73
|
+
})),
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (event.name === AgentEvent.STEP_ACTIVE) {
|
|
79
|
+
const stepName = event.value?.step;
|
|
80
|
+
if (!stepName) return;
|
|
81
|
+
|
|
82
|
+
if (stepName === PLANNER_STEP_NAME) {
|
|
83
|
+
setExecutionState((prev) => ({
|
|
84
|
+
...prev,
|
|
85
|
+
planning: true,
|
|
86
|
+
}));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const reasoning = event.value?.reasoning ?? null;
|
|
91
|
+
|
|
92
|
+
setExecutionState((prev) => {
|
|
93
|
+
// Mark previous active step as completed
|
|
94
|
+
const steps = updateSteps(
|
|
95
|
+
prev.steps,
|
|
96
|
+
(step) => step.status === 'active',
|
|
97
|
+
(step) => ({ ...step, status: 'completed' as const }),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// If step already exists (from PLAN_CREATED), activate it
|
|
101
|
+
const existingIndex = steps.findIndex((step) => step.step_name === stepName);
|
|
102
|
+
if (existingIndex >= 0) {
|
|
103
|
+
steps[existingIndex] = {
|
|
104
|
+
...steps[existingIndex],
|
|
105
|
+
status: 'active',
|
|
106
|
+
reasoning: reasoning ?? steps[existingIndex].reasoning,
|
|
107
|
+
};
|
|
108
|
+
} else {
|
|
109
|
+
steps.push({
|
|
110
|
+
step_name: stepName,
|
|
111
|
+
reasoning,
|
|
112
|
+
status: 'active',
|
|
113
|
+
tool_calls: [],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { planning: false, steps };
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
onToolCallStartEvent: ({ event }) => {
|
|
123
|
+
setExecutionState((prev) => {
|
|
124
|
+
const currentStep = prev.steps.find((step) => step.status === 'active');
|
|
125
|
+
if (!currentStep) return prev;
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
...prev,
|
|
129
|
+
steps: updateSteps(
|
|
130
|
+
prev.steps,
|
|
131
|
+
(step) => step.step_name === currentStep.step_name,
|
|
132
|
+
(step) => ({
|
|
133
|
+
...step,
|
|
134
|
+
tool_calls: [
|
|
135
|
+
...step.tool_calls,
|
|
136
|
+
{
|
|
137
|
+
id: event.toolCallId,
|
|
138
|
+
name: event.toolCallName,
|
|
139
|
+
status: 'executing' as const,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
}),
|
|
143
|
+
),
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
onToolCallEndEvent: ({ event }) => {
|
|
149
|
+
setExecutionState((prev) => ({
|
|
150
|
+
...prev,
|
|
151
|
+
steps: updateSteps(
|
|
152
|
+
prev.steps,
|
|
153
|
+
(step) => step.tool_calls.some((toolCall) => toolCall.id === event.toolCallId),
|
|
154
|
+
(step) => ({
|
|
155
|
+
...step,
|
|
156
|
+
tool_calls: step.tool_calls.map((toolCall) =>
|
|
157
|
+
toolCall.id === event.toolCallId ? { ...toolCall, status: 'complete' as const } : toolCall,
|
|
158
|
+
),
|
|
159
|
+
}),
|
|
160
|
+
),
|
|
161
|
+
}));
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
onRunStartedEvent: () => {
|
|
165
|
+
setExecutionState(initialState);
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
onRunFinishedEvent: () => {
|
|
169
|
+
setExecutionState((prev) => ({
|
|
170
|
+
planning: false,
|
|
171
|
+
steps: updateSteps(
|
|
172
|
+
prev.steps,
|
|
173
|
+
(step) => step.status === 'active',
|
|
174
|
+
(step) => ({ ...step, status: 'completed' as const }),
|
|
175
|
+
),
|
|
176
|
+
}));
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const subscription = agent.subscribe(subscriber);
|
|
181
|
+
|
|
182
|
+
return () => {
|
|
183
|
+
subscription.unsubscribe();
|
|
184
|
+
};
|
|
185
|
+
}, [agent]);
|
|
186
|
+
|
|
187
|
+
return executionState;
|
|
188
|
+
}
|
package/src/messages/en-GB.json
CHANGED
|
@@ -558,6 +558,11 @@
|
|
|
558
558
|
"get_valid_operators": "I'm getting valid operators",
|
|
559
559
|
"set_temporal_grouping": "I'm setting temporal grouping"
|
|
560
560
|
},
|
|
561
|
+
"planProgress": {
|
|
562
|
+
"planning": "Planning...",
|
|
563
|
+
"completed": "Plan completed",
|
|
564
|
+
"executing": "Executing plan ({completed}/{total})"
|
|
565
|
+
},
|
|
561
566
|
"visualization": {
|
|
562
567
|
"noDataAvailable": "No data available for visualization.",
|
|
563
568
|
"invalidDataStructure": "Invalid data structure."
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SEARCH_QUERY_RESULTS_ENDPOINT } from '@/configuration';
|
|
2
|
+
import { BaseQueryTypes, orchestratorApi } from '@/rtk';
|
|
3
|
+
import { QueryResultsData } from '@/types';
|
|
4
|
+
|
|
5
|
+
const agentQueryResultsApi = orchestratorApi.injectEndpoints({
|
|
6
|
+
endpoints: (builder) => ({
|
|
7
|
+
getAgentQueryResults: builder.query<QueryResultsData, string>({
|
|
8
|
+
query: (queryId) => ({
|
|
9
|
+
url: `${SEARCH_QUERY_RESULTS_ENDPOINT}/${queryId}/results`,
|
|
10
|
+
method: 'GET',
|
|
11
|
+
}),
|
|
12
|
+
extraOptions: {
|
|
13
|
+
baseQueryType: BaseQueryTypes.fetch,
|
|
14
|
+
},
|
|
15
|
+
}),
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const { useGetAgentQueryResultsQuery } = agentQueryResultsApi;
|
package/src/types/search.ts
CHANGED
|
@@ -156,7 +156,7 @@ export type PathInfo = {
|
|
|
156
156
|
|
|
157
157
|
/** ---------- Agent visualization types ---------- */
|
|
158
158
|
|
|
159
|
-
export type
|
|
159
|
+
export type ResultRow = {
|
|
160
160
|
group_values: Record<string, string>;
|
|
161
161
|
aggregations: Record<string, number>;
|
|
162
162
|
};
|
|
@@ -172,11 +172,26 @@ export enum VisualizationType {
|
|
|
172
172
|
TABLE = 'table',
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
export type
|
|
176
|
-
results:
|
|
177
|
-
|
|
175
|
+
export type QueryResultsData = {
|
|
176
|
+
results: ResultRow[];
|
|
177
|
+
total_results: number;
|
|
178
178
|
metadata: SearchMetadata;
|
|
179
179
|
visualization_type: {
|
|
180
180
|
type: VisualizationType;
|
|
181
181
|
};
|
|
182
182
|
};
|
|
183
|
+
|
|
184
|
+
export type QueryArtifact = {
|
|
185
|
+
query_id: string;
|
|
186
|
+
total_results: number;
|
|
187
|
+
visualization_type: {
|
|
188
|
+
type: VisualizationType;
|
|
189
|
+
};
|
|
190
|
+
description: string;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export type ExportArtifact = {
|
|
194
|
+
query_id: string;
|
|
195
|
+
download_url: string;
|
|
196
|
+
description: string;
|
|
197
|
+
};
|
|
@@ -48,4 +48,9 @@ describe('isOrchestratorUiVersionCompatible', () => {
|
|
|
48
48
|
expect(getOrchestratorCoreVersionIfNotCompatible('1.0.0', '2.10.0', TEST_VERSIONS)).toBe(null); // falls back to first MAPPED_VERSION
|
|
49
49
|
expect(getOrchestratorCoreVersionIfNotCompatible('1.0.0', '2.9.9', TEST_VERSIONS)).toBe('2.10.0');
|
|
50
50
|
});
|
|
51
|
+
|
|
52
|
+
test('handles prerelease orchestratorCoreVersion (e.g. 5.0.0a7)', () => {
|
|
53
|
+
expect(getOrchestratorCoreVersionIfNotCompatible('3.10.0', '5.0.0a7', TEST_VERSIONS)).toBe(null);
|
|
54
|
+
expect(getOrchestratorCoreVersionIfNotCompatible('3.10.0', '3.1.1a1', TEST_VERSIONS)).toBe('3.1.1');
|
|
55
|
+
});
|
|
51
56
|
});
|
|
@@ -1,33 +1,62 @@
|
|
|
1
1
|
import { MappedVersion } from '@/types';
|
|
2
2
|
|
|
3
|
-
const compareVersions = (
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
const compareVersions = (v1: string, v2: string): number => {
|
|
4
|
+
const parse = (v: string) => {
|
|
5
|
+
const parts = v.split('.');
|
|
6
|
+
|
|
7
|
+
const major = parseInt(parts[0]);
|
|
8
|
+
const minor = parseInt(parts[1]);
|
|
9
|
+
|
|
10
|
+
const patchPart = parts[2] ?? '';
|
|
11
|
+
|
|
12
|
+
let patch = 0;
|
|
13
|
+
let suffix = '';
|
|
14
|
+
|
|
15
|
+
// extract numeric patch and suffix manually
|
|
16
|
+
for (let i = 0; i < patchPart.length; i++) {
|
|
17
|
+
const char = patchPart[i];
|
|
18
|
+
|
|
19
|
+
if (char >= '0' && char <= '9') {
|
|
20
|
+
patch = patch * 10 + Number(char);
|
|
21
|
+
} else {
|
|
22
|
+
suffix = patchPart.slice(i);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
12
25
|
}
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
|
|
27
|
+
return { major, minor, patch, suffix };
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const a = parse(v1);
|
|
31
|
+
const b = parse(v2);
|
|
32
|
+
|
|
33
|
+
// compare numeric parts
|
|
34
|
+
if (a.major !== b.major) return a.major > b.major ? 1 : -1;
|
|
35
|
+
if (a.minor !== b.minor) return a.minor > b.minor ? 1 : -1;
|
|
36
|
+
if (a.patch !== b.patch) return a.patch > b.patch ? 1 : -1;
|
|
37
|
+
|
|
38
|
+
// compare suffix
|
|
39
|
+
if (a.suffix === b.suffix) return 0;
|
|
40
|
+
if (!a.suffix) return 1; // stable > pre-release
|
|
41
|
+
if (!b.suffix) return -1;
|
|
42
|
+
|
|
43
|
+
return a.suffix > b.suffix ? 1 : -1;
|
|
15
44
|
};
|
|
16
45
|
|
|
17
46
|
const findMinimumOrchestratorCoreVersion = (
|
|
18
47
|
orchestratorUiVersion: string,
|
|
19
48
|
versionMappings: MappedVersion[],
|
|
20
|
-
): string => {
|
|
21
|
-
|
|
22
|
-
|
|
49
|
+
): string | null => {
|
|
50
|
+
// sort mappings descending by UI version. This is done just in case the input versionMappings are not sorted
|
|
51
|
+
const sorted = [...versionMappings].sort((a, b) => compareVersions(b.orchestratorUiVersion, a.orchestratorUiVersion));
|
|
23
52
|
|
|
24
|
-
for (
|
|
25
|
-
if (
|
|
26
|
-
|
|
53
|
+
for (const mapping of sorted) {
|
|
54
|
+
if (compareVersions(orchestratorUiVersion, mapping.orchestratorUiVersion) >= 0) {
|
|
55
|
+
return mapping.minimumOrchestratorCoreVersion;
|
|
27
56
|
}
|
|
28
57
|
}
|
|
29
58
|
|
|
30
|
-
return
|
|
59
|
+
return sorted[sorted.length - 1]?.minimumOrchestratorCoreVersion ?? null;
|
|
31
60
|
};
|
|
32
61
|
|
|
33
62
|
export const getOrchestratorCoreVersionIfNotCompatible = (
|
|
@@ -35,10 +64,13 @@ export const getOrchestratorCoreVersionIfNotCompatible = (
|
|
|
35
64
|
orchestratorCoreVersion: string,
|
|
36
65
|
versionMappings: MappedVersion[],
|
|
37
66
|
): string | null => {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
return
|
|
67
|
+
const minimumVersion = findMinimumOrchestratorCoreVersion(orchestratorUiVersion, versionMappings);
|
|
68
|
+
|
|
69
|
+
if (!minimumVersion) {
|
|
70
|
+
return null;
|
|
42
71
|
}
|
|
43
|
-
|
|
72
|
+
|
|
73
|
+
const isCompatible = compareVersions(orchestratorCoreVersion, minimumVersion) !== -1;
|
|
74
|
+
|
|
75
|
+
return isCompatible ? null : minimumVersion;
|
|
44
76
|
};
|
|
@@ -1,99 +0,0 @@
|
|
|
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 = ({ parameters, result }: DiscoverFilterPathsDisplayProps) => {
|
|
26
|
-
const { field_names = [] } = parameters;
|
|
27
|
-
|
|
28
|
-
const foundFields: [string, DiscoverFilterPathsResult][] =
|
|
29
|
-
result ?
|
|
30
|
-
Object.entries(result as Record<string, DiscoverFilterPathsResult>).filter(
|
|
31
|
-
([, fieldResult]) => fieldResult.status !== 'NOT_FOUND',
|
|
32
|
-
)
|
|
33
|
-
: [];
|
|
34
|
-
|
|
35
|
-
// Count total paths across all found fields
|
|
36
|
-
const totalPaths = foundFields.reduce((count, [, fieldResult]) => {
|
|
37
|
-
const pathCount =
|
|
38
|
-
fieldResult.leaves?.reduce((leafCount: number, leaf) => {
|
|
39
|
-
return leafCount + (leaf.paths?.length || 1);
|
|
40
|
-
}, 0) || 0;
|
|
41
|
-
return count + pathCount;
|
|
42
|
-
}, 0);
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<div>
|
|
46
|
-
{field_names.length > 0 && (
|
|
47
|
-
<>
|
|
48
|
-
<EuiText size="xs" color="subdued">
|
|
49
|
-
Looking for{' '}
|
|
50
|
-
{field_names.map((name, idx) => (
|
|
51
|
-
<React.Fragment key={name}>
|
|
52
|
-
{idx > 0 && ', '}
|
|
53
|
-
<WfoBadge color="hollow" textColor="default">
|
|
54
|
-
{name}
|
|
55
|
-
</WfoBadge>
|
|
56
|
-
</React.Fragment>
|
|
57
|
-
))}
|
|
58
|
-
</EuiText>
|
|
59
|
-
<EuiSpacer size="s" />
|
|
60
|
-
</>
|
|
61
|
-
)}
|
|
62
|
-
|
|
63
|
-
{result && totalPaths > 0 && (
|
|
64
|
-
<div>
|
|
65
|
-
<EuiText size="xs" color="subdued">
|
|
66
|
-
<strong>
|
|
67
|
-
Found {totalPaths} path
|
|
68
|
-
{totalPaths > 1 ? 's' : ''}:
|
|
69
|
-
</strong>
|
|
70
|
-
</EuiText>
|
|
71
|
-
<EuiSpacer size="xs" />
|
|
72
|
-
{foundFields.map(([fieldName, fieldResult]) => (
|
|
73
|
-
<div key={fieldName} style={{ marginBottom: '8px' }}>
|
|
74
|
-
{fieldResult.leaves
|
|
75
|
-
&& fieldResult.leaves.length > 0
|
|
76
|
-
&& fieldResult.leaves.map((leaf, leafIdx: number) => {
|
|
77
|
-
const paths = leaf.paths || (leaf.name ? [leaf.name] : []);
|
|
78
|
-
return (
|
|
79
|
-
<React.Fragment key={leafIdx}>
|
|
80
|
-
{paths.map((path: string, pathIdx: number) => (
|
|
81
|
-
<div
|
|
82
|
-
key={pathIdx}
|
|
83
|
-
style={{
|
|
84
|
-
marginBottom: '4px',
|
|
85
|
-
}}
|
|
86
|
-
>
|
|
87
|
-
<WfoPathBreadcrumb path={path} size="s" />
|
|
88
|
-
</div>
|
|
89
|
-
))}
|
|
90
|
-
</React.Fragment>
|
|
91
|
-
);
|
|
92
|
-
})}
|
|
93
|
-
</div>
|
|
94
|
-
))}
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
</div>
|
|
98
|
-
);
|
|
99
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
|
|
3
|
-
import { WfoThemeHelpers } from '@/hooks';
|
|
4
|
-
|
|
5
|
-
export const getFilterDisplayStyles = ({ theme }: WfoThemeHelpers) => {
|
|
6
|
-
const wrapStyle = css({
|
|
7
|
-
display: 'flex',
|
|
8
|
-
flexWrap: 'wrap',
|
|
9
|
-
gap: theme.size.s,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const columnGroupWrapStyle = css({
|
|
13
|
-
display: 'flex',
|
|
14
|
-
flexDirection: 'column',
|
|
15
|
-
gap: theme.size.s,
|
|
16
|
-
alignItems: 'flex-start',
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const chipStyle = css({
|
|
20
|
-
display: 'inline-flex',
|
|
21
|
-
alignItems: 'center',
|
|
22
|
-
borderRadius: theme.size.xl,
|
|
23
|
-
border: `1px solid ${theme.border.color}`,
|
|
24
|
-
backgroundColor: theme.colors.backgroundBasePlain,
|
|
25
|
-
padding: `${theme.size.s} ${theme.size.m}`,
|
|
26
|
-
lineHeight: 1.1,
|
|
27
|
-
gap: theme.size.s,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const groupStyle = css({
|
|
31
|
-
border: `1px solid ${theme.colors.borderBaseSubdued}`,
|
|
32
|
-
borderRadius: theme.border.radius.medium,
|
|
33
|
-
padding: theme.size.s,
|
|
34
|
-
margin: theme.size.xs,
|
|
35
|
-
backgroundColor: theme.colors.backgroundBasePlain,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const operatorStyle = css({
|
|
39
|
-
fontFamily: theme.font.familyCode,
|
|
40
|
-
padding: `${theme.size.xs}px ${theme.size.s}px`,
|
|
41
|
-
borderRadius: theme.size.s,
|
|
42
|
-
backgroundColor: theme.colors.primary,
|
|
43
|
-
color: theme.colors.textGhost,
|
|
44
|
-
fontSize: theme.size.m,
|
|
45
|
-
fontWeight: theme.font.weight.bold,
|
|
46
|
-
margin: `${theme.size.xs} 0`,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const valueStyle = css({
|
|
50
|
-
fontWeight: theme.font.weight.semiBold,
|
|
51
|
-
color: theme.colors.warning,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
wrapStyle,
|
|
56
|
-
columnGroupWrapStyle,
|
|
57
|
-
chipStyle,
|
|
58
|
-
groupStyle,
|
|
59
|
-
operatorStyle,
|
|
60
|
-
valueStyle,
|
|
61
|
-
};
|
|
62
|
-
};
|