This is an automated email from the ASF dual-hosted git repository.
tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new 3daeaf23be1 KOGITO-10042: Migrate SWF Dev UI Java module from
kogito-apps to kie-tools (#2167)
3daeaf23be1 is described below
commit 3daeaf23be1fa78bdaaf0869c8bf387ed600726e
Author: Fabrizio Antonangeli <[email protected]>
AuthorDate: Mon Mar 25 20:35:52 2024 +0100
KOGITO-10042: Migrate SWF Dev UI Java module from kogito-apps to kie-tools
(#2167)
Co-authored-by: Yeser Amer <[email protected]>
Co-authored-by: Thiago Lugli <[email protected]>
Co-authored-by: Paulo Martins <[email protected]>
---
.../env/index.js | 31 +++
.../sonataflow-quarkus-devui-extension/install.js | 25 +++
.../package.json | 41 ++++
.../sonataflow-quarkus-devui-extension/pom.xml | 150 ++++++++++++++
.../pom.xml | 201 ++++++++++++++++++
.../swf/tools/deployment/DevConsoleProcessor.java | 133 ++++++++++++
.../SonataFlowQuarkusExtensionProcessor.java | 32 +++
.../src/main/resources/dev-templates/embedded.html | 53 +++++
.../main/resources/dev-templates/monitoring.html | 44 ++++
.../resources/dev-templates/workflowInstances.html | 45 ++++
.../src/main/resources/static/index.html | 45 ++++
.../sonataflow-quarkus-devui-extension/pom.xml | 159 +++++++++++++++
.../custom/dashboard/CustomDashboardService.java | 83 ++++++++
.../custom/dashboard/CustomDashboardStorage.java | 36 ++++
.../CustomDashboardFilterParamConverter.java | 40 ++++
...ustomDashboardFilterParamConverterProvider.java | 41 ++++
.../dashboard/impl/CustomDashboardStorageImpl.java | 226 +++++++++++++++++++++
.../dashboard/model/CustomDashboardFilter.java | 50 +++++
.../dashboard/model/CustomDashboardInfo.java | 95 +++++++++
.../src/main/resources/META-INF/beans.xml | 7 +
.../main/resources/META-INF/quarkus-extension.yaml | 28 +++
.../dashboard/impl/CustomDashboardStorageTest.java | 115 +++++++++++
.../impl/CustomDashboardStorageTestProfile.java | 46 +++++
.../resources/custom/dashboards/products.dash.yaml | 61 ++++++
.../custom/dashboards/subdir/age.dash.yml | 44 ++++
pnpm-lock.yaml | 15 ++
repo/graph.dot | 2 +
repo/graph.json | 7 +
28 files changed, 1855 insertions(+)
diff --git a/packages/sonataflow-quarkus-devui-extension/env/index.js
b/packages/sonataflow-quarkus-devui-extension/env/index.js
new file mode 100644
index 00000000000..33ffd575a68
--- /dev/null
+++ b/packages/sonataflow-quarkus-devui-extension/env/index.js
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const { varsWithName, composeEnv, getOrDefault } =
require("@kie-tools-scripts/build-env");
+
+module.exports = composeEnv([require("@kie-tools/root-env/env")], {
+ vars: varsWithName({}),
+ get env() {
+ return {
+ sonataflowQuarkusDevuiExtension: {
+ version: require("../package.json").version,
+ },
+ };
+ },
+});
diff --git a/packages/sonataflow-quarkus-devui-extension/install.js
b/packages/sonataflow-quarkus-devui-extension/install.js
new file mode 100644
index 00000000000..99bfadb8cf8
--- /dev/null
+++ b/packages/sonataflow-quarkus-devui-extension/install.js
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+const buildEnv = require("./env");
+const { setup } = require("@kie-tools/maven-config-setup-helper");
+
+setup(`
+ -Drevision=${buildEnv.env.sonataflowQuarkusDevuiExtension.version}
+`);
diff --git a/packages/sonataflow-quarkus-devui-extension/package.json
b/packages/sonataflow-quarkus-devui-extension/package.json
new file mode 100644
index 00000000000..9407dfdba19
--- /dev/null
+++ b/packages/sonataflow-quarkus-devui-extension/package.json
@@ -0,0 +1,41 @@
+{
+ "private": true,
+ "name": "@kie-tools/sonataflow-quarkus-devui-extension",
+ "version": "0.0.0",
+ "description": "",
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/apache/incubator-kie-tools",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/apache/incubator-kie-tools.git"
+ },
+ "bugs": {
+ "url": "https://github.com/apache/incubator-kie-tools/issues"
+ },
+ "scripts": {
+ "build:dev": "run-script-os",
+ "build:dev:darwin:linux": "mvn clean install -DskipTests",
+ "build:dev:win32": "pnpm powershell \"mvn clean install -DskipTests \"",
+ "build:prod": "pnpm lint && run-script-os",
+ "build:prod:darwin:linux": "mvn clean install -DskipTests=$(build-env
tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)",
+ "build:prod:win32": "pnpm powershell \"mvn clean install `-DskipTests
`-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"",
+ "install": "node install.js",
+ "lint": "echo 'Linting'",
+ "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted
-Command",
+ "quarkus:dev": "run-script-os",
+ "quarkus:dev:darwin:linux": "mvn clean package quarkus:dev -DskipTests",
+ "quarkus:dev:win32": "mvn clean package quarkus:dev -DskipTests"
+ },
+ "devDependencies": {
+ "@kie-tools/maven-config-setup-helper": "workspace:*",
+ "@kie-tools/root-env": "workspace:*",
+ "@kie-tools/serverless-workflow-dev-ui-webapp": "workspace:*",
+ "run-script-os": "^1.1.6"
+ },
+ "kieTools": {
+ "requiredPreinstalledCliCommands": [
+ "java",
+ "mvn"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/sonataflow-quarkus-devui-extension/pom.xml
b/packages/sonataflow-quarkus-devui-extension/pom.xml
new file mode 100644
index 00000000000..cded104b09b
--- /dev/null
+++ b/packages/sonataflow-quarkus-devui-extension/pom.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+>
+
+ <modelVersion>4.0.0</modelVersion>
+ <name>KIE Tools :: SonataFlow Quarkus Dev UI Extension</name>
+ <groupId>org.apache.kie.sonataflow</groupId>
+ <version>${revision}</version>
+ <artifactId>sonataflow-quarkus-devui-extension-parent</artifactId>
+ <packaging>pom</packaging>
+
+ <repositories>
+ <repository>
+ <!-- Duplicating the Maven Central repository here (as it is already
coming from Super POM) makes the build much faster,
+ as the Maven Central is now treated as the first (default)
repository (because it is before the Apache Nexus one).
+ Artifacts with release (fixed) versions are being downloaded
primarily from there. Without the central being the
+ first repository the Apache Nexus would be contacted first and
since it is quite slow it slows down the build.
+ We use Apache repo only to download our SNAPSHOTs. -->
+ <id>central</id>
+ <name>Central Repository</name>
+ <url>https://repo.maven.apache.org/maven2</url>
+ <layout>default</layout>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>apache-public-repository-group</id>
+ <name>Apache Public Repository Group</name>
+ <url>https://repository.apache.org/content/groups/public/</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>daily</updatePolicy>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <properties>
+ <compiler-plugin.version>3.12.1</compiler-plugin.version>
+ <maven.compiler.source>17</maven.compiler.source>
+ <maven.compiler.target>17</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <version.resources.plugin>3.2.0</version.resources.plugin>
+ <java.module.name>org.kie.kogito.quarkus.swf.dev.ui</java.module.name>
+ <version.flatten.plugin>1.3.0</version.flatten.plugin>
+ <quarkus.platform.version>3.2.9.Final</quarkus.platform.version>
+ <version.org.kie.kogito>999-20240218-SNAPSHOT</version.org.kie.kogito>
+ </properties>
+
+ <modules>
+ <module>sonataflow-quarkus-devui-extension-deployment</module>
+ <module>sonataflow-quarkus-devui-extension</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-bom</artifactId>
+ <version>${quarkus.platform.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>flatten-maven-plugin</artifactId>
+ <version>${version.flatten.plugin}</version>
+ <configuration>
+ <updatePomFile>true</updatePomFile>
+ <flattenMode>resolveCiFriendliesOnly</flattenMode>
+ </configuration>
+ <executions>
+ <execution>
+ <id>flatten-revision</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>flatten</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>flatten-revision-clean</id>
+ <phase>clean</phase>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/pom.xml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/pom.xml
new file mode 100644
index 00000000000..e319b361962
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/pom.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+>
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.kie.sonataflow</groupId>
+ <artifactId>sonataflow-quarkus-devui-extension-parent</artifactId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>sonataflow-quarkus-devui-extension-deployment</artifactId>
+ <name>KIE Tools :: SonataFlow Quarkus Dev UI Extension :: Deployment</name>
+
+ <properties>
+
<path.to.webapp.app>../../serverless-workflow-dev-ui-webapp</path.to.webapp.app>
+ </properties>
+
+ <dependencies>
+ <!-- quarkus -->
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-development-mode-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-core-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-arc-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-jackson-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-rest-client-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-multipart-deployment</artifactId>
+ </dependency>
+
+ <!-- Undertow is needed so that the static resource serving can correctly
locate CP resources from `META-INF/resources` of the application, as it would
be normally expected.
+ See https://issues.redhat.com/browse/KOGITO-3477 -->
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-undertow-deployment</artifactId>
+ </dependency>
+
+ <!-- test -->
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.kie.sonataflow</groupId>
+ <artifactId>sonataflow-quarkus-devui-extension</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5-internal</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${compiler-plugin.version}</version>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.platform.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>${version.resources.plugin}</version>
+ <executions>
+ <execution>
+ <id>copy-webapp</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${basedir}/target/classes/dev-static/resources/webapp</outputDirectory>
+ <resources>
+ <resource>
+
<directory>${path.to.webapp.app}/dist/resources/webapp</directory>
+ <filtering>false</filtering>
+ </resource>
+ <resource>
+ <directory>${path.to.webapp.app}/dist/webapp</directory>
+ <filtering>false</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ <execution>
+ <id>copy-envelope-resources</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${basedir}/target/classes/dev-static</outputDirectory>
+ <resources>
+ <resource>
+ <directory>${path.to.webapp.app}/dist</directory>
+ <includes>
+ <include>form-displayer.html</include>
+ <include>form-displayer.js</include>
+
<include>serverless-workflow-combined-editor-envelope.html</include>
+
<include>serverless-workflow-combined-editor-envelope.js</include>
+
<include>serverless-workflow-text-editor-envelope.html</include>
+
<include>serverless-workflow-text-editor-envelope.js</include>
+
<include>serverless-workflow-diagram-editor-envelope.html</include>
+
<include>serverless-workflow-diagram-editor-envelope.js</include>
+ <include>vendors-*.bundle.js</include>
+ <include>*.worker.js</include>
+ </includes>
+ </resource>
+ <!--copy diagram into the dev-static-->
+ <resource>
+ <directory>${path.to.webapp.app}/dist</directory>
+ <includes>
+ <include>diagram/</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ <execution>
+ <id>copy-index</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${basedir}/target/classes/dev-static</outputDirectory>
+ <resources>
+ <resource>
+ <directory>${basedir}/target/classes/static</directory>
+ <includes>
+ <include>index.html</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/DevConsoleProcessor.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/DevConsoleProcessor.java
new file mode 100644
index 00000000000..721a00c4e2e
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/DevConsoleProcessor.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.deployment;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.file.Path;
+
+import io.quarkus.deployment.IsDevelopment;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.ConfigurationBuildItem;
+import io.quarkus.deployment.builditem.LaunchModeBuildItem;
+import io.quarkus.deployment.builditem.LiveReloadBuildItem;
+import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
+import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem;
+import io.quarkus.deployment.util.WebJarUtil;
+import io.quarkus.devui.spi.page.CardPageBuildItem;
+import io.quarkus.devui.spi.page.Page;
+import io.quarkus.maven.dependency.ResolvedDependency;
+import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem;
+import io.quarkus.vertx.http.deployment.RouteBuildItem;
+import io.quarkus.vertx.http.runtime.devmode.DevConsoleRecorder;
+import
io.quarkus.vertx.http.runtime.management.ManagementInterfaceBuildTimeConfig;
+
+public class DevConsoleProcessor {
+
+ private static final String STATIC_RESOURCES_PATH = "dev-static/";
+ private static final String BASE_RELATIVE_URL =
"/q/dev-v1/org.apache.kie.sonataflow.sonataflow-quarkus-devui-extension";
+
+ @BuildStep(onlyIf = IsDevelopment.class)
+ public CardPageBuildItem pages(NonApplicationRootPathBuildItem
nonApplicationRootPathBuildItem,
+ ManagementInterfaceBuildTimeConfig
managementInterfaceBuildTimeConfig,
+ LaunchModeBuildItem launchModeBuildItem,
+ ConfigurationBuildItem configurationBuildItem) throws
UnsupportedEncodingException {
+
+ String uiPath =
nonApplicationRootPathBuildItem.resolveManagementPath(BASE_RELATIVE_URL,
+ managementInterfaceBuildTimeConfig, launchModeBuildItem, true);
+
+ String devUIUrl = getProperty(configurationBuildItem,
"kogito.dev-ui.url");
+ String devUIUrlQueryParam = devUIUrl != null ? "&devUIUrl=" +
URLEncoder.encode(devUIUrl, "UTF-8") : "";
+
+ String dataIndexUrl = getProperty(configurationBuildItem,
"kogito.data-index.url");
+ String dataIndexUrlQueryParam = dataIndexUrl != null ?
"&dataIndexUrl=" + URLEncoder.encode(dataIndexUrl, "UTF-8") : "";
+
+ CardPageBuildItem cardPageBuildItem = new CardPageBuildItem();
+
+ cardPageBuildItem.addPage(Page.externalPageBuilder("Workflows")
+ .url(uiPath + "/index.html?page=Workflows" +
devUIUrlQueryParam + dataIndexUrlQueryParam, uiPath)
+ .isHtmlContent()
+ .icon("font-awesome-solid:diagram-project"));
+
+ cardPageBuildItem.addPage(Page.externalPageBuilder("Monitoring")
+ .url(uiPath + "/index.html?page=Monitoring" +
devUIUrlQueryParam + dataIndexUrlQueryParam, uiPath)
+ .isHtmlContent()
+ .icon("font-awesome-solid:gauge-high"));
+
+ return cardPageBuildItem;
+ }
+
+ @BuildStep(onlyIf = IsDevelopment.class)
+ @Record(ExecutionTime.RUNTIME_INIT)
+ public void deployStaticResources(final DevConsoleRecorder recorder,
+ final CurateOutcomeBuildItem curateOutcomeBuildItem,
+ final LiveReloadBuildItem liveReloadBuildItem,
+ final LaunchModeBuildItem launchMode,
+ final ShutdownContextBuildItem shutdownContext,
+ final BuildProducer<RouteBuildItem> routeBuildItemBuildProducer)
throws IOException {
+ ResolvedDependency devConsoleResourcesArtifact =
WebJarUtil.getAppArtifact(curateOutcomeBuildItem,
+ "org.apache.kie.sonataflow",
+ "sonataflow-quarkus-devui-extension-deployment");
+
+ Path devConsoleStaticResourcesDeploymentPath =
WebJarUtil.copyResourcesForDevOrTest(
+ liveReloadBuildItem,
+ curateOutcomeBuildItem,
+ launchMode,
+ devConsoleResourcesArtifact,
+ STATIC_RESOURCES_PATH,
+ true);
+
+ routeBuildItemBuildProducer.produce(new RouteBuildItem.Builder()
+ .route(BASE_RELATIVE_URL + "/*")
+
.handler(recorder.devConsoleHandler(devConsoleStaticResourcesDeploymentPath.toString(),
+ shutdownContext))
+ .build());
+ }
+
+ private static String getProperty(ConfigurationBuildItem
configurationBuildItem,
+ String propertyKey) {
+
+ String propertyValue = configurationBuildItem
+ .getReadResult()
+ .getAllBuildTimeValues()
+ .get(propertyKey);
+
+ if (propertyValue == null) {
+ propertyValue = configurationBuildItem
+ .getReadResult()
+ .getBuildTimeRunTimeValues()
+ .get(propertyKey);
+ } else {
+ return propertyValue;
+ }
+
+ if (propertyValue == null) {
+ propertyValue = configurationBuildItem
+ .getReadResult()
+ .getRunTimeDefaultValues()
+ .get(propertyKey);
+ }
+
+ return propertyValue;
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/SonataFlowQuarkusExtensionProcessor.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/SonataFlowQuarkusExtensionProcessor.java
new file mode 100644
index 00000000000..60d10d1853b
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/java/org/kie/sonataflow/swf/tools/deployment/SonataFlowQuarkusExtensionProcessor.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+class SonataFlowQuarkusExtensionProcessor {
+
+ private static final String FEATURE = "sonataflow-quarkus-devui-extension";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/embedded.html
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/embedded.html
new file mode 100644
index 00000000000..da2e7069430
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/embedded.html
@@ -0,0 +1,53 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<a href="{urlbase}/workflowInstances" class="badge badge-light">
+ <i class="fa fa-project-diagram fa-fw"></i>
+ Workflow Instances
+ <span id="workflowInstancesCount" class="badge badge-light" />
+</a>
+<a href="{urlbase}/monitoring" class="badge badge-light">
+ <i class="fa fa-tachometer fa-fw"></i>
+ Monitoring
+</a>
+<script>
+ const graphqlUrl = "{config:property('kogito.data-index.url') ?:
''}/graphql";
+
+ {|
+ const fillCount = () => {
+ fetch(graphqlUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ body: JSON.stringify({query: "query getAllProcessesIds{
ProcessInstances{ id } }"}),
+ })
+ .then(r => r.json())
+ .then(json =>
$("#workflowInstancesCount").text(json.data.ProcessInstances.length))
+ .catch(error => {
+ console.log("Error while trying to fetch workflow instances
count.");
+ console.error(error);
+ });
+ };
+
+ fillCount();
+ |}
+</script>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/monitoring.html
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/monitoring.html
new file mode 100644
index 00000000000..2132fd4c35c
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/monitoring.html
@@ -0,0 +1,44 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+{#include main fluid=true} {#style} .main-container { margin: 0; padding: 0; }
#envelope-app { width: 100vw; height:
+calc(100vh - 98px); } {/style} {#title}Runtime UI{/title} {#body}
+<div id="envelope-app"></div>
+
+<script src="resources/webapp/standalone.js"></script>
+<script>
+ const devUIUrl= {#if
config:property('kogito.dev-ui.url')}"{config:property('kogito.dev-ui.url')}"{#else}window.location.origin{/if};
+ const devUI = RuntimeToolsDevUI.open({
+ container: document.getElementById("envelope-app"),
+ isDataIndexAvailable: true,
+ dataIndexUrl: "{config:property('kogito.data-index.url') ?: ''}/graphql",
+ page: "Monitoring",
+ devUIUrl,
+ openApiBaseUrl: devUIUrl,
+ openApiPath: "q/openapi.json",
+ availablePages: ["Workflows", "Monitoring", "CustomDashboard"],
+ omittedWorkflowTimelineEvents: ["EmbeddedStart", "EmbeddedEnd",
"Script"],
+ diagramPreviewSize: {
+ width: 1000,
+ height: 1000
+ }
+ })
+</script>
+{/body} {/include}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/workflowInstances.html
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/workflowInstances.html
new file mode 100644
index 00000000000..90370483336
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/dev-templates/workflowInstances.html
@@ -0,0 +1,45 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+{#include main fluid=true} {#style} .main-container { margin: 0; padding: 0; }
#envelope-app { width: 100vw; height:
+calc(100vh - 98px); } {/style} {#title}Runtime UI{/title} {#body}
+<div id="envelope-app"></div>
+
+<script src="resources/webapp/standalone.js"></script>
+<script>
+ const devUIUrl= {#if
config:property('kogito.dev-ui.url')}"{config:property('kogito.dev-ui.url')}"{#else}window.location.origin{/if};
+
+ const devUI = RuntimeToolsDevUI.open({
+ container: document.getElementById("envelope-app"),
+ isDataIndexAvailable: true,
+ dataIndexUrl: "{config:property('kogito.data-index.url') ?: ''}/graphql",
+ devUIUrl,
+ page: "Workflows",
+ openApiBaseUrl: devUIUrl,
+ openApiPath: "q/openapi.json",
+ availablePages: ["Workflows", "Monitoring", "CustomDashboard"],
+ omittedWorkflowTimelineEvents: ["EmbeddedStart", "EmbeddedEnd",
"Script"],
+ diagramPreviewSize: {
+ width: 1000,
+ height: 1000
+ }
+ })
+</script>
+{/body} {/include}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/static/index.html
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/static/index.html
new file mode 100644
index 00000000000..8e850ece508
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension-deployment/src/main/resources/static/index.html
@@ -0,0 +1,45 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<div id="envelope-app"></div>
+
+<script src="resources/webapp/standalone.js"></script>
+<script>
+ const urlParams = new URLSearchParams(window.location.search);
+ const page = urlParams.get("page");
+ const devUIUrl = urlParams.get("devUIUrl");
+ const dataIndexUrl = urlParams.get("dataIndexUrl");
+
+ const devUI = RuntimeToolsDevUI.open({
+ container: document.getElementById("envelope-app"),
+ isDataIndexAvailable: true,
+ dataIndexUrl: dataIndexUrl ? dataIndexUrl : "" + "/graphql",
+ page: page,
+ devUIUrl: devUIUrl ? devUIUrl : window.location.origin,
+ openApiBaseUrl: devUIUrl ? devUIUrl : window.location.origin,
+ openApiPath: "q/openapi.json",
+ availablePages: ["Workflows", "Monitoring", "CustomDashboard"],
+ omittedWorkflowTimelineEvents: ["EmbeddedStart", "EmbeddedEnd", "Script"],
+ diagramPreviewSize: {
+ width: 1000,
+ height: 1000,
+ },
+ });
+</script>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/pom.xml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/pom.xml
new file mode 100644
index 00000000000..87e8bf44fe4
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/pom.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.kie.sonataflow</groupId>
+ <artifactId>sonataflow-quarkus-devui-extension-parent</artifactId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>sonataflow-quarkus-devui-extension</artifactId>
+ <name>KIE Tools :: SonataFlow Quarkus Dev UI Extension :: Runtime</name>
+ <description>Runtime development tools for Serverless Workflows</description>
+ <dependencies>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-jackson</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-rest-client</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-multipart</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-arc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus.arc</groupId>
+ <artifactId>arc-processor</artifactId>
+ </dependency>
+
+ <!-- Undertow is needed so that the static resource serving can correctly
locate CP resources from `META-INF/resources` of the application, as it would
be normally expected.
+ See https://issues.redhat.com/browse/KOGITO-3477 -->
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-undertow</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-maven-plugin</artifactId>
+ <version>${quarkus.platform.version}</version>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>extension-descriptor</goal>
+ </goals>
+ <configuration>
+
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${compiler-plugin.version}</version>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.platform.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardService.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardService.java
new file mode 100644
index 00000000000..530819d4cae
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardService.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard;
+
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+
+@Path("/customDashboard")
+public class CustomDashboardService {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(CustomDashboardService.class);
+
+ private CustomDashboardStorage storage;
+
+ @Inject
+ public void setStorage(CustomDashboardStorage storage) {
+ this.storage = storage;
+ }
+
+ @GET
+ @Path("/count")
+ @Produces(MediaType.TEXT_PLAIN)
+ public Response getCustomDashboardFilesCount() {
+ try {
+ return Response.ok(storage.getCustomDashboardFilesCount()).build();
+ } catch (Exception e) {
+ LOGGER.warn("Error while getting CustomDashboard file count: ", e);
+ return Response.status(INTERNAL_SERVER_ERROR.getStatusCode(),
"Unexpected error while getting CustomDashboard files count: " +
e.getMessage()).build();
+ }
+ }
+
+ @GET
+ @Path("/list")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getCustomDashboardFiles(@QueryParam("names")
CustomDashboardFilter filter) {
+ try {
+ return
Response.ok(storage.getCustomDashboardFiles(filter)).build();
+ } catch (Exception e) {
+ LOGGER.warn("Error while getting CustomDashboard list: ", e);
+ return Response.status(INTERNAL_SERVER_ERROR.getStatusCode(),
"Unexpected error while getting CustomDashboard files list: " +
e.getMessage()).build();
+ }
+ }
+
+ @GET
+ @Path("/{name:\\S+}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getCustomDashboardFileContent(@PathParam("name") String
name) {
+ try {
+ return
Response.ok(storage.getCustomDashboardFileContent(name)).build();
+ } catch (Exception e) {
+ LOGGER.warn("Error while getting CustomDashboard file content: ",
e);
+ return Response.status(INTERNAL_SERVER_ERROR.getStatusCode(),
"Unexpected error while getting CustomDashboard file content: " +
e.getMessage()).build();
+ }
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardStorage.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardStorage.java
new file mode 100644
index 00000000000..29f6096ad69
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/CustomDashboardStorage.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+import org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardInfo;
+
+public interface CustomDashboardStorage {
+
+ int getCustomDashboardFilesCount();
+
+ Collection<CustomDashboardInfo>
getCustomDashboardFiles(CustomDashboardFilter filter);
+
+ String getCustomDashboardFileContent(String name) throws IOException;
+
+ void updateCustomDashboard(String content);
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverter.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverter.java
new file mode 100644
index 00000000000..fe648a586ad
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverter.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.converter;
+
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.stream.Collectors;
+
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class CustomDashboardFilterParamConverter implements
ParamConverter<CustomDashboardFilter> {
+ public CustomDashboardFilter fromString(String names) {
+ StringTokenizer stringTokenizer = new StringTokenizer(names, ";");
+ return new
CustomDashboardFilter(Collections.list(stringTokenizer).stream().map(s ->
(String) s).collect(Collectors.toList()));
+ }
+
+ public String toString(CustomDashboardFilter names) {
+ return names.toString();
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverterProvider.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverterProvider.java
new file mode 100644
index 00000000000..dcf1487657b
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/converter/CustomDashboardFilterParamConverterProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.converter;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+
+import jakarta.ws.rs.ext.ParamConverter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Provider;
+
+@Provider
+public class CustomDashboardFilterParamConverterProvider implements
ParamConverterProvider {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> ParamConverter<T> getConverter(Class<T> rawType, Type
genericType, Annotation[] annotations) {
+ if (rawType.isAssignableFrom(CustomDashboardFilter.class)) {
+ return (ParamConverter<T>) new
CustomDashboardFilterParamConverter();
+ }
+ return null;
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageImpl.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageImpl.java
new file mode 100644
index 00000000000..5060c20f749
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageImpl.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.kie.sonataflow.swf.tools.custom.dashboard.CustomDashboardStorage;
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+import org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+
+@ApplicationScoped
+public class CustomDashboardStorageImpl implements CustomDashboardStorage {
+
+ public static final String PROJECT_CUSTOM_DASHBOARD_STORAGE_PROP =
"quarkus.kogito-runtime-tools.custom.dashboard.folder";
+ private static final String CUSTOM_DASHBOARD_STORAGE_PATH = "/dashboards/";
+ private static final Logger LOGGER =
LoggerFactory.getLogger(CustomDashboardStorageImpl.class);
+
+ private final Map<String, CustomDashboardInfo> customDashboardInfoMap =
new HashMap<>();
+
+ private URL classLoaderCustomDashboardUrl;
+ private URL customDashStorageUrl;
+
+ public CustomDashboardStorageImpl() {
+
start(Thread.currentThread().getContextClassLoader().getResource(CUSTOM_DASHBOARD_STORAGE_PATH));
+ }
+
+ public CustomDashboardStorageImpl(final URL classLoaderFormsUrl) {
+ start(classLoaderFormsUrl);
+ }
+
+ private void start(final URL classLoaderFormsUrl) {
+ start(classLoaderFormsUrl,
getCustomDashboardStorageUrl(classLoaderFormsUrl));
+ }
+
+ private void start(final URL classLoaderCustomDashboardUrl, final URL
customDashStorageUrl) {
+ try {
+ this.classLoaderCustomDashboardUrl = classLoaderCustomDashboardUrl;
+ this.customDashStorageUrl = customDashStorageUrl;
+ } catch (Exception ex) {
+ LOGGER.warn("Couldn't properly initialize
CustomDashboardStorageImpl");
+ } finally {
+ if (classLoaderCustomDashboardUrl == null) {
+ return;
+ }
+
+ init(readCustomDashboardResources());
+ String storageUrl = getStorageUrl(classLoaderCustomDashboardUrl);
+ Thread t = new Thread(new DashboardFilesWatcher(reload(),
storageUrl));
+ t.start();
+ }
+ }
+
+ protected String getStorageUrl(URL classLoaderCustomDashboardUrl) {
+ return ConfigProvider.getConfig()
+ .getOptionalValue(PROJECT_CUSTOM_DASHBOARD_STORAGE_PROP,
String.class)
+ .orElseGet(() -> classLoaderCustomDashboardUrl.getFile());
+ }
+
+ private URL getCustomDashboardStorageUrl(URL
classLoaderCustomDashboardUrl) {
+ if (classLoaderCustomDashboardUrl == null) {
+ return null;
+ }
+
+ String storageUrl = getStorageUrl(classLoaderCustomDashboardUrl);
+
+ File customDashStorageeFolder = new File(storageUrl);
+
+ if (!customDashStorageeFolder.exists() ||
!customDashStorageeFolder.isDirectory()) {
+ LOGGER.warn("Cannot initialize form storage folder in path '" +
customDashStorageeFolder.getPath() + "'");
+ }
+
+ try {
+ return customDashStorageeFolder.toURI().toURL();
+ } catch (MalformedURLException ex) {
+ LOGGER.warn("Cannot initialize form storage folder in path '" +
customDashStorageeFolder.getPath() + "'", ex);
+ }
+ return null;
+ }
+
+ @Override
+ public int getCustomDashboardFilesCount() {
+ return customDashboardInfoMap.size();
+ }
+
+ @Override
+ public Collection<CustomDashboardInfo>
getCustomDashboardFiles(CustomDashboardFilter filter) {
+ if (filter != null && !filter.getNames().isEmpty()) {
+ return customDashboardInfoMap.entrySet().stream()
+ .filter(entry ->
StringUtils.containsAnyIgnoreCase(entry.getKey(), filter.getNames().toArray(new
String[0])))
+ .map(Map.Entry::getValue)
+ .collect(Collectors.toList());
+ } else {
+ return customDashboardInfoMap.values();
+ }
+ }
+
+ @Override
+ public String getCustomDashboardFileContent(String name) throws
IOException {
+ try {
+ return IOUtils.toString(new
FileInputStream(customDashboardInfoMap.get(name).getPath()),
StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ LOGGER.info("custom-dashboard's file {} can not ready, because of
{}", customDashboardInfoMap.get(name).getPath(), e.getMessage());
+ throw e;
+ }
+ }
+
+ @Override
+ public void updateCustomDashboard(String content) {
+
+ }
+
+ private void init(Collection<File> files) {
+ customDashboardInfoMap.clear();
+ files.stream()
+ .forEach(file -> {
+ LocalDateTime lastModified =
LocalDateTime.ofInstant(Instant.ofEpochMilli(file.lastModified()),
TimeZone.getDefault().toZoneId());
+ customDashboardInfoMap.put(file.getName(),
+ new CustomDashboardInfo(file.getName(),
file.getPath(), lastModified));
+ });
+ }
+
+ private Collection<File> readCustomDashboardResources() {
+ if (classLoaderCustomDashboardUrl != null) {
+ LOGGER.info("custom-dashboard's files path is {}",
classLoaderCustomDashboardUrl.toString());
+ File rootFolder = FileUtils.toFile(classLoaderCustomDashboardUrl);
+ return FileUtils.listFiles(rootFolder, new String[] { "dash.yaml",
"dash.yml" }, true);
+ }
+ return Collections.emptyList();
+ }
+
+ private Consumer<Collection<File>> reload() {
+ return this::init;
+ }
+
+ private class DashboardFilesWatcher implements Runnable {
+
+ private final Map<WatchKey, Path> keys = new HashMap<>();
+ private Consumer<Collection<File>> consumer;
+ private String folder;
+
+ public DashboardFilesWatcher(Consumer<Collection<File>> consumer,
String folder) {
+ this.consumer = consumer;
+ this.folder = folder;
+ }
+
+ @Override
+ public void run() {
+ try (WatchService ws = FileSystems.getDefault().newWatchService())
{
+ Path path = Path.of(folder);
+ keys.put(path.register(ws, ENTRY_MODIFY, ENTRY_CREATE), path);
+
+ Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
+ keys.put(dir.register(ws, ENTRY_MODIFY, ENTRY_CREATE,
ENTRY_DELETE), dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ WatchKey key;
+ while ((key = ws.take()) != null) {
+ for (WatchEvent<?> event : key.pollEvents()) {
+ LOGGER.warn("Event kind: {}. File affected: {}",
event.kind(), event.context());
+ consumer.accept(readCustomDashboardResources());
+ }
+ key.reset();
+ }
+ } catch (InterruptedException e) {
+ LOGGER.warn("Exception in custom dashboard folder watcher for
folder: {}, message: {}", folder, e.getMessage(), e);
+ Thread.currentThread().interrupt();
+ } catch (IOException ex) {
+ LOGGER.warn("Exception in custom dashboard folder watcher for
folder: {}, message: {}", folder, ex.getMessage(), ex);
+ }
+ }
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardFilter.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardFilter.java
new file mode 100644
index 00000000000..e4a59b5917e
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardFilter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CustomDashboardFilter {
+
+ private final List<String> names;
+
+ public CustomDashboardFilter() {
+ this.names = new ArrayList<>();
+ }
+
+ public CustomDashboardFilter(List<String> names) {
+ this.names = names;
+ }
+
+ public List<String> getNames() {
+ return names;
+ }
+
+ public void setNames(List<String> names) {
+ this.names.addAll(names);
+ }
+
+ @Override
+ public String toString() {
+ return "CustomDashboardFilter{" +
+ "names=" + names +
+ '}';
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardInfo.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardInfo.java
new file mode 100644
index 00000000000..7c873cbd136
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/java/org/kie/sonataflow/swf/tools/custom/dashboard/model/CustomDashboardInfo.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.model;
+
+import java.time.LocalDateTime;
+
+public class CustomDashboardInfo {
+ String name;
+ String path;
+ LocalDateTime lastModified;
+
+ public CustomDashboardInfo(String name, String path, LocalDateTime
lastModified) {
+ this.name = name;
+ this.path = path;
+ this.lastModified = lastModified;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public LocalDateTime getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(LocalDateTime lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ CustomDashboardInfo that = (CustomDashboardInfo) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (path != null ? !path.equals(that.path) : that.path != null) {
+ return false;
+ }
+ return lastModified != null ? lastModified.equals(that.lastModified) :
that.lastModified == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (path != null ? path.hashCode() : 0);
+ result = 31 * result + (lastModified != null ? lastModified.hashCode()
: 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "CustomDashboardInfo{" +
+ "name='" + name + '\'' +
+ ", path='" + path + '\'' +
+ ", lastModified=" + lastModified +
+ '}';
+ }
+
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/beans.xml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/beans.xml
new file mode 100644
index 00000000000..030bdcbec5b
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,7 @@
+<beans
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"
+>
+
+</beans>
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/quarkus-extension.yaml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 00000000000..06ec65f1e4c
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+name: Serverless Workflow Tools
+metadata:
+ keywords:
+ - "sonataflow"
+ - "workflows"
+ guide: "https://quarkus.io/guides/kogito"
+ categories:
+ - "business-automation"
+ status: "preview"
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTest.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTest.java
new file mode 100644
index 00000000000..912c021d9a6
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.kie.sonataflow.swf.tools.custom.dashboard.CustomDashboardStorage;
+import
org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardFilter;
+import org.kie.sonataflow.swf.tools.custom.dashboard.model.CustomDashboardInfo;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class CustomDashboardStorageTest {
+
+ private static String[] DASHBOARD_NAMES = { "age.dash.yml",
"products.dash.yaml" };
+ private static String DASHBOARD_NAME = "age.dash.yml";
+
+ private CustomDashboardStorage customDashboardStorage;
+ private URL tempFolder;
+
+ @BeforeAll
+ public void init() {
+ tempFolder =
Thread.currentThread().getContextClassLoader().getResource("custom/dashboards/");
+
+ customDashboardStorage = new CustomDashboardStorageImpl(tempFolder);
+ }
+
+ @Test
+ public void testGetFormInfoList() {
+ Collection<CustomDashboardInfo> customDashboardInfoFilterAll =
customDashboardStorage.getCustomDashboardFiles(null);
+ assertEquals(2, customDashboardInfoFilterAll.size());
+
+ CustomDashboardFilter filterEmpty = new CustomDashboardFilter();
+ filterEmpty.setNames(Collections.emptyList());
+ Collection<CustomDashboardInfo> customDashboardInfoAllEmptyFilter =
customDashboardStorage.getCustomDashboardFiles(filterEmpty);
+ assertEquals(2, customDashboardInfoAllEmptyFilter.size());
+
+ CustomDashboardFilter filter = new CustomDashboardFilter();
+ filter.setNames(Arrays.asList(DASHBOARD_NAMES));
+
+ Collection<CustomDashboardInfo> formInfos =
customDashboardStorage.getCustomDashboardFiles(filter);
+ assertEquals(2, formInfos.size());
+ }
+
+ @Test
+ public void testHotReloading() throws IOException {
+ String storageUrl =
Thread.currentThread().getContextClassLoader().getResource("custom/dashboards/").getFile();
+ File srcFile = new File(storageUrl + "products.dash.yaml");
+ File targetFile = new File(storageUrl + "copy.dash.yml");
+
+ assertEquals(false, targetFile.exists());
+ FileUtils.copyFile(srcFile, targetFile);
+ assertEquals(true, targetFile.exists());
+ await().atMost(20, TimeUnit.SECONDS).until(() -> testBeforeDelete());
+ Collection<CustomDashboardInfo>
customDashboardInfoFilterAllBeforeDelete =
customDashboardStorage.getCustomDashboardFiles(null);
+ assertEquals(3, customDashboardInfoFilterAllBeforeDelete.size());
+
+ assertEquals(true, targetFile.exists());
+ FileUtils.delete(targetFile);
+ assertEquals(false, targetFile.exists());
+ await().atMost(20, TimeUnit.SECONDS).until(() -> testAfterDelete());
+
+ Collection<CustomDashboardInfo>
customDashboardInfoFilterAllAfterDelete =
customDashboardStorage.getCustomDashboardFiles(null);
+ assertEquals(2, customDashboardInfoFilterAllAfterDelete.size());
+ }
+
+ private boolean testBeforeDelete() {
+ if (customDashboardStorage.getCustomDashboardFiles(null).size() == 3) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean testAfterDelete() {
+ if (customDashboardStorage.getCustomDashboardFiles(null).size() == 2) {
+ return true;
+ }
+ return false;
+ }
+
+ @Test
+ public void testGetFormContent() throws IOException {
+ String content =
customDashboardStorage.getCustomDashboardFileContent(DASHBOARD_NAME);
+ assertNotNull(content);
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTestProfile.java
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTestProfile.java
new file mode 100644
index 00000000000..9b9e3350be9
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/java/org/kie/sonataflow/swf/tools/custom/dashboard/impl/CustomDashboardStorageTestProfile.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.sonataflow.swf.tools.custom.dashboard.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Collections;
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+
+import static
org.kie.sonataflow.swf.tools.custom.dashboard.impl.CustomDashboardStorageImpl.PROJECT_CUSTOM_DASHBOARD_STORAGE_PROP;
+
+public class CustomDashboardStorageTestProfile implements QuarkusTestProfile {
+
+ private String storagePath;
+
+ public CustomDashboardStorageTestProfile() throws IOException {
+ File storage =
Files.createTempDirectory("CustomDashboardStorageTestProfile").toFile();
+ storage.deleteOnExit();
+ storage.mkdir();
+ storagePath = storage.getAbsolutePath();
+ }
+
+ @Override
+ public Map<String, String> getConfigOverrides() {
+ return Collections.singletonMap(PROJECT_CUSTOM_DASHBOARD_STORAGE_PROP,
storagePath);
+ }
+}
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/products.dash.yaml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/products.dash.yaml
new file mode 100644
index 00000000000..ea685a0b5c3
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/products.dash.yaml
@@ -0,0 +1,61 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+datasets:
+ - uuid: products
+ content: >-
+ [
+ ["Computers", "Scanner", 5, 3],
+ ["Computers", "Printer", 7, 4],
+ ["Computers", "Laptop", 3, 2],
+ ["Electronics", "Camera", 10, 7],
+ ["Electronics", "Headphones", 5, 9]
+ ]
+ columns:
+ - id: Section
+ type: LABEL
+ - id: Product
+ type: LABEL
+ - id: Quantity
+ type: NUMBER
+ - id: Quantity2
+ type: NUMBER
+pages:
+ - components:
+ - html: Welcome to Dashbuilder!
+ properties:
+ font-size: xx-large
+ margin-bottom: 30px
+ - settings:
+ type: BARCHART
+ dataSetLookup:
+ uuid: products
+ group:
+ - columnGroup:
+ source: Product
+ groupFunctions:
+ - source: Product
+ - source: Quantity
+ function: SUM
+ - source: Quantity2
+ function: SUM
+ - settings:
+ type: TABLE
+ dataSetLookup:
+ uuid: products
diff --git
a/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/subdir/age.dash.yml
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/subdir/age.dash.yml
new file mode 100644
index 00000000000..011aff8684e
--- /dev/null
+++
b/packages/sonataflow-quarkus-devui-extension/sonataflow-quarkus-devui-extension/src/test/resources/custom/dashboards/subdir/age.dash.yml
@@ -0,0 +1,44 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+datasets:
+ - uuid: age
+ content: >-
+ [
+ ["John", 5],
+ ["Mary", 7],
+ ["Mark", 3]
+ ]
+ columns:
+ - id: Name
+ type: LABEL
+ - id: Age
+ type: Number
+pages:
+ - components:
+ - settings:
+ type: BARCHART
+ dataSetLookup:
+ uuid: age
+ group:
+ - columnGroup:
+ source: Name
+ groupFunctions:
+ - source: Name
+ - source: Age
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dac30f69a52..ddf6f313063 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9221,6 +9221,21 @@ importers:
specifier: ^5.9.0
version: 5.9.0
+ packages/sonataflow-quarkus-devui-extension:
+ devDependencies:
+ "@kie-tools/maven-config-setup-helper":
+ specifier: workspace:*
+ version: link:../maven-config-setup-helper
+ "@kie-tools/root-env":
+ specifier: workspace:*
+ version: link:../root-env
+ "@kie-tools/serverless-workflow-dev-ui-webapp":
+ specifier: workspace:*
+ version: link:../serverless-workflow-dev-ui-webapp
+ run-script-os:
+ specifier: ^1.1.6
+ version: 1.1.6
+
packages/storybook-base:
devDependencies:
"@kie-tools-core/webpack-base":
diff --git a/repo/graph.dot b/repo/graph.dot
index 30d6dff5996..ec49e8db3f4 100644
--- a/repo/graph.dot
+++ b/repo/graph.dot
@@ -150,6 +150,7 @@ digraph G {
"@kie-tools/serverless-workflow-service-catalog" [ color = "blue", fontcolor
= "blue", style = "rounded" ];
"@kie-tools/serverless-workflow-language-service" [ color = "blue",
fontcolor = "blue", style = "rounded" ];
"swf-vscode-extension" [ color = "blue", fontcolor = "blue", style =
"rounded" ];
+ "@kie-tools/sonataflow-quarkus-devui-extension" [ color = "black", fontcolor
= "black", style = "dashed, rounded" ];
"@kie-tools/stunner-editors-dmn-loader" [ color = "blue", fontcolor =
"blue", style = "rounded" ];
"@kie-tools/unitables" [ color = "blue", fontcolor = "blue", style =
"rounded" ];
"vscode-extension-dashbuilder-editor" [ color = "blue", fontcolor = "blue",
style = "rounded" ];
@@ -462,6 +463,7 @@ digraph G {
"swf-vscode-extension" -> "@kie-tools/vscode-extension-common-test-helpers"
[ style = "dashed", color = "blue" ];
"sonataflow-deployment-webapp" -> "@kie-tools-core/react-hooks" [ style =
"dashed", color = "blue" ];
"sonataflow-deployment-webapp" ->
"@kie-tools/runtime-tools-webapp-components" [ style = "dashed", color = "blue"
];
+ "@kie-tools/sonataflow-quarkus-devui-extension" ->
"@kie-tools/serverless-workflow-dev-ui-webapp" [ style = "dashed", color =
"black" ];
"@kie-tools/storybook-base" -> "@kie-tools-core/webpack-base" [ style =
"dashed", color = "blue" ];
"@kie-tools/storybook-base" -> "@kie-tools/tsconfig" [ style = "dashed",
color = "blue" ];
"@kie-tools/stunner-editors" -> "@kie-tools/stunner-editors-dmn-loader" [
style = "solid", color = "black" ];
diff --git a/repo/graph.json b/repo/graph.json
index 3440aac19f1..7014bcd673e 100644
--- a/repo/graph.json
+++ b/repo/graph.json
@@ -155,6 +155,7 @@
{ "id": "@kie-tools/serverless-workflow-jq-expressions" },
{ "id": "@kie-tools/serverless-workflow-service-catalog" },
{ "id": "swf-vscode-extension" },
+ { "id": "@kie-tools/sonataflow-quarkus-devui-extension" },
{ "id": "vscode-extension-dashbuilder-editor" },
{ "id": "vscode-extension-kie-ba-bundle" },
{ "id": "vscode-extension-kogito-bundle" },
@@ -963,6 +964,11 @@
"weight": 1
},
{ "source": "swf-vscode-extension", "target":
"@kie-tools/vscode-extension-common-test-helpers", "weight": 1 },
+ {
+ "source": "@kie-tools/sonataflow-quarkus-devui-extension",
+ "target": "@kie-tools/serverless-workflow-dev-ui-webapp",
+ "weight": 1
+ },
{ "source": "vscode-extension-dashbuilder-editor", "target":
"@kie-tools-core/vscode-extension", "weight": 1 },
{
"source": "vscode-extension-dashbuilder-editor",
@@ -1141,6 +1147,7 @@
["@kie-tools/serverless-workflow-text-editor",
"packages/serverless-workflow-text-editor"],
["swf-vscode-extension", "packages/serverless-workflow-vscode-extension"],
["sonataflow-deployment-webapp", "packages/sonataflow-deployment-webapp"],
+ ["@kie-tools/sonataflow-quarkus-devui-extension",
"packages/sonataflow-quarkus-devui-extension"],
["@kie-tools/storybook-base", "packages/storybook-base"],
["@kie-tools/stunner-editors", "packages/stunner-editors"],
["@kie-tools/stunner-editors-dmn-loader",
"packages/stunner-editors-dmn-loader"],
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]