Skip to content

Commit

Permalink
Refactor & improve Workflow Builder; connect to redux store (#36) (#41)
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
(cherry picked from commit ea04bce)

Co-authored-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
opensearch-trigger-bot[bot] and ohltyler authored Sep 25, 2023
1 parent 6054b8f commit 660ad90
Show file tree
Hide file tree
Showing 29 changed files with 252 additions and 166 deletions.
1 change: 1 addition & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

export * from './constants';
export * from './interfaces';
export { IComponent } from '../public/component_types';
7 changes: 7 additions & 0 deletions common/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ export interface IIndex {
name: string;
health: 'green' | 'yellow' | 'red';
}

// TODO: this will grow as more fields are defined and what frontend reqts there will be
export interface IWorkflow {
name: string;
id: string;
description: string;
}
25 changes: 13 additions & 12 deletions public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import React from 'react';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { EuiPageSideBar, EuiSideNav, EuiPageTemplate } from '@elastic/eui';
import { Navigation, APP_PATH } from './utils';
import { Overview, UseCases, Workflows, WorkflowBuilder } from './pages';
import {
Overview,
UseCases,
Workflows,
WorkflowDetail,
WorkflowDetailRouterProps,
} from './pages';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Props extends RouteComponentProps {}
Expand All @@ -34,13 +40,6 @@ export const AiFlowDashboardsApp = (props: Props) => {
href: `#${APP_PATH.WORKFLOWS}`,
isSelected: props.location.pathname === APP_PATH.WORKFLOWS,
},
{
name: Navigation.WorkflowBuilder,
id: 3,
href: `#${APP_PATH.WORKFLOW_BUILDER}`,
isSelected:
props.location.pathname === APP_PATH.WORKFLOW_BUILDER,
},
],
},
]}
Expand All @@ -61,12 +60,14 @@ export const AiFlowDashboardsApp = (props: Props) => {
render={(routeProps: RouteComponentProps) => <UseCases />}
/>
<Route
path={APP_PATH.WORKFLOWS}
render={(routeProps: RouteComponentProps) => <Workflows />}
path={APP_PATH.WORKFLOW_DETAIL}
render={(
routeProps: RouteComponentProps<WorkflowDetailRouterProps>
) => <WorkflowDetail {...routeProps} />}
/>
<Route
path={APP_PATH.WORKFLOW_BUILDER}
render={(routeProps: RouteComponentProps) => <WorkflowBuilder />}
path={APP_PATH.WORKFLOWS}
render={(routeProps: RouteComponentProps) => <Workflows />}
/>
{/* Defaulting to Overview page */}
<Route
Expand Down
2 changes: 1 addition & 1 deletion public/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
export * from './use_cases';
export * from './workflows';
export * from './overview';
export * from './workflow_builder';
export * from './workflow_detail';
2 changes: 1 addition & 1 deletion public/pages/use_cases/components/use_case.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function UseCase(props: UseCaseProps) {
disabled={false}
isLoading={false}
onClick={() => {
// TODO: possibly link to the workflow builder with a pre-configured flow
// TODO: possibly link to the workflow details with a pre-configured flow
}}
>
Go
Expand Down
8 changes: 0 additions & 8 deletions public/pages/workflow_builder/components/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions public/pages/workflow_builder/index.ts

This file was deleted.

68 changes: 0 additions & 68 deletions public/pages/workflow_builder/workflow_builder.tsx

This file was deleted.

31 changes: 31 additions & 0 deletions public/pages/workflow_detail/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiPageHeader, EuiButton } from '@elastic/eui';
import { IWorkflow } from '../../../../common';

interface WorkflowDetailHeaderProps {
workflow: IWorkflow | undefined;
}

export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
return (
<div>
<EuiPageHeader
pageTitle={props.workflow ? props.workflow.name : ''}
description={props.workflow ? props.workflow.description : ''}
rightSideItems={[
<EuiButton fill={false} onClick={() => {}}>
Prototype
</EuiButton>,
<EuiButton fill={false} onClick={() => {}}>
Save
</EuiButton>,
]}
/>
</div>
);
}
6 changes: 6 additions & 0 deletions public/pages/workflow_detail/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { WorkflowDetailHeader } from './header';
6 changes: 6 additions & 0 deletions public/pages/workflow_detail/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './workflow_detail';
47 changes: 47 additions & 0 deletions public/pages/workflow_detail/workflow_detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useEffect } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { EuiSpacer } from '@elastic/eui';
import { BREADCRUMBS } from '../../utils';
import { getCore } from '../../services';
import { WorkflowDetailHeader } from './components';
import { Workspace } from './workspace';
import { AppState } from '../../store';

export interface WorkflowDetailRouterProps {
workflowId: string;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface WorkflowDetailProps
extends RouteComponentProps<WorkflowDetailRouterProps> {}

export function WorkflowDetail(props: WorkflowDetailProps) {
const { workflows } = useSelector((state: AppState) => state.workflows);

const workflow = workflows.find(
(wf) => wf.id === props.match?.params?.workflowId
);
const workflowName = workflow ? workflow.name : '';

useEffect(() => {
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.AI_APPLICATION_BUILDER,
BREADCRUMBS.WORKFLOWS,
{ text: workflowName },
]);
});

return (
<div>
<WorkflowDetailHeader workflow={workflow} />
<EuiSpacer size="l" />
<Workspace />
</div>
);
}
6 changes: 6 additions & 0 deletions public/pages/workflow_detail/workspace/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { Workspace } from './workspace';
26 changes: 26 additions & 0 deletions public/pages/workflow_detail/workspace/workspace.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { useSelector } from 'react-redux';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { AppState } from '../../../store';
import { WorkspaceComponent } from '../workspace_component';

export function Workspace() {
const { components } = useSelector((state: AppState) => state.workspace);

return (
<EuiFlexGroup direction="row">
{components.map((component, idx) => {
return (
<EuiFlexItem key={idx}>
<WorkspaceComponent component={component} />
</EuiFlexItem>
);
})}
</EuiFlexGroup>
);
}
6 changes: 6 additions & 0 deletions public/pages/workflow_detail/workspace_component/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { WorkspaceComponent } from './workspace_component';
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import {
EuiSpacer,
EuiCard,
} from '@elastic/eui';
import { IComponent } from '../../component_types';
import { InputFieldList, NewOrExistingTabs } from './components';
import { IComponent } from '../../../component_types';
import { InputFieldList } from './input_field_list';
import { NewOrExistingTabs } from './new_or_existing_tabs';

interface WorkflowComponentProps {
interface WorkspaceComponentProps {
component: IComponent;
}

Expand All @@ -24,7 +25,7 @@ interface WorkflowComponentProps {
* Similar to Flowise's CanvasNode - see
* https://github.com/FlowiseAI/Flowise/blob/main/packages/ui/src/views/canvas/CanvasNode.js
*/
export function WorkflowComponent(props: WorkflowComponentProps) {
export function WorkspaceComponent(props: WorkspaceComponentProps) {
const { component } = props;

const [selectedTabId, setSelectedTabId] = useState<string>('existing');
Expand Down
29 changes: 29 additions & 0 deletions public/pages/workflows/components/columns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiLink } from '@elastic/eui';
import { PLUGIN_ID, IWorkflow } from '../../../../common';

export const columns = [
{
field: 'name',
name: 'Name',
sortable: true,
render: (name: string, workflow: IWorkflow) => (
<EuiLink href={`${PLUGIN_ID}#/workflows/${workflow.id}`}>{name}</EuiLink>
),
},
{
field: 'id',
name: 'ID',
sortable: true,
},
{
field: 'description',
name: 'Description',
sortable: false,
},
];
Loading

0 comments on commit 660ad90

Please sign in to comment.