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 visual/json toggle and expose workflow template on editor #189

Merged
merged 2 commits into from
Jun 20, 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
5 changes: 4 additions & 1 deletion public/pages/workflow_detail/resizable_workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,10 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
style={{ height: '100%' }}
>
<EuiFlexItem>
<Workspace uiConfig={uiConfig} />
<Workspace
workflow={props.workflow}
uiConfig={uiConfig}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiResizablePanel>
Expand Down
142 changes: 106 additions & 36 deletions public/pages/workflow_detail/workspace/workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useRef, useCallback, useEffect } from 'react';
import React, { useRef, useCallback, useEffect, useState } from 'react';
import ReactFlow, {
Controls,
Background,
Expand All @@ -13,9 +13,16 @@ import ReactFlow, {
BackgroundVariant,
MarkerType,
} from 'reactflow';
import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import {
EuiFlexItem,
EuiFlexGroup,
EuiTitle,
EuiFilterGroup,
EuiFilterButton,
EuiCodeEditor,
} from '@elastic/eui';
import { setDirty, useAppDispatch } from '../../../store';
import { IComponentData, WorkflowConfig } from '../../../../common';
import { IComponentData, Workflow, WorkflowConfig } from '../../../../common';
import {
IngestGroupComponent,
SearchGroupComponent,
Expand All @@ -31,6 +38,7 @@ import './workspace-styles.scss';
import './workspace_edge/deletable-edge-styles.scss';

interface WorkspaceProps {
workflow?: Workflow;
uiConfig?: WorkflowConfig;
}

Expand All @@ -44,6 +52,22 @@ const edgeTypes = { customEdge: DeletableEdge };
export function Workspace(props: WorkspaceProps) {
const dispatch = useAppDispatch();

// Visual/JSON toggle states
const [visualSelected, setVisualSelected] = useState<boolean>(true);
function toggleSelection(): void {
setVisualSelected(!visualSelected);
}

// JSON state
const [provisionTemplate, setProvisionTemplate] = useState<string>('');
useEffect(() => {
if (props.workflow?.workflows.provision) {
const templateAsObj = props.workflow?.workflows.provision as {};
const templateAsStr = JSON.stringify(templateAsObj, undefined, 2);
setProvisionTemplate(templateAsStr);
}
}, [props.workflow]);

// ReactFlow state
const reactFlowWrapper = useRef(null);
const [nodes, setNodes, onNodesChange] = useNodesState<IComponentData>([]);
Expand Down Expand Up @@ -88,46 +112,92 @@ export function Workspace(props: WorkspaceProps) {
gutterSize="none"
justifyContent="spaceBetween"
>
<EuiFlexItem className="euiPanel euiPanel--hasShadow euiPanel--borderRadiusMedium">
<EuiFlexItem
className="euiPanel euiPanel--hasShadow euiPanel--borderRadiusMedium"
style={{ overflowX: 'hidden' }}
>
{/**
* We have these wrapper divs & reactFlowWrapper ref to control and calculate the
* ReactFlow bounds when calculating node positioning.
*/}
<div>
<EuiFlexGroup direction="row" style={{ padding: '12px' }}>
<EuiFlexItem grow={false}>
<EuiTitle>
<h2>Preview</h2>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFilterGroup>
<EuiFilterButton
size="l"
hasActiveFilters={visualSelected}
onClick={() => toggleSelection()}
>
Visual
</EuiFilterButton>
<EuiFilterButton
size="l"
hasActiveFilters={!visualSelected}
onClick={() => toggleSelection()}
>
JSON
</EuiFilterButton>
</EuiFilterGroup>
</EuiFlexItem>
</EuiFlexGroup>
</div>
<div className="reactflow-parent-wrapper">
<div className="reactflow-wrapper" ref={reactFlowWrapper}>
<ReactFlow
id="workspace"
nodes={nodes}
edges={edges}
nodeTypes={nodeTypes}
// TODO: add custom edge types back if we want to support custom deletable buttons
// edgeTypes={edgeTypes}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
className="reactflow-workspace"
fitView
minZoom={0.2}
edgesUpdatable={false}
edgesFocusable={false}
nodesDraggable={false}
nodesConnectable={false}
nodesFocusable={false}
draggable={true}
panOnDrag={true}
elementsSelectable={false}
>
<Controls
showFitView={false}
showZoom={false}
showInteractive={false}
position="top-left"
></Controls>
<Background
color="#343741"
variant={'dots' as BackgroundVariant}
{visualSelected ? (
<ReactFlow
id="workspace"
nodes={nodes}
edges={edges}
nodeTypes={nodeTypes}
// TODO: add custom edge types back if we want to support custom deletable buttons
// edgeTypes={edgeTypes}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
className="reactflow-workspace"
fitView
minZoom={0.2}
edgesUpdatable={false}
edgesFocusable={false}
nodesDraggable={false}
nodesConnectable={false}
nodesFocusable={false}
draggable={true}
panOnDrag={true}
elementsSelectable={false}
>
<Controls
showFitView={false}
showZoom={false}
showInteractive={false}
position="top-left"
></Controls>
<Background
color="#343741"
variant={'dots' as BackgroundVariant}
/>
</ReactFlow>
) : (
<EuiCodeEditor
mode="json"
theme="textmate"
width="100%"
height="100%"
value={provisionTemplate}
readOnly={true}
setOptions={{
fontSize: '12px',
autoScrollEditorIntoView: true,
}}
tabSize={2}
/>
</ReactFlow>
)}
</div>
</div>
</EuiFlexItem>
Expand Down
Loading