Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add deletion to Workflow List page table #90

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion public/pages/workflows/workflow_list/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React from 'react';
import { EuiLink } from '@elastic/eui';
import { PLUGIN_ID, Workflow } from '../../../../common';

export const columns = [
export const columns = (actions: any[]) => [
{
field: 'name',
name: 'Name',
Expand Down Expand Up @@ -36,4 +36,8 @@ export const columns = [
name: 'Last launched',
sortable: true,
},
{
name: 'Actions',
actions,
},
];
35 changes: 30 additions & 5 deletions public/pages/workflows/workflow_list/workflow_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { debounce } from 'lodash';
import {
EuiInMemoryTable,
Expand All @@ -13,8 +13,9 @@ import {
EuiFlexItem,
EuiFilterSelectItem,
EuiFieldSearch,
EuiLoadingSpinner,
} from '@elastic/eui';
import { AppState } from '../../../store';
import { AppState, deleteWorkflow } from '../../../store';
import { Workflow } from '../../../../common';
import { columns } from './columns';
import { MultiSelectFilter } from '../../../general_components';
Expand All @@ -33,7 +34,10 @@ const sorting = {
* The searchable list of created workflows.
*/
export function WorkflowList(props: WorkflowListProps) {
const { workflows } = useSelector((state: AppState) => state.workflows);
const dispatch = useDispatch();
const { workflows, loading } = useSelector(
(state: AppState) => state.workflows
);

// search bar state
const [searchQuery, setSearchQuery] = useState<string>('');
Expand All @@ -58,6 +62,19 @@ export function WorkflowList(props: WorkflowListProps) {
);
}, [selectedStates, searchQuery, workflows]);

const tableActions = [
{
name: 'Delete',
description: 'Delete this workflow',
type: 'icon',
icon: 'trash',
color: 'danger',
onClick: (item: Workflow) => {
dispatch(deleteWorkflow(item.id));
},
},
];

return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
Expand All @@ -80,10 +97,18 @@ export function WorkflowList(props: WorkflowListProps) {
<EuiInMemoryTable<Workflow>
items={filteredWorkflows}
rowHeader="name"
columns={columns}
// @ts-ignore
columns={columns(tableActions)}
sorting={sorting}
pagination={true}
message={'No existing workflows found'}
message={
loading === true ? (
<EuiLoadingSpinner size="xl" />
) : (
'No existing workflows found'
)
}
hasActions={true}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
7 changes: 7 additions & 0 deletions public/pages/workflows/workflows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ export function Workflows(props: WorkflowsProps) {
}
}, [selectedTabId, workflows]);

// If the user navigates back to the manage tab, re-fetch workflows
useEffect(() => {
if (selectedTabId === WORKFLOWS_TAB.MANAGE) {
dispatch(searchWorkflows({ query: { match_all: {} } }));
}
}, [selectedTabId]);

useEffect(() => {
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.FLOW_FRAMEWORK,
Expand Down
8 changes: 2 additions & 6 deletions public/store/reducers/workflows_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,8 @@ const workflowsSlice = createSlice({
state.errorMessage = '';
})
.addCase(deleteWorkflow.fulfilled, (state, action) => {
// TODO: add logic to mutate state
// const workflow = action.payload;
// state.workflows = {
// ...state.workflows,
// [workflow.id]: workflow,
// };
const workflowId = action.payload.id;
delete state.workflows[workflowId];
state.loading = false;
state.errorMessage = '';
})
Expand Down
9 changes: 2 additions & 7 deletions server/routes/flow_framework_routes_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@
req: OpenSearchDashboardsRequest,
res: OpenSearchDashboardsResponseFactory
): Promise<IOpenSearchDashboardsResponse<any>> => {
const { workflow_id } = req.params as { workflow_id: string };

Check failure on line 101 in server/routes/flow_framework_routes_service.ts

View workflow job for this annotation

GitHub Actions / Run lint script

Variable name `workflow_id` must match one of the following formats: camelCase, UPPER_CASE, PascalCase
try {
const response = await this.client
.asScoped(req)
.callAsCurrentUser('flowFramework.getWorkflow', { workflow_id });
console.log('response from get workflow: ', response);

Check failure on line 106 in server/routes/flow_framework_routes_service.ts

View workflow job for this annotation

GitHub Actions / Run lint script

Unexpected console statement
// TODO: format response
return res.ok({ body: response });
} catch (err: any) {
Expand Down Expand Up @@ -147,12 +147,12 @@
req: OpenSearchDashboardsRequest,
res: OpenSearchDashboardsResponseFactory
): Promise<IOpenSearchDashboardsResponse<any>> => {
const { workflow_id } = req.params as { workflow_id: string };

Check failure on line 150 in server/routes/flow_framework_routes_service.ts

View workflow job for this annotation

GitHub Actions / Run lint script

Variable name `workflow_id` must match one of the following formats: camelCase, UPPER_CASE, PascalCase
try {
const response = await this.client
.asScoped(req)
.callAsCurrentUser('flowFramework.getWorkflowState', { workflow_id });
console.log('response from get workflow state: ', response);

Check failure on line 155 in server/routes/flow_framework_routes_service.ts

View workflow job for this annotation

GitHub Actions / Run lint script

Unexpected console statement
// TODO: format response
return res.ok({ body: response });
} catch (err: any) {
Expand All @@ -172,28 +172,23 @@
const response = await this.client
.asScoped(req)
.callAsCurrentUser('flowFramework.createWorkflow', { body });
console.log('response from create workflow: ', response);
// TODO: format response
return res.ok({ body: response });
return res.ok({ body: { id: response._id } });
} catch (err: any) {
return generateCustomError(res, err);
}
};

// TODO: test e2e
deleteWorkflow = async (
context: RequestHandlerContext,
req: OpenSearchDashboardsRequest,
res: OpenSearchDashboardsResponseFactory
): Promise<IOpenSearchDashboardsResponse<any>> => {
const { workflow_id } = req.params as { workflow_id: string };

Check failure on line 186 in server/routes/flow_framework_routes_service.ts

View workflow job for this annotation

GitHub Actions / Run lint script

Variable name `workflow_id` must match one of the following formats: camelCase, UPPER_CASE, PascalCase
try {
const response = await this.client
.asScoped(req)
.callAsCurrentUser('flowFramework.deleteWorkflow', { workflow_id });
console.log('response from delete workflow: ', response);
// TODO: format response
return res.ok({ body: response });
return res.ok({ body: { id: response._id } });
} catch (err: any) {
return generateCustomError(res, err);
}
Expand Down
22 changes: 12 additions & 10 deletions server/routes/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,20 @@
workflowHits.forEach((workflowHit: any) => {
workflowDict[workflowHit._id] = toWorkflowObj(workflowHit);
const workflowStateHit = workflowStateHits.find(
(workflowStateHit) => workflowStateHit._id === workflowHit._id

Check failure on line 51 in server/routes/helpers.ts

View workflow job for this annotation

GitHub Actions / Run lint script

'workflowStateHit' is already declared in the upper scope
);
const workflowState = workflowStateHit._source
.state as typeof WORKFLOW_STATE;
workflowDict[workflowHit._id] = {
...workflowDict[workflowHit._id],
// @ts-ignore
state: WORKFLOW_STATE[workflowState],
// TODO: this needs to be persisted by backend. Tracking issue:
// https://github.com/opensearch-project/flow-framework/issues/548
lastLaunched: 1234,
};
if (workflowStateHit) {
const workflowState = workflowStateHit._source
.state as typeof WORKFLOW_STATE;
workflowDict[workflowHit._id] = {
...workflowDict[workflowHit._id],
// @ts-ignore
state: WORKFLOW_STATE[workflowState],
// TODO: this needs to be persisted by backend. Tracking issue:
// https://github.com/opensearch-project/flow-framework/issues/548
lastLaunched: 1234,
};
}
});
return workflowDict;
}
Loading