Skip to content

Commit

Permalink
Clean up obj serialization; use setDirty();
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler committed Oct 3, 2023
1 parent d3e74c7 commit b911754
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 27 deletions.
15 changes: 15 additions & 0 deletions public/component_types/base_component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

/**
* A base component class.
*/
export abstract class BaseComponent {
// Persist a standard toObj() fn that all component classes can use. This is necessary
// so we have standard JS Object when serializing comoponent state in redux.
toObj() {
return Object.assign({}, this);
}
}
4 changes: 3 additions & 1 deletion public/component_types/indices/knn_index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { COMPONENT_CATEGORY, COMPONENT_CLASS } from '../../utils';
import { BaseComponent } from '../base_component';
import {
IComponent,
IComponentField,
Expand All @@ -15,7 +16,7 @@ import {
/**
* A k-NN index UI component
*/
export class KnnIndex implements IComponent {
export class KnnIndex extends BaseComponent implements IComponent {
type: COMPONENT_CLASS;
label: string;
description: string;
Expand All @@ -30,6 +31,7 @@ export class KnnIndex implements IComponent {
outputs: IComponentOutput[];

constructor() {
super();
this.type = COMPONENT_CLASS.KNN_INDEX;
this.label = 'k-NN Index';
this.description = 'A k-NN Index to be used as a vector store';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import { COMPONENT_CATEGORY, COMPONENT_CLASS } from '../../utils';
import { BaseComponent } from '../base_component';
import {
IComponent,
IComponentField,
Expand All @@ -15,7 +16,9 @@ import {
/**
* A text embedding processor UI component
*/
export class TextEmbeddingProcessor implements IComponent {
export class TextEmbeddingProcessor
extends BaseComponent
implements IComponent {
type: COMPONENT_CLASS;
label: string;
description: string;
Expand All @@ -29,6 +32,7 @@ export class TextEmbeddingProcessor implements IComponent {
outputs: IComponentOutput[];

constructor() {
super();
this.type = COMPONENT_CLASS.TEXT_EMBEDDING_PROCESSOR;
this.label = 'Text Embedding Processor';
this.description =
Expand Down
19 changes: 17 additions & 2 deletions public/pages/workflow_detail/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import React, { useContext } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { EuiPageHeader, EuiButton } from '@elastic/eui';
import { Workflow } from '../../../../common';
import { generateUseCaseTemplate } from '../utils';
import { rfContext, AppState, removeDirty } from '../../../store';

interface WorkflowDetailHeaderProps {
workflow?: Workflow;
}

export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
const dispatch = useDispatch();
const { reactFlowInstance } = useContext(rfContext);
const isDirty = useSelector((state: AppState) => state.workspace.isDirty);

return (
<div>
<EuiPageHeader
Expand All @@ -21,7 +28,15 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
<EuiButton fill={false} onClick={() => {}}>
Prototype
</EuiButton>,
<EuiButton fill={false} onClick={() => {}}>
<EuiButton
fill={false}
disabled={!props.workflow || !isDirty}
onClick={() => {
// @ts-ignore
generateUseCaseTemplate(props.workflow, reactFlowInstance);
dispatch(removeDirty());
}}
>
Save
</EuiButton>,
]}
Expand Down
6 changes: 6 additions & 0 deletions public/pages/workflow_detail/utils/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 './utils';
16 changes: 16 additions & 0 deletions public/pages/workflow_detail/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { UseCaseTemplate, Workflow } from '../../../../common';

export function generateUseCaseTemplate(
workflow: Workflow,
rfInstance: any
): UseCaseTemplate {
let useCaseTemplate = {} as UseCaseTemplate;

return useCaseTemplate;
}
8 changes: 4 additions & 4 deletions public/pages/workflow_detail/workspace/workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import React, { useRef, useContext, useCallback, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import ReactFlow, {
Controls,
Background,
Expand All @@ -12,7 +13,7 @@ import ReactFlow, {
addEdge,
} from 'reactflow';
import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import { rfContext } from '../../../store';
import { rfContext, setDirty } from '../../../store';
import { IComponent, Workflow } from '../../../../common';
import { generateId } from '../../../utils';
import { getCore } from '../../../services';
Expand All @@ -30,6 +31,7 @@ const nodeTypes = { customComponent: WorkspaceComponent };
// TODO: probably have custom edge types here too

export function Workspace(props: WorkspaceProps) {
const dispatch = useDispatch();
const reactFlowWrapper = useRef(null);
const { reactFlowInstance, setReactFlowInstance } = useContext(rfContext);

Expand All @@ -39,10 +41,8 @@ export function Workspace(props: WorkspaceProps) {
const onConnect = useCallback(
(params) => {
setEdges((eds) => addEdge(params, eds));
dispatch(setDirty());
},
// TODO: add customized logic to prevent connections based on the node's
// allowed inputs. If allowed, update that node state as well with the added
// connection details.
[setEdges]
);

Expand Down
6 changes: 3 additions & 3 deletions public/store/reducers/workflows_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ const dummyNodes = [
{
id: generateId('text_embedding_processor'),
position: { x: 0, y: 500 },
data: new TextEmbeddingProcessor(),
data: new TextEmbeddingProcessor().toObj(),
type: 'customComponent',
},
{
id: generateId('text_embedding_processor'),
position: { x: 0, y: 200 },
data: new TextEmbeddingProcessor(),
data: new TextEmbeddingProcessor().toObj(),
type: 'customComponent',
},
{
id: generateId('knn_index'),
position: { x: 500, y: 500 },
data: new KnnIndex(),
data: new KnnIndex().toObj(),
type: 'customComponent',
},
] as ReactFlowComponent[];
Expand Down
17 changes: 1 addition & 16 deletions public/store/reducers/workspace_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,9 @@
*/

import { createSlice } from '@reduxjs/toolkit';
import { IComponent } from '../../../common';
import { KnnIndex, TextEmbeddingProcessor } from '../../component_types';

// TODO: should be fetched from server-side. This will be the list of all
// available components that the framework offers. This will be used in the component
// library to populate the available components to drag-and-drop into the workspace.
const dummyComponents = [
new TextEmbeddingProcessor(),
new KnnIndex(),
] as IComponent[];

const initialState = {
isDirty: false,
components: dummyComponents,
};

const workspaceSlice = createSlice({
Expand All @@ -30,12 +19,8 @@ const workspaceSlice = createSlice({
removeDirty(state) {
state.isDirty = false;
},
setComponents(state, action) {
state.components = action.payload;
state.isDirty = true;
},
},
});

export const workspaceReducer = workspaceSlice.reducer;
export const { setDirty, removeDirty, setComponents } = workspaceSlice.actions;
export const { setDirty, removeDirty } = workspaceSlice.actions;

0 comments on commit b911754

Please sign in to comment.