Skip to content

Commit

Permalink
Add node deletion functionality in Workspace (#59) (#60)
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
(cherry picked from commit 52e5cec)

Co-authored-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
opensearch-trigger-bot[bot] and ohltyler authored Oct 16, 2023
1 parent d2b7d3d commit 6226131
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 18 deletions.
8 changes: 8 additions & 0 deletions public/component_types/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@ export interface IComponent {
createFields?: IComponentField[];
outputs?: IComponentOutput[];
}

/**
* We need to include some extra instance-specific data to the ReactFlow component
* to perform extra functionality, such as deleting the node from the ReactFlowInstance.
*/
export interface IComponentData extends IComponent {
id: string;
}
7 changes: 4 additions & 3 deletions public/pages/workflow_detail/workspace/workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import ReactFlow, {
import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import { rfContext, setDirty } from '../../../store';
import { IComponent, Workflow } from '../../../../common';
import { generateId } from '../../../utils';
import { generateId, initComponentData } from '../../../utils';
import { getCore } from '../../../services';
import { WorkspaceComponent } from '../workspace_component';
import { DeletableEdge } from '../workspace_edge';
Expand Down Expand Up @@ -84,11 +84,12 @@ export function Workspace(props: WorkspaceProps) {

// TODO: remove hardcoded values when more component info is passed in the event.
// Only keep the calculated 'position' field.
const id = generateId(nodeData.type);
const newNode = {
id: generateId(nodeData.type),
id,
type: nodeData.type,
position,
data: nodeData,
data: initComponentData(nodeData, id),
style: {
background: 'white',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiCard } from '@elastic/eui';
import { IComponent } from '../../../component_types';
import React, { useContext } from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiCard,
EuiText,
EuiTitle,
EuiButtonIcon,
} from '@elastic/eui';
import { rfContext } from '../../../store';
import { IComponentData } from '../../../component_types';
import { InputHandle } from './input_handle';
import { OutputHandle } from './output_handle';

interface WorkspaceComponentProps {
data: IComponent;
data: IComponentData;
}

/**
Expand All @@ -20,18 +28,43 @@ interface WorkspaceComponentProps {
*/
export function WorkspaceComponent(props: WorkspaceComponentProps) {
const component = props.data;
const { deleteNode } = useContext(rfContext);

return (
<EuiCard title={component.label}>
<EuiCard
textAlign="left"
title={
<EuiFlexGroup direction="row" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<h3>{component.label}</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType="trash"
onClick={() => {
deleteNode(component.id);
}}
aria-label="Delete"
/>
</EuiFlexItem>
</EuiFlexGroup>
}
>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiText size="s" color="subdued">
{component.description}
</EuiText>
</EuiFlexItem>
{component.inputs?.map((input, index) => {
return (
<EuiFlexItem key={index}>
<InputHandle input={input} data={component} />
</EuiFlexItem>
);
})}
{/* TODO: finalize from UX what we show in the component itself. Readonly fields? Configure in the component JSON definition? */}
{component.outputs?.map((output, index) => {
return (
<EuiFlexItem key={index}>
Expand Down
17 changes: 14 additions & 3 deletions public/store/context/react_flow_context_provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React, { createContext, useState } from 'react';
import { useDispatch } from 'react-redux';
import { Edge } from 'reactflow';
import { Edge, Node } from 'reactflow';
import { setDirty } from '../reducers';

const initialValues = {
Expand All @@ -30,8 +30,19 @@ export function ReactFlowContextProvider({ children }: any) {
const [reactFlowInstance, setReactFlowInstance] = useState(null);

const deleteNode = (nodeId: string) => {
// TODO: implement node deletion
// reactFlowInstance.setNodes(...)
reactFlowInstance.setNodes(
reactFlowInstance.getNodes().filter((node: Node) => node.id !== nodeId)
);
// Also delete any dangling edges attached to the component
reactFlowInstance.setEdges(
reactFlowInstance
.getEdges()
.filter(
(edge: Edge) => edge.source !== nodeId && edge.target !== nodeId
)
);

dispatch(setDirty());
};

const deleteEdge = (edgeId: string) => {
Expand Down
16 changes: 10 additions & 6 deletions public/store/reducers/workflows_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,30 @@ import {
KnnIndex,
TextEmbeddingProcessor,
generateId,
initComponentData,
} from '../../../common';

// TODO: remove after fetching from server-side
const id1 = generateId('text_embedding_processor');
const id2 = generateId('text_embedding_processor');
const id3 = generateId('knn_index');
const dummyNodes = [
{
id: generateId('text_embedding_processor'),
id: id1,
position: { x: 0, y: 500 },
data: new TextEmbeddingProcessor().toObj(),
data: initComponentData(new TextEmbeddingProcessor().toObj(), id1),
type: 'customComponent',
},
{
id: generateId('text_embedding_processor'),
id: id2,
position: { x: 0, y: 200 },
data: new TextEmbeddingProcessor().toObj(),
data: initComponentData(new TextEmbeddingProcessor().toObj(), id2),
type: 'customComponent',
},
{
id: generateId('knn_index'),
id: id3,
position: { x: 500, y: 500 },
data: new KnnIndex().toObj(),
data: initComponentData(new KnnIndex().toObj(), id3),
type: 'customComponent',
},
] as ReactFlowComponent[];
Expand Down
14 changes: 14 additions & 0 deletions public/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { IComponent, IComponentData } from '../../common';

// Append 16 random characters
export function generateId(prefix: string) {
const uniqueChar = () => {
Expand All @@ -11,3 +13,15 @@ export function generateId(prefix: string) {
};
return `${prefix}_${uniqueChar()}${uniqueChar()}${uniqueChar()}${uniqueChar()}`;
}

// Adding any instance metadata. Converting the base IComponent obj into
// an instance-specific IComponentData obj.
export function initComponentData(
data: IComponent,
componentId: string
): IComponentData {
return {
...data,
id: componentId,
} as IComponentData;
}

0 comments on commit 6226131

Please sign in to comment.