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

feat:integrate orkes-workflow-visualizer #290

Merged
merged 3 commits into from
Nov 25, 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
27 changes: 13 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: CI
on:
push:
paths-ignore:
- 'conductor-clients/**'
- "conductor-clients/**"
pull_request:
paths-ignore:
- 'conductor-clients/**'
- "conductor-clients/**"

jobs:
build:
Expand All @@ -21,8 +21,8 @@ jobs:
- name: Set up Zulu JDK 17
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
distribution: "zulu"
java-version: "17"
- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
Expand Down Expand Up @@ -53,20 +53,20 @@ jobs:
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
report_paths: "**/build/test-results/test/TEST-*.xml"
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: '**/build/reports'
path: "**/build/reports"
- name: Store Buildscan URL
uses: actions/upload-artifact@v3
with:
name: build-scan
path: 'buildscan.log'
path: "buildscan.log"
build-ui:
runs-on: ubuntu-latest
container: cypress/browsers:node14.17.6-chrome100-ff98
container: cypress/browsers:node-22.11.0-chrome-130.0.6723.116-1-ff-132.0.1-edge-130.0.2849.68-1
defaults:
run:
working-directory: ui
Expand All @@ -81,15 +81,15 @@ jobs:

- name: Run E2E Tests
uses: cypress-io/github-action@v4
with:
with:
working-directory: ui
install: false
start: yarn run serve-build
wait-on: 'http://localhost:5000'
wait-on: "http://localhost:5000"

- name: Run Component Tests
uses: cypress-io/github-action@v4
with:
with:
working-directory: ui
install: false
component: true
Expand All @@ -100,11 +100,10 @@ jobs:
with:
name: cypress-screenshots
path: ui/cypress/screenshots

- name: Archive test videos
uses: actions/upload-artifact@v3
if: always()
with:
name: cypress-videos
path: ui/cypress/videos

5 changes: 3 additions & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
"moment": "^2.29.2",
"monaco-editor": "^0.44.0",
"node-forge": "^1.3.0",
"orkes-workflow-visualizer": "^1.0.0",
"parse-svg-path": "^0.1.2",
"prop-types": "^15.7.2",
"react": "^16.8.0",
"react": "^18.3.1",
"react-cron-generator": "^1.3.5",
"react-data-table-component": "^6.11.8",
"react-dom": "^16.8.0",
"react-dom": "^18.3.1",
"react-helmet": "^6.1.0",
"react-is": "^17.0.2",
"react-query": "^3.19.4",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/diagram/WorkflowDAG.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ export default class WorkflowDAG {
return this.taskResultsById.get(taskPointer.id);
} else {
const node = this.graph.node(taskPointer.ref);
return _.last(node.taskResults);
return _.last(node?.taskResults);
}
}
}
Expand Down
52 changes: 33 additions & 19 deletions ui/src/pages/definition/WorkflowDefinition.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
useWorkflowNamesAndVersions,
} from "../../data/workflow";
import WorkflowDAG from "../../components/diagram/WorkflowDAG";
import WorkflowGraph from "../../components/diagram/WorkflowGraph";
import ResetConfirmationDialog from "./ResetConfirmationDialog";
import {
configureMonaco,
Expand All @@ -23,6 +22,7 @@ import SaveWorkflowDialog from "./SaveWorkflowDialog";
import update from "immutability-helper";
import { usePushHistory } from "../../components/NavLink";
import { timestampRenderer } from "../../utils/helpers";
import { WorkflowVisualizer } from "orkes-workflow-visualizer";

import {
KeyboardArrowLeftRounded,
Expand Down Expand Up @@ -67,8 +67,8 @@ const useStyles = makeStyles({
gap: 8,
},
editorLineDecorator: {
backgroundColor: "rgb(45, 45, 45, 0.1)"
}
backgroundColor: "rgb(45, 45, 45, 0.1)",
},
});

const actions = {
Expand Down Expand Up @@ -240,21 +240,26 @@ export default function Workflow() {
};

const handleWorkflowNodeClick = (node) => {
let editor = editorRef.current.getModel()
let searchResult = editor.findMatches(`"taskReferenceName": "${node.ref}"`)
if (searchResult.length){
editorRef.current.revealLineInCenter(searchResult[0]?.range?.startLineNumber, 0);
setDecorations(editorRef.current.deltaDecorations(decorations, [
{
range: searchResult[0]?.range,
options: {
isWholeLine: true,
inlineClassName: classes.editorLineDecorator
}
}
]))
let editor = editorRef.current.getModel();
let searchResult = editor.findMatches(`"taskReferenceName": "${node.ref}"`);
if (searchResult.length) {
editorRef.current.revealLineInCenter(
searchResult[0]?.range?.startLineNumber,
0
);
setDecorations(
editorRef.current.deltaDecorations(decorations, [
{
range: searchResult[0]?.range,
options: {
isWholeLine: true,
inlineClassName: classes.editorLineDecorator,
},
},
])
);
}
}
};

return (
<>
Expand Down Expand Up @@ -369,8 +374,17 @@ export default function Workflow() {
className={classes.resizer}
onMouseDown={(e) => handleMouseDown(e)}
/>
<div className={classes.workflowGraph}>
{dag && <WorkflowGraph dag={dag} onClick={handleWorkflowNodeClick} />}
<div className={classes.workflowGraph} style={{ overflow: "scroll" }}>
{dag && dag?.workflowDef && (
<WorkflowVisualizer
maxHeightOverride
pannable
zoomable
zoom={0.7}
data={dag?.workflowDef}
onClick={(e, data) => handleWorkflowNodeClick({ ref: data?.id })}
/>
)}
</div>
</div>
</>
Expand Down
11 changes: 10 additions & 1 deletion ui/src/pages/execution/Execution.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export default function Execution() {
const [isFullWidth, setIsFullWidth] = useState(false);
const [isResizing, setIsResizing] = useState(false);
const [drawerWidth, setDrawerWidth] = useState(INIT_DRAWER_WIDTH);
const [selectedNode, setSelectedNode] = useState();

const [tabIndex, setTabIndex] = useQueryState("tabIndex", 0);
const [selectedTaskRison, setSelectedTaskRison] = useQueryState("task", "");
Expand Down Expand Up @@ -222,7 +223,12 @@ export default function Execution() {
</div>
)}
<div className={classes.frItem}>
<NavLink newTab path={`/workflowDef/${execution.workflowName}`}>Definition</NavLink>
<NavLink
newTab
path={`/workflowDef/${execution.workflowName}`}
>
Definition
</NavLink>
</div>
<SecondaryButton onClick={refresh} style={{ marginRight: 10 }}>
Refresh
Expand Down Expand Up @@ -260,6 +266,7 @@ export default function Execution() {
execution={execution}
setSelectedTask={setSelectedTask}
selectedTask={selectedTask}
setSelectedNode={setSelectedNode}
/>
)}
{tabIndex === 1 && <ExecutionSummary execution={execution} />}
Expand Down Expand Up @@ -302,6 +309,8 @@ export default function Execution() {
className={classes.rightPanel}
selectedTask={selectedTask}
dag={dag}
execution={execution}
selectedNode={selectedNode}
onTaskChange={setSelectedTask}
/>
</div>
Expand Down
21 changes: 16 additions & 5 deletions ui/src/pages/execution/RightPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import TaskLogs from "./TaskLogs";
import { makeStyles } from "@material-ui/styles";
import _ from "lodash";
import TaskPollData from "./TaskPollData";
import {
pendingTaskSelection,
taskWithLatestIteration,
} from "../../utils/helpers";

const useStyles = makeStyles({
banner: {
Expand All @@ -24,7 +28,13 @@ const useStyles = makeStyles({
},
});

export default function RightPanel({ selectedTask, dag, onTaskChange }) {
export default function RightPanel({
selectedTask,
dag,
execution,
onTaskChange,
selectedNode,
}) {
const [tabIndex, setTabIndex] = useState("summary");

const classes = useStyles();
Expand All @@ -33,10 +43,11 @@ export default function RightPanel({ selectedTask, dag, onTaskChange }) {
setTabIndex("summary"); // Reset to Status Tab on ref change
}, [selectedTask]);

const taskResult = useMemo(
() => dag && dag.resolveTaskResult(selectedTask),
[dag, selectedTask]
);
const taskResult =
selectedNode?.data?.task?.executionData?.status === "PENDING"
? pendingTaskSelection(selectedNode?.data?.task)
: taskWithLatestIteration(execution?.tasks, selectedTask?.ref);

const dfOptions = useMemo(
() => dag && dag.getSiblings(selectedTask),
[dag, selectedTask]
Expand Down
29 changes: 23 additions & 6 deletions ui/src/pages/execution/TaskDetails.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import React, { useState } from "react";
import { useState } from "react";
import { Tabs, Tab, Paper } from "../../components";
import Timeline from "./Timeline";
import TaskList from "./TaskList";
import WorkflowGraph from "../../components/diagram/WorkflowGraph";
import { makeStyles } from "@material-ui/styles";
import { WorkflowVisualizer } from "orkes-workflow-visualizer";
import {
pendingTaskSelection,
taskWithLatestIteration,
} from "../../utils/helpers";

const useStyles = makeStyles({
taskWrapper: {
Expand All @@ -18,6 +22,7 @@ export default function TaskDetails({
dag,
selectedTask,
setSelectedTask,
setSelectedNode,
}) {
const [tabIndex, setTabIndex] = useState(0);
const classes = useStyles();
Expand All @@ -32,11 +37,23 @@ export default function TaskDetails({
</Tabs>

{tabIndex === 0 && (
<WorkflowGraph
selectedTask={selectedTask}
<WorkflowVisualizer
maxHeightOverride
pannable
zoomable
zoom={0.7}
data={dag?.execution}
executionMode={true}
dag={dag}
onClick={setSelectedTask}
onClick={(e, data) => {
const selectedTaskRefName =
data?.data?.task?.executionData?.status === "PENDING"
? pendingTaskSelection(data?.data?.task)?.workflowTask
?.taskReferenceName
: taskWithLatestIteration(execution?.tasks, data?.id)
?.referenceTaskName;
setSelectedNode(data);
setSelectedTask({ ref: selectedTaskRefName });
}}
/>
)}
{tabIndex === 1 && (
Expand Down
47 changes: 42 additions & 5 deletions ui/src/utils/helpers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { format, formatDuration, intervalToDuration } from "date-fns";
import _ from "lodash";
import packageJson from '../../package.json';
import packageJson from "../../package.json";
import _nth from "lodash/nth";

export function timestampRenderer(date) {
if (_.isNil(date)) return null;
Expand Down Expand Up @@ -91,9 +92,45 @@ export function isEmptyIterable(iterable) {
}

export function getBasename() {
let basename = '/';
try{
let basename = "/";
try {
basename = new URL(packageJson.homepage).pathname;
} catch(e) {}
return _.isEmpty(basename) ? '/' : basename;
} catch (e) {}
return _.isEmpty(basename) ? "/" : basename;
}

export const taskWithLatestIteration = (tasksList, taskReferenceName) => {
const filteredTasks = tasksList?.filter(
(task) =>
task?.workflowTask?.taskReferenceName === taskReferenceName ||
task?.referenceTaskName === taskReferenceName
);

if (filteredTasks && filteredTasks.length === 1) {
// task without any retry/iteration
return _nth(filteredTasks, 0);
} else if (filteredTasks && filteredTasks.length > 1) {
const result = filteredTasks.reduce(
(acc, task, idx) => {
if (task?.seq && acc?.seqNumber < Number(task.seq)) {
return { seqNumber: Number(task.seq), idx };
}
return acc;
},
{ seqNumber: 0, idx: -1 }
);

if (result?.idx > -1) {
return _nth(filteredTasks, result.idx);
}
}
return undefined;
};

export const pendingTaskSelection = (task) => {
const result = {
...task?.executionData,
workflowTask: task,
};
return result;
};
Loading