Skip to content

Commit

Permalink
Onboard initial flow framework APIs
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler committed Feb 28, 2024
1 parent 569b500 commit d04e593
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 161 deletions.
26 changes: 19 additions & 7 deletions common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@

export const PLUGIN_ID = 'flow-framework';

/**
* BACKEND/CLUSTER APIs
*/
export const FLOW_FRAMEWORK_API_ROUTE_PREFIX = '/_plugins/_flow_framework';
export const FLOW_FRAMEWORK_WORKFLOW_ROUTE_PREFIX = `${FLOW_FRAMEWORK_API_ROUTE_PREFIX}/workflow`;
export const FLOW_FRAMEWORK_SEARCH_WORKFLOWS_ROUTE = `${FLOW_FRAMEWORK_WORKFLOW_ROUTE_PREFIX}/_search`;

/**
* NODE APIs
*/
export const BASE_NODE_API_PATH = '/api/flow_framework';

// OpenSearch APIs
export const BASE_INDICES_NODE_API_PATH = `${BASE_NODE_API_PATH}/indices`;
export const SEARCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/search`;
export const FETCH_INDICES_PATH = `${BASE_INDICES_NODE_API_PATH}/fetch`;
// OpenSearch node APIs
export const BASE_OPENSEARCH_NODE_API_PATH = `${BASE_NODE_API_PATH}/opensearch`;
export const CAT_INDICES_NODE_API_PATH = `${BASE_OPENSEARCH_NODE_API_PATH}/catIndices`;

// Flow Framework APIs
// Flow Framework node APIs
export const BASE_WORKFLOW_NODE_API_PATH = `${BASE_NODE_API_PATH}/workflow`;
export const GET_WORKFLOW_PATH = `${BASE_WORKFLOW_NODE_API_PATH}`;
export const CREATE_WORKFLOW_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/create`;
export const GET_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}`;
export const SEARCH_WORKFLOWS_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/search`;
export const GET_WORKFLOW_STATE_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/state`;
export const CREATE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/create`;
export const DELETE_WORKFLOW_NODE_API_PATH = `${BASE_WORKFLOW_NODE_API_PATH}/delete`;
4 changes: 4 additions & 0 deletions common/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ export enum WORKFLOW_STATE {
IN_PROGRESS = 'In progress',
NOT_STARTED = 'Not started',
}

export type WorkflowDict = {
[workflowId: string]: Workflow;
};
17 changes: 9 additions & 8 deletions public/pages/workflows/workflow_list/workflow_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,29 @@ const sorting = {
*/
export function WorkflowList(props: WorkflowListProps) {
const { workflows } = useSelector((state: AppState) => state.workflows);
const workflowsAsList = Object.values(workflows);

// search bar state
const [searchQuery, setSearchQuery] = useState<string>('');
const debounceSearchQuery = debounce((query: string) => {
setSearchQuery(query);
}, 100);
}, 200);

// filters state
const [selectedStates, setSelectedStates] = useState<EuiFilterSelectItem[]>(
getStateOptions()
);
const [filteredWorkflows, setFilteredWorkflows] = useState<Workflow[]>(
workflowsAsList || []
);
const [filteredWorkflows, setFilteredWorkflows] = useState<Workflow[]>([]);

// When a filter selection or search query changes, update the list
// When any filter changes or new workflows are found, update the list
useEffect(() => {
setFilteredWorkflows(
fetchFilteredWorkflows(workflowsAsList, selectedStates, searchQuery)
fetchFilteredWorkflows(
Object.values(workflows),
selectedStates,
searchQuery
)
);
}, [selectedStates, searchQuery]);
}, [selectedStates, searchQuery, workflows]);

return (
<EuiFlexGroup direction="column">
Expand Down
5 changes: 3 additions & 2 deletions public/pages/workflows/workflows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { BREADCRUMBS } from '../../utils';
import { getCore } from '../../services';
import { WorkflowList } from './workflow_list';
import { NewWorkflow } from './new_workflow';
import { AppState, getWorkflow } from '../../store';
import { AppState, searchWorkflows } from '../../store';

export interface WorkflowsRouterProps {}

Expand Down Expand Up @@ -79,8 +79,9 @@ export function Workflows(props: WorkflowsProps) {
]);
});

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

return (
Expand Down
66 changes: 56 additions & 10 deletions public/route_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,69 @@

import { CoreStart, HttpFetchError } from '../../../src/core/public';
import {
FETCH_INDICES_PATH,
GET_WORKFLOW_PATH,
SEARCH_INDICES_PATH,
CREATE_WORKFLOW_NODE_API_PATH,
DELETE_WORKFLOW_NODE_API_PATH,
CAT_INDICES_NODE_API_PATH,
GET_WORKFLOW_NODE_API_PATH,
GET_WORKFLOW_STATE_NODE_API_PATH,
SEARCH_WORKFLOWS_NODE_API_PATH,
} from '../common';

/**
* A simple client-side service interface containing all of the available node API functions.
* Exposed in services.ts.
* Example function call: getRouteService().getWorkflow(<workflow-id>)
*
* Used in redux by wrapping them in async thunk functions which mutate redux state when executed.
*/
export interface RouteService {
getWorkflow: (workflowId: string) => Promise<any | HttpFetchError>;
searchIndex: (indexName: string, body: {}) => Promise<any | HttpFetchError>;
fetchIndices: (pattern: string) => Promise<any | HttpFetchError>;
searchWorkflows: (body: {}) => Promise<any | HttpFetchError>;
getWorkflowState: (workflowId: string) => Promise<any | HttpFetchError>;
createWorkflow: (body: {}) => Promise<any | HttpFetchError>;
deleteWorkflow: (workflowId: string) => Promise<any | HttpFetchError>;
catIndices: (pattern: string) => Promise<any | HttpFetchError>;
}

export function configureRoutes(core: CoreStart): RouteService {
return {
getWorkflow: async (workflowId: string) => {
try {
const response = await core.http.get<{ respString: string }>(
`${GET_WORKFLOW_PATH}/${workflowId}`
`${GET_WORKFLOW_NODE_API_PATH}/${workflowId}`
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
searchIndex: async (indexName: string, body: {}) => {
searchWorkflows: async (body: {}) => {
try {
const response = await core.http.post<{ respString: string }>(
SEARCH_WORKFLOWS_NODE_API_PATH,
{
body: JSON.stringify(body),
}
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
getWorkflowState: async (workflowId: string) => {
try {
const response = await core.http.get<{ respString: string }>(
`${SEARCH_INDICES_PATH}/${indexName}`,
`${GET_WORKFLOW_STATE_NODE_API_PATH}/${workflowId}`
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
createWorkflow: async (body: {}) => {
try {
const response = await core.http.post<{ respString: string }>(
CREATE_WORKFLOW_NODE_API_PATH,
{
body: JSON.stringify(body),
}
Expand All @@ -41,10 +77,20 @@ export function configureRoutes(core: CoreStart): RouteService {
return e as HttpFetchError;
}
},
fetchIndices: async (pattern: string) => {
deleteWorkflow: async (workflowId: string) => {
try {
const response = await core.http.delete<{ respString: string }>(
`${DELETE_WORKFLOW_NODE_API_PATH}/${workflowId}`
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
catIndices: async (pattern: string) => {
try {
const response = await core.http.get<{ respString: string }>(
`${FETCH_INDICES_PATH}/${pattern}`
`${CAT_INDICES_NODE_API_PATH}/${pattern}`
);
return response;
} catch (e: any) {
Expand Down
16 changes: 8 additions & 8 deletions public/store/reducers/opensearch_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ const initialState = {
};

const OPENSEARCH_PREFIX = 'opensearch';
const FETCH_INDICES_ACTION = `${OPENSEARCH_PREFIX}/fetchIndices`;
const CAT_INDICES_ACTION = `${OPENSEARCH_PREFIX}/catIndices`;

export const fetchIndices = createAsyncThunk(
FETCH_INDICES_ACTION,
export const catIndices = createAsyncThunk(
CAT_INDICES_ACTION,
async (pattern: string, { rejectWithValue }) => {
// defaulting to fetch everything except system indices (starting with '.')
const patternString = pattern || '*,-.*';
const response: any | HttpFetchError = await getRouteService().fetchIndices(
const response: any | HttpFetchError = await getRouteService().catIndices(
patternString
);
if (response instanceof HttpFetchError) {
return rejectWithValue(
'Error fetching indices: ' + response.body.message
'Error running cat indices: ' + response.body.message
);
} else {
return response;
Expand All @@ -41,11 +41,11 @@ const opensearchSlice = createSlice({
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchIndices.pending, (state, action) => {
.addCase(catIndices.pending, (state, action) => {
state.loading = true;
state.errorMessage = '';
})
.addCase(fetchIndices.fulfilled, (state, action) => {
.addCase(catIndices.fulfilled, (state, action) => {
const indicesMap = new Map<string, Index>();
action.payload.forEach((index: Index) => {
indicesMap.set(index.name, index);
Expand All @@ -54,7 +54,7 @@ const opensearchSlice = createSlice({
state.loading = false;
state.errorMessage = '';
})
.addCase(fetchIndices.rejected, (state, action) => {
.addCase(catIndices.rejected, (state, action) => {
state.errorMessage = action.payload as string;
state.loading = false;
});
Expand Down
Loading

0 comments on commit d04e593

Please sign in to comment.