Skip to content

Commit d04e593

Browse files
committed
Onboard initial flow framework APIs
Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com>
1 parent 569b500 commit d04e593

13 files changed

+524
-161
lines changed

common/constants.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,26 @@
55

66
export const PLUGIN_ID = 'flow-framework';
77

8+
/**
9+
* BACKEND/CLUSTER APIs
10+
*/
11+
export const FLOW_FRAMEWORK_API_ROUTE_PREFIX = '/_plugins/_flow_framework';
12+
export const FLOW_FRAMEWORK_WORKFLOW_ROUTE_PREFIX = `${FLOW_FRAMEWORK_API_ROUTE_PREFIX}/workflow`;
13+
export const FLOW_FRAMEWORK_SEARCH_WORKFLOWS_ROUTE = `${FLOW_FRAMEWORK_WORKFLOW_ROUTE_PREFIX}/_search`;
14+
15+
/**
16+
* NODE APIs
17+
*/
818
export const BASE_NODE_API_PATH = '/api/flow_framework';
919

10-
// OpenSearch APIs
11-
export const BASE_INDICES_NODE_API_PATH = `${BASE_NODE_API_PATH}/indices`;
12-
export const SEARCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/search`;
13-
export const FETCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/fetch`;
20+
// OpenSearch node APIs
21+
export const BASE_OPENSEARCH_NODE_API_PATH = `${BASE_NODE_API_PATH}/opensearch`;
22+
export const CAT_INDICES_NODE_API_PATH = `${BASE_OPENSEARCH_NODE_API_PATH}/catIndices`;
1423

15-
// Flow Framework APIs
24+
// Flow Framework node APIs
1625
export const BASE_WORKFLOW_NODE_API_PATH = `${BASE_NODE_API_PATH}/workflow`;
17-
export const GET_WORKFLOW_PATH = `${BASE_WORKFLOW_NODE_API_PATH}`;
18-
export const CREATE_WORKFLOW_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/create`;
26+
export const GET_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}`;
27+
export const SEARCH_WORKFLOWS_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/search`;
28+
export const GET_WORKFLOW_STATE_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/state`;
29+
export const CREATE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/create`;
30+
export const DELETE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/delete`;

common/interfaces.ts

+4
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,7 @@ export enum WORKFLOW_STATE {
102102
IN_PROGRESS = 'In progress',
103103
NOT_STARTED = 'Not started',
104104
}
105+
106+
export type WorkflowDict = {
107+
[workflowId: string]: Workflow;
108+
};

public/pages/workflows/workflow_list/workflow_list.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -34,28 +34,29 @@ const sorting = {
3434
*/
3535
export function WorkflowList(props: WorkflowListProps) {
3636
const { workflows } = useSelector((state: AppState) => state.workflows);
37-
const workflowsAsList = Object.values(workflows);
3837

3938
// search bar state
4039
const [searchQuery, setSearchQuery] = useState<string>('');
4140
const debounceSearchQuery = debounce((query: string) => {
4241
setSearchQuery(query);
43-
}, 100);
42+
}, 200);
4443

4544
// filters state
4645
const [selectedStates, setSelectedStates] = useState<EuiFilterSelectItem[]>(
4746
getStateOptions()
4847
);
49-
const [filteredWorkflows, setFilteredWorkflows] = useState<Workflow[]>(
50-
workflowsAsList || []
51-
);
48+
const [filteredWorkflows, setFilteredWorkflows] = useState<Workflow[]>([]);
5249

53-
// When a filter selection or search query changes, update the list
50+
// When any filter changes or new workflows are found, update the list
5451
useEffect(() => {
5552
setFilteredWorkflows(
56-
fetchFilteredWorkflows(workflowsAsList, selectedStates, searchQuery)
53+
fetchFilteredWorkflows(
54+
Object.values(workflows),
55+
selectedStates,
56+
searchQuery
57+
)
5758
);
58-
}, [selectedStates, searchQuery]);
59+
}, [selectedStates, searchQuery, workflows]);
5960

6061
return (
6162
<EuiFlexGroup direction="column">

public/pages/workflows/workflows.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { BREADCRUMBS } from '../../utils';
1919
import { getCore } from '../../services';
2020
import { WorkflowList } from './workflow_list';
2121
import { NewWorkflow } from './new_workflow';
22-
import { AppState, getWorkflow } from '../../store';
22+
import { AppState, searchWorkflows } from '../../store';
2323

2424
export interface WorkflowsRouterProps {}
2525

@@ -79,8 +79,9 @@ export function Workflows(props: WorkflowsProps) {
7979
]);
8080
});
8181

82+
// On initial render: fetch all workflows
8283
useEffect(() => {
83-
dispatch(getWorkflow('dummy-id'));
84+
dispatch(searchWorkflows({ query: { match_all: {} } }));
8485
}, []);
8586

8687
return (

public/route_service.ts

+56-10
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,69 @@
55

66
import { CoreStart, HttpFetchError } from '../../../src/core/public';
77
import {
8-
FETCH_INDICES_PATH,
9-
GET_WORKFLOW_PATH,
10-
SEARCH_INDICES_PATH,
8+
CREATE_WORKFLOW_NODE_API_PATH,
9+
DELETE_WORKFLOW_NODE_API_PATH,
10+
CAT_INDICES_NODE_API_PATH,
11+
GET_WORKFLOW_NODE_API_PATH,
12+
GET_WORKFLOW_STATE_NODE_API_PATH,
13+
SEARCH_WORKFLOWS_NODE_API_PATH,
1114
} from '../common';
1215

16+
/**
17+
* A simple client-side service interface containing all of the available node API functions.
18+
* Exposed in services.ts.
19+
* Example function call: getRouteService().getWorkflow(<workflow-id>)
20+
*
21+
* Used in redux by wrapping them in async thunk functions which mutate redux state when executed.
22+
*/
1323
export interface RouteService {
1424
getWorkflow: (workflowId: string) => Promise<any | HttpFetchError>;
15-
searchIndex: (indexName: string, body: {}) => Promise<any | HttpFetchError>;
16-
fetchIndices: (pattern: string) => Promise<any | HttpFetchError>;
25+
searchWorkflows: (body: {}) => Promise<any | HttpFetchError>;
26+
getWorkflowState: (workflowId: string) => Promise<any | HttpFetchError>;
27+
createWorkflow: (body: {}) => Promise<any | HttpFetchError>;
28+
deleteWorkflow: (workflowId: string) => Promise<any | HttpFetchError>;
29+
catIndices: (pattern: string) => Promise<any | HttpFetchError>;
1730
}
1831

1932
export function configureRoutes(core: CoreStart): RouteService {
2033
return {
2134
getWorkflow: async (workflowId: string) => {
2235
try {
2336
const response = await core.http.get<{ respString: string }>(
24-
`${GET_WORKFLOW_PATH}/${workflowId}`
37+
`${GET_WORKFLOW_NODE_API_PATH}/${workflowId}`
2538
);
2639
return response;
2740
} catch (e: any) {
2841
return e as HttpFetchError;
2942
}
3043
},
31-
searchIndex: async (indexName: string, body: {}) => {
44+
searchWorkflows: async (body: {}) => {
45+
try {
46+
const response = await core.http.post<{ respString: string }>(
47+
SEARCH_WORKFLOWS_NODE_API_PATH,
48+
{
49+
body: JSON.stringify(body),
50+
}
51+
);
52+
return response;
53+
} catch (e: any) {
54+
return e as HttpFetchError;
55+
}
56+
},
57+
getWorkflowState: async (workflowId: string) => {
3258
try {
3359
const response = await core.http.get<{ respString: string }>(
34-
`${SEARCH_INDICES_PATH}/${indexName}`,
60+
`${GET_WORKFLOW_STATE_NODE_API_PATH}/${workflowId}`
61+
);
62+
return response;
63+
} catch (e: any) {
64+
return e as HttpFetchError;
65+
}
66+
},
67+
createWorkflow: async (body: {}) => {
68+
try {
69+
const response = await core.http.post<{ respString: string }>(
70+
CREATE_WORKFLOW_NODE_API_PATH,
3571
{
3672
body: JSON.stringify(body),
3773
}
@@ -41,10 +77,20 @@ export function configureRoutes(core: CoreStart): RouteService {
4177
return e as HttpFetchError;
4278
}
4379
},
44-
fetchIndices: async (pattern: string) => {
80+
deleteWorkflow: async (workflowId: string) => {
81+
try {
82+
const response = await core.http.delete<{ respString: string }>(
83+
`${DELETE_WORKFLOW_NODE_API_PATH}/${workflowId}`
84+
);
85+
return response;
86+
} catch (e: any) {
87+
return e as HttpFetchError;
88+
}
89+
},
90+
catIndices: async (pattern: string) => {
4591
try {
4692
const response = await core.http.get<{ respString: string }>(
47-
`${FETCH_INDICES_PATH}/${pattern}`
93+
`${CAT_INDICES_NODE_API_PATH}/${pattern}`
4894
);
4995
return response;
5096
} catch (e: any) {

public/store/reducers/opensearch_reducer.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ const initialState = {
1515
};
1616

1717
const OPENSEARCH_PREFIX = 'opensearch';
18-
const FETCH_INDICES_ACTION = `${OPENSEARCH_PREFIX}/fetchIndices`;
18+
const CAT_INDICES_ACTION = `${OPENSEARCH_PREFIX}/catIndices`;
1919

20-
export const fetchIndices = createAsyncThunk(
21-
FETCH_INDICES_ACTION,
20+
export const catIndices = createAsyncThunk(
21+
CAT_INDICES_ACTION,
2222
async (pattern: string, { rejectWithValue }) => {
2323
// defaulting to fetch everything except system indices (starting with '.')
2424
const patternString = pattern || '*,-.*';
25-
const response: any | HttpFetchError = await getRouteService().fetchIndices(
25+
const response: any | HttpFetchError = await getRouteService().catIndices(
2626
patternString
2727
);
2828
if (response instanceof HttpFetchError) {
2929
return rejectWithValue(
30-
'Error fetching indices: ' + response.body.message
30+
'Error running cat indices: ' + response.body.message
3131
);
3232
} else {
3333
return response;
@@ -41,11 +41,11 @@ const opensearchSlice = createSlice({
4141
reducers: {},
4242
extraReducers: (builder) => {
4343
builder
44-
.addCase(fetchIndices.pending, (state, action) => {
44+
.addCase(catIndices.pending, (state, action) => {
4545
state.loading = true;
4646
state.errorMessage = '';
4747
})
48-
.addCase(fetchIndices.fulfilled, (state, action) => {
48+
.addCase(catIndices.fulfilled, (state, action) => {
4949
const indicesMap = new Map<string, Index>();
5050
action.payload.forEach((index: Index) => {
5151
indicesMap.set(index.name, index);
@@ -54,7 +54,7 @@ const opensearchSlice = createSlice({
5454
state.loading = false;
5555
state.errorMessage = '';
5656
})
57-
.addCase(fetchIndices.rejected, (state, action) => {
57+
.addCase(catIndices.rejected, (state, action) => {
5858
state.errorMessage = action.payload as string;
5959
state.loading = false;
6060
});

0 commit comments

Comments
 (0)