Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5eab2ba
Installing npm packages via mvn
fantonangeli May 28, 2026
76bc91c
Show the Diagram Editor and receive the WF definition from JsonRpc
fantonangeli Jun 19, 2026
e73a620
Use of registryCache to fix build issue
fantonangeli Jun 22, 2026
91baeb7
Refinements and avoid multiple renderings
fantonangeli Jun 24, 2026
9e826b9
Avoid multiple rendering on start
fantonangeli Jun 25, 2026
a152eb9
Fix DiagramEditor not resetting when switching workflows
fantonangeli Jun 25, 2026
6e534ad
Show loading progress bar while waiting jsonRpc answer
fantonangeli Jun 26, 2026
8fb48d9
Created test files
fantonangeli Jun 26, 2026
6ac35eb
Fixes comment: https://github.com/quarkiverse/quarkus-flow/pull/575#d…
fantonangeli Jun 30, 2026
31239fd
Merge remote-tracking branch 'upstream/main' into issue-523-feat-Inte…
fantonangeli Jul 2, 2026
2cd6385
Empty commit
fantonangeli Jul 2, 2026
93a5734
Merge remote-tracking branch 'upstream/main' into issue-523-feat-Inte…
fantonangeli Jul 9, 2026
7a1630f
Update DE version
fantonangeli Jul 10, 2026
ce24e36
Remove pom-diagram-editor-dev.xml
fantonangeli Jul 10, 2026
41da431
Merge remote-tracking branch 'upstream/main' into issue-523-feat-Inte…
fantonangeli Jul 10, 2026
2d0aecc
Merge remote-tracking branch 'upstream/main' into issue-523-feat-Inte…
fantonangeli Jul 17, 2026
9e13428
Update DE package references to the new openworkflowspec
fantonangeli Jul 17, 2026
d878517
Still need to use the old @serverlessworkflow/sdk-typescript
fantonangeli Jul 17, 2026
f4c9e29
Empty commit
fantonangeli Jul 17, 2026
92c75f7
Merge remote-tracking branch 'upstream/main' into issue-523-feat-Inte…
fantonangeli Jul 19, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ pom.xml.versionsBackup
release.properties
.m2/

# Esbuild Maven Plugin for dev-ui
node_modules/
build.js

# Claude Code
.claude/settings.local.json

Expand Down
87 changes: 87 additions & 0 deletions core/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
<artifactId>quarkus-flow-deployment</artifactId>
<name>Quarkus Flow :: Core :: Deployment</name>

<properties>
<esbuild-maven-plugin.version>2.0.0</esbuild-maven-plugin.version>
<react.version>19.2.7</react.version>
<scheduler.version>0.27.0</scheduler.version>
<openworkflowspec.diagram-editor.version>0.2.0</openworkflowspec.diagram-editor.version>
<use-sync-external-store.version>1.6.0</use-sync-external-store.version>
</properties>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
Expand Down Expand Up @@ -117,6 +125,16 @@
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<!-- Do not copy the raw bundle source, esbuild will generate the compiled version -->
<exclude>dev-ui/bundle.js</exclude>
</excludes>
</resource>
</resources>

<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
Expand All @@ -135,6 +153,75 @@
</execution>
</executions>
</plugin>

<plugin>
<groupId>io.mvnpm</groupId>
<artifactId>esbuild-maven-plugin</artifactId>
<version>${esbuild-maven-plugin.version}</version>

<executions>
<execution>
<id>esbuild</id>
<goals>
<goal>esbuild</goal>
</goals>
</execution>
</executions>

<configuration>
<sourceDirectory>src/main/resources/dev-ui</sourceDirectory>
<outputDirectory>target/classes/dev-ui</outputDirectory>
<entryPoint>bundle.js</entryPoint>
</configuration>

<dependencies>
<!-- OpenWorkflowSpec Diagram Editor (mvnpm) -->
<dependency>
<groupId>org.mvnpm.at.openworkflowspec</groupId>
<artifactId>diagram-editor</artifactId>
<version>${openworkflowspec.diagram-editor.version}</version>
<exclusions>
<!-- Required because @serverlessworkflow/sdk is an npm dependency, not available on mvnpm as alpha version, but is already bundled in @serverlessworkflow/diagram-editor's dist. -->
<exclusion>
<groupId>org.mvnpm.at.serverlessworkflow</groupId>
<artifactId>sdk</artifactId>
</exclusion>
<!-- D3 is already bundled in @openworkflowspec/diagram-editor, avoid version conflicts for transitive D3 dependencies. -->
<exclusion>
<groupId>org.mvnpm</groupId>
<artifactId>d3-interpolate</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- @openworkflowspec/diagram-editor peerDependency -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>react</artifactId>
<version>${react.version}</version>
</dependency>
<!-- @openworkflowspec/diagram-editor peerDependency -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>react-dom</artifactId>
<version>${react.version}</version>
</dependency>

<!-- Required by react-dom -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>scheduler</artifactId>
<version>${scheduler.version}</version>
</dependency>

<!-- Required because use-sync-external-store is kept external by @openworkflowspec/diagram-editor to avoid bundling it as CJS into the final Dev UI bundle. -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>use-sync-external-store</artifactId>
<version>${use-sync-external-store.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
28 changes: 28 additions & 0 deletions core/deployment/src/main/resources/dev-ui/bundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from "react";
import { createRoot } from "react-dom/client";
import { DiagramEditor } from "@openworkflowspec/diagram-editor";
import "@openworkflowspec/diagram-editor/styles.css";

const roots = new WeakMap();

export function renderOpenWorkflowSpecDiagramEditor(container, props) {
let root = roots.get(container);

if (!root) {
root = createRoot(container);
roots.set(container, root);
}

root.render(React.createElement(DiagramEditor, {key: props.workflowKey, ...props}));

return root;
}

export function unmountOpenWorkflowSpecDiagramEditor(container) {
const root = roots.get(container);

if (root) {
root.unmount();
roots.delete(container);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { LitElement, html, css } from 'lit';
import '@vaadin/progress-bar';
import {
renderOpenWorkflowSpecDiagramEditor,
unmountOpenWorkflowSpecDiagramEditor,
} from '../bundle.js';
import { JsonRpc } from 'jsonrpc';

const diagramEditorStylesUrl = new URL('../bundle.css', import.meta.url).href;

export class OpenWorkflowSpecDiagramEditorElement extends LitElement {
_workflowDefinition = null;

static properties = {
workflow: { type: Object },
readonly: { type: Boolean },
extensionName: { type: String },
workflowKey: { state: true },
_isLoading: { state: true },
};

static styles = css`
:host {
display: block;
width: 100%;
height: 100%;
min-height: 520px;
}

#container {
width: 100%;
height: 100%;
min-height: 520px;
}

.loading-workflow-definition {
max-width: 80%;
margin: auto;
padding-top: 80px;
text-align: center;
}
`;

constructor() {
super();
this.workflow = null;
this.readonly = true;
this.extensionName = 'quarkus-flow';
this.workflowKey = null;
this._isLoading = false;
}

connectedCallback() {
super.connectedCallback();
this.jsonRpc = new JsonRpc(this.extensionName);
}

render() {
return html`
<link rel="stylesheet" href=${diagramEditorStylesUrl} />

${this._isLoading
? html`
<div class="loading-workflow-definition">
<vaadin-progress-bar indeterminate></vaadin-progress-bar>
<p>Loading workflow definition…</p>
</div>
`
: html`
<div id="container" class="openworkflowspec-diagram-editor-container"></div>
`}
`;
}

async updated(changedProperties) {
if (changedProperties.has('workflow')) {
this._unmountReactEditor();

this._isLoading = true;
await this.updateComplete;

try {
await this._loadWorkflowDefinition();
} finally {
this._isLoading = false;
await this.updateComplete;
this._renderReactEditor();
}
}
}

async _loadWorkflowDefinition() {
if (!this.workflow?.id) {
this._workflowDefinition = null;
return;
}

try {
const { result } = await this.jsonRpc.getWorkflowDefinition({ id: this.workflow.id });
this._workflowDefinition = result;
} catch (error) {
console.error('Failed to load workflow definition:', error);
this._workflowDefinition = null;
}
}

disconnectedCallback() {
this._unmountReactEditor();
super.disconnectedCallback();
}

_renderReactEditor() {
const container = this.renderRoot.querySelector('#container');

if (!container) {
return;
}

renderOpenWorkflowSpecDiagramEditor(container, {
content: this._workflowDefinition,
isReadOnly: this.readonly,
workflowKey: this.workflowKey,
});
}

_unmountReactEditor() {
const container = this.renderRoot?.querySelector('#container');

if (container) {
unmountOpenWorkflowSpecDiagramEditor(container);
}
}
}

customElements.define(
'qwc-openworkflowspec-diagram-editor',
OpenWorkflowSpecDiagramEditorElement
);
Loading
Loading