Skip to content

Commit 5a8fb42

Browse files
committed
wip
1 parent d6f84b8 commit 5a8fb42

4 files changed

Lines changed: 546 additions & 353 deletions

File tree

src/platform/plugins/shared/workflows_management/public/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
*/
99

1010
export { WorkflowsEmptyState } from './workflows_empty_state';
11+
export { WorkflowSelector } from './workflow_selector';
12+
export { useWorkflowSelection } from './use_workflow_selection';
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import { useCallback, useEffect, useState } from 'react';
11+
import { useKibana } from '@kbn/kibana-react-plugin/public';
12+
import type { WorkflowListDto } from '@kbn/workflows';
13+
14+
export interface WorkflowOption {
15+
id: string;
16+
name: string;
17+
description: string;
18+
enabled: boolean;
19+
tags: string[];
20+
label: string;
21+
disabled?: boolean;
22+
checked?: 'on' | 'off';
23+
prepend?: React.ReactNode;
24+
append?: React.ReactNode;
25+
data?: {
26+
secondaryContent?: string;
27+
};
28+
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
29+
}
30+
31+
export interface WorkflowSelectionConfig {
32+
filterFunction?: (workflow: any) => boolean; // eslint-disable-line @typescript-eslint/no-explicit-any
33+
sortFunction?: (a: any, b: any) => number; // eslint-disable-line @typescript-eslint/no-explicit-any
34+
selectedWorkflowId?: string;
35+
}
36+
37+
export interface WorkflowSelectionState {
38+
workflows: WorkflowOption[];
39+
isLoading: boolean;
40+
loadError: string | null;
41+
selectedWorkflowDisabledError: string | null;
42+
}
43+
44+
export interface WorkflowSelectionActions {
45+
onWorkflowChange: (
46+
newOptions: WorkflowOption[],
47+
event: unknown,
48+
changedOption: WorkflowOption
49+
) => void;
50+
refreshWorkflows: () => void;
51+
}
52+
53+
export const useWorkflowSelection = (
54+
config: WorkflowSelectionConfig = {}
55+
): WorkflowSelectionState & WorkflowSelectionActions => {
56+
const { filterFunction, sortFunction, selectedWorkflowId } = config;
57+
const [workflows, setWorkflows] = useState<WorkflowOption[]>([]);
58+
const [isLoading, setIsLoading] = useState(false);
59+
const [loadError, setLoadError] = useState<string | null>(null);
60+
const [selectedWorkflowDisabledError, setSelectedWorkflowDisabledError] = useState<string | null>(
61+
null
62+
);
63+
const { http } = useKibana().services;
64+
65+
const fetchWorkflows = useCallback(async () => {
66+
if (!http) {
67+
return;
68+
}
69+
70+
setIsLoading(true);
71+
setLoadError(null);
72+
73+
try {
74+
const response = await http.post('/api/workflows/search', {
75+
body: JSON.stringify({
76+
limit: 1000,
77+
page: 1,
78+
query: '',
79+
}),
80+
});
81+
const workflowsMap = response as WorkflowListDto;
82+
83+
// Check if the currently selected workflow is disabled
84+
let hasSelectedWorkflowDisabled = false;
85+
86+
const workflowOptionsWithSortInfo = workflowsMap.results.map((workflow) => {
87+
const isDisabled = !workflow.enabled;
88+
const isSelected = workflow.id === selectedWorkflowId;
89+
const wasSelectedButNowDisabled = isSelected && isDisabled;
90+
91+
// Track if selected workflow is disabled
92+
if (wasSelectedButNowDisabled) {
93+
hasSelectedWorkflowDisabled = true;
94+
}
95+
96+
// Apply custom filter if provided
97+
const passesFilter = filterFunction ? filterFunction(workflow) : true;
98+
99+
const workflowTags = workflow.definition?.tags || [];
100+
101+
return {
102+
workflowOption: {
103+
id: workflow.id,
104+
name: workflow.name,
105+
description: workflow.description,
106+
enabled: workflow.enabled,
107+
tags: workflowTags,
108+
label: workflow.name,
109+
disabled: isDisabled,
110+
checked: isSelected ? 'on' : undefined,
111+
data: {
112+
secondaryContent: workflow.description,
113+
},
114+
// Store additional data for the UI components to use
115+
wasSelectedButNowDisabled,
116+
isDisabled,
117+
} as WorkflowOption,
118+
passesFilter,
119+
workflow,
120+
};
121+
});
122+
123+
// Apply filter
124+
const filteredWorkflowOptions = workflowOptionsWithSortInfo.filter(
125+
(item) => item.passesFilter
126+
);
127+
128+
// Apply custom sort if provided
129+
const sortedWorkflowOptions = sortFunction
130+
? filteredWorkflowOptions.sort((a, b) => sortFunction(a.workflow, b.workflow))
131+
: filteredWorkflowOptions;
132+
133+
// Extract just the workflow options for the component
134+
const workflowOptions = sortedWorkflowOptions.map((item) => item.workflowOption);
135+
136+
// Set error state if selected workflow is disabled
137+
if (hasSelectedWorkflowDisabled) {
138+
setSelectedWorkflowDisabledError(
139+
'The previously selected workflow is no longer available. Please select a different workflow.'
140+
);
141+
} else {
142+
setSelectedWorkflowDisabledError(null);
143+
}
144+
145+
setWorkflows(workflowOptions);
146+
} catch (error) {
147+
setLoadError('Failed to load workflows. Please check your connector configuration.');
148+
} finally {
149+
setIsLoading(false);
150+
}
151+
}, [http, filterFunction, sortFunction, selectedWorkflowId]);
152+
153+
const onWorkflowChange = useCallback(
154+
(newOptions: WorkflowOption[], event: unknown, changedOption: WorkflowOption) => {
155+
setWorkflows(newOptions);
156+
// Clear the disabled workflow error when a new workflow is selected
157+
setSelectedWorkflowDisabledError(null);
158+
},
159+
[]
160+
);
161+
162+
const refreshWorkflows = useCallback(() => {
163+
fetchWorkflows();
164+
}, [fetchWorkflows]);
165+
166+
useEffect(() => {
167+
fetchWorkflows();
168+
}, [fetchWorkflows]);
169+
170+
return {
171+
workflows,
172+
isLoading,
173+
loadError,
174+
selectedWorkflowDisabledError,
175+
onWorkflowChange,
176+
refreshWorkflows,
177+
};
178+
};

0 commit comments

Comments
 (0)