Repository: apache/streampipes
Pull request #3047 (2024-07-17 19:05:19)

refactor(#2777): Fix test case for DateTimeFromStringProcessor
<!--
  ~ 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.
  ~
  -->

  <!--
Thanks for contributing! Here are some tips you can follow to help us incorporate your contribution quickly and easily:
1. If this is your first time, please read our contributor guidelines:
    - https://streampipes.apache.org/community/get-involved/
    - https://cwiki.apache.org/confluence/display/STREAMPIPES/Getting+Started
2. Make sure the PR title is formatted like: `[#<GitHub issue id>] PR title ...`
3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., `[WIP][#<GitHub issue id>] PR title ...`.
4. Please write your PR title to summarize what this PR proposes/fixes.
5. Link the PR to the corresponding GitHub issue (if present) in the `Development` section in the right menu bar.
6. Be sure to keep the PR description updated to reflect all changes.
7. If possible, provide a concise example to reproduce the issue for a faster review.
8. Make sure tests pass via `mvn clean install`.
9. (Optional) If the contribution is large, please file an Apache ICLA
    - http://apache.org/licenses/icla.pdf
-->

### Purpose
<!--
Please clarify what changes you are proposing and describe how those changes will address the issue.
Furthermore, describe potential consequences the changes might have.
-->

### Remarks
<!--
Is there anything left we need to pay attention on?
Are there some references that might be important? E.g. links to Confluence, or discussions
on the mailing list or GitHub.
-->
PR introduces (a) breaking change(s): no

PR introduces (a) deprecation(s): no



Patch:
diff --git a/streampipes-client-python/poetry.lock b/streampipes-client-python/poetry.lock
index d0f9111741..4338147b67 100644
--- a/streampipes-client-python/poetry.lock
+++ b/streampipes-client-python/poetry.lock
@@ -1719,44 +1719,44 @@ files = [
 
 [[package]]
 name = "mypy"
-version = "1.10.0"
+version = "1.11.0"
 description = "Optional static typing for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"},
-    {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"},
-    {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"},
-    {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"},
-    {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"},
-    {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"},
-    {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"},
-    {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"},
-    {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"},
-    {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"},
-    {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"},
-    {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"},
-    {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"},
-    {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"},
-    {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"},
-    {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"},
-    {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"},
-    {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"},
-    {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"},
-    {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"},
-    {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"},
-    {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"},
-    {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"},
-    {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"},
-    {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"},
-    {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"},
-    {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"},
+    {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"},
+    {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"},
+    {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"},
+    {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"},
+    {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"},
+    {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"},
+    {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"},
+    {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"},
+    {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"},
+    {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"},
+    {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"},
+    {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"},
+    {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"},
+    {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"},
+    {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"},
+    {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"},
+    {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"},
+    {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"},
+    {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"},
+    {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"},
+    {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"},
+    {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"},
+    {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"},
+    {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"},
+    {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"},
+    {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"},
+    {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"},
 ]
 
 [package.dependencies]
 mypy-extensions = ">=1.0.0"
 tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = ">=4.1.0"
+typing-extensions = ">=4.6.0"
 
 [package.extras]
 dmypy = ["psutil (>=4.0)"]
@@ -3885,4 +3885,4 @@ test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-it
 [metadata]
 lock-version = "2.0"
 python-versions = ">3.8.1,<3.12"
-content-hash = "0d45d9f1c001e6fe102370408f7a9a29d712e6e13c31f584326b9d228086ea34"
+content-hash = "3343cfec2162e5e4debb57f6cc76c5c7385479b2bdaa2a6b36dc37ad10a3998f"
diff --git a/streampipes-client-python/pyproject.toml b/streampipes-client-python/pyproject.toml
index 2e00a81a64..d6932a3aec 100644
--- a/streampipes-client-python/pyproject.toml
+++ b/streampipes-client-python/pyproject.toml
@@ -71,7 +71,7 @@ blacken-docs = "1.18.0"
 flake8 = "7.1.0"
 interrogate = { version = "1.7.0", extras = ["png"] }
 isort = "5.13.0"
-mypy = "1.10.0"
+mypy = "1.11.0"
 ruff = "0.5.0"
 pre-commit = "3.5.0"
 pytest = "8.2.0"
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/DefaultEnvValues.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/DefaultEnvValues.java
index 983cc02951..960c6d7406 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/DefaultEnvValues.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/DefaultEnvValues.java
@@ -24,7 +24,6 @@ public class DefaultEnvValues {
   public static final String INITIAL_CLIENT_USER_DEFAULT = "sp-service-client";
   public static final String INITIAL_CLIENT_SECRET_DEFAULT = "my-apache-streampipes-secret-key-change-me";
 
-  public static final int MAX_WAIT_TIME_AT_SHUTDOWN_DEFAULT = 10000;
   public static final String INSTALL_PIPELINE_ELEMENTS = "true";
 
   public static final String DEFAULT_ENCRYPTION_PASSCODE = "eGgemyGBoILAu3xckoIp";
diff --git a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GlobalStreamPipesConstants.java b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GlobalStreamPipesConstants.java
index c52eb6778b..b452d74c1a 100644
--- a/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GlobalStreamPipesConstants.java
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GlobalStreamPipesConstants.java
@@ -22,8 +22,6 @@ public class GlobalStreamPipesConstants {
   public static final String STD_ICON_NAME = "icon.png";
   public static final String STD_DOCUMENTATION_NAME = "documentation.md";
 
-  public static final String CONNECT_MASTER_SOURCES_ENDPOINT = "/streampipes-backend/api/v2/connect/master/sources";
-
   public static final String INTERNAL_TOPIC_PREFIX = "org-apache-streampipes-internal-";
 
 }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/param/model/WhereClauseParams.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/param/model/WhereClauseParams.java
index 6e1f633622..3381983268 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/param/model/WhereClauseParams.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/param/model/WhereClauseParams.java
@@ -98,7 +98,7 @@ public class WhereClauseParams implements IQueryStatement {
   }
 
   private Object returnCondition(String inputCondition) {
-    if (NumberUtils.isCreatable(inputCondition)) {
+    if (NumberUtils.isParsable(inputCondition)) {
       return Double.parseDouble(inputCondition);
     } else if (isBoolean(inputCondition)) {
       return Boolean.parseBoolean(inputCondition);
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml b/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
index 696ce89520..bc17948896 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/pom.xml
@@ -63,6 +63,12 @@
             <artifactId>junit-jupiter-params</artifactId>
             <scope>test</scope>
         </dependency>
+      <dependency>
+        <groupId>org.apache.streampipes</groupId>
+        <artifactId>streampipes-test-utils-executors</artifactId>
+        <version>0.97.0-SNAPSHOT</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
 
     <build>
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/SizeMeasureProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/SizeMeasureProcessor.java
index deea211707..c9d2cdc15f 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/SizeMeasureProcessor.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/SizeMeasureProcessor.java
@@ -48,6 +48,10 @@ public class SizeMeasureProcessor extends StreamPipesDataProcessor {
   static final String KILOBYTE_SIZE = "KILOBYTE";
   static final String MEGABYTE_SIZE = "MEGABYTE";
 
+  static final String BYTES_OPTION = "Bytes";
+  static final String KILO_BYTES_OPTION = "Kilobytes (1024 Bytes)";
+  static final String MEGA_BYTES_OPTION = "Megabytes (1024 Kilobytes)";
+
   static final String EVENT_SIZE = "eventSize";
 
   private String sizeUnit;
@@ -55,29 +59,37 @@ public class SizeMeasureProcessor extends StreamPipesDataProcessor {
   @Override
   public DataProcessorDescription declareModel() {
     return ProcessingElementBuilder.create("org.apache.streampipes.processors.enricher.jvm.sizemeasure")
-        .category(DataProcessorType.STRUCTURE_ANALYTICS)
-        .withAssets(ExtensionAssetType.DOCUMENTATION, ExtensionAssetType.ICON)
-        .withLocales(Locales.EN)
-        .requiredStream(StreamRequirementsBuilder
-            .create()
-            .requiredProperty(EpRequirements.anyProperty())
-            .build())
-        .requiredSingleValueSelection(Labels.withId(SIZE_UNIT),
-            Options.from(new Tuple2<>("Bytes", BYTE_SIZE),
-                new Tuple2<>("Kilobytes (1024 Bytes)", KILOBYTE_SIZE),
-                new Tuple2<>("Megabytes (1024 Kilobytes)", MEGABYTE_SIZE)))
-        .outputStrategy(OutputStrategies.append(EpProperties.doubleEp(
-            Labels.withId(EVENT_SIZE),
-            EVENT_SIZE,
-            "http://schema.org/contentSize")))
-        .build();
+                                   .category(DataProcessorType.STRUCTURE_ANALYTICS)
+                                   .withAssets(ExtensionAssetType.DOCUMENTATION, ExtensionAssetType.ICON)
+                                   .withLocales(Locales.EN)
+                                   .requiredStream(StreamRequirementsBuilder
+                                                       .create()
+                                                       .requiredProperty(EpRequirements.anyProperty())
+                                                       .build())
+                                   .requiredSingleValueSelection(
+                                       Labels.withId(SIZE_UNIT),
+                                       Options.from(
+                                           new Tuple2<>(BYTES_OPTION, BYTE_SIZE),
+                                           new Tuple2<>(KILO_BYTES_OPTION, KILOBYTE_SIZE),
+                                           new Tuple2<>(MEGA_BYTES_OPTION, MEGABYTE_SIZE)
+                                       )
+                                   )
+                                   .outputStrategy(OutputStrategies.append(EpProperties.doubleEp(
+                                       Labels.withId(EVENT_SIZE),
+                                       EVENT_SIZE,
+                                       "http://schema.org/contentSize"
+                                   )))
+                                   .build();
   }
 
   @Override
-  public void onInvocation(ProcessorParams parameters,
-                           SpOutputCollector spOutputCollector,
-                           EventProcessorRuntimeContext runtimeContext) throws SpRuntimeException {
-    this.sizeUnit = parameters.extractor().selectedSingleValueInternalName(SIZE_UNIT, String.class);
+  public void onInvocation(
+      ProcessorParams parameters,
+      SpOutputCollector spOutputCollector,
+      EventProcessorRuntimeContext runtimeContext
+  ) throws SpRuntimeException {
+    this.sizeUnit = parameters.extractor()
+                              .selectedSingleValueInternalName(SIZE_UNIT, String.class);
   }
 
   @Override
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/StringTimerProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/StringTimerProcessor.java
index c56488e64a..c00fcdfc50 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/StringTimerProcessor.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/main/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/StringTimerProcessor.java
@@ -47,13 +47,13 @@ public class StringTimerProcessor extends StreamPipesDataProcessor {
   public static final String FIELD_VALUE_ID = "fieldValue";
 
   public static final String OUTPUT_UNIT_ID = "outputUnit";
-  private static final String MILLISECONDS = "Milliseconds";
-  private static final String SECONDS = "Seconds";
-  private static final String MINUTES = "Minutes";
+  public static final String MILLISECONDS = "Milliseconds";
+  public static final String SECONDS = "Seconds";
+  public static final String MINUTES = "Minutes";
 
   public static final String OUTPUT_FREQUENCY = "outputFrequency";
-  private static final String ON_INPUT_EVENT = "On Input Event";
-  private static final String ON_STRING_VALUE_CHANGE = "When String Value Changes";
+  public static final String ON_INPUT_EVENT = "On Input Event";
+  public static final String ON_STRING_VALUE_CHANGE = "When String Value Changes";
 
   public static final String MEASURED_TIME_FIELD_RUNTIME_NAME = "measured_time";
   public static final String FIELD_VALUE_RUNTIME_NAME = "field_value";
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/AssetDashboardConfig.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/AssetDashboardConfig.java
deleted file mode 100644
index 9d162c9595..0000000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/AssetDashboardConfig.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.apache.streampipes.model.client.assetdashboard;
-
-import org.apache.streampipes.model.shared.api.Storable;
-
-import com.google.gson.annotations.SerializedName;
-
-import java.util.List;
-import java.util.Map;
-
-public class AssetDashboardConfig implements Storable {
-
-  private @SerializedName("_id") String dashboardId;
-  private @SerializedName("_rev") String rev;
-
-  private String dashboardName;
-  private String dashboardDescription;
-  private ImageInfo imageInfo;
-  private Map<String, Object> attrs;
-  private String className;
-  private List<CanvasElement> children;
-
-  public AssetDashboardConfig() {
-  }
-
-  public String getDashboardName() {
-    return dashboardName;
-  }
-
-  public void setDashboardName(String dashboardName) {
-    this.dashboardName = dashboardName;
-  }
-
-  public String getDashboardDescription() {
-    return dashboardDescription;
-  }
-
-  public void setDashboardDescription(String dashboardDescription) {
-    this.dashboardDescription = dashboardDescription;
-  }
-
-  public Map<String, Object> getAttrs() {
-    return attrs;
-  }
-
-  public void setAttrs(Map<String, Object> attrs) {
-    this.attrs = attrs;
-  }
-
-  public String getClassName() {
-    return className;
-  }
-
-  public void setClassName(String className) {
-    this.className = className;
-  }
-
-  public List<CanvasElement> getChildren() {
-    return children;
-  }
-
-  public void setChildren(List<CanvasElement> children) {
-    this.children = children;
-  }
-
-  public ImageInfo getImageInfo() {
-    return imageInfo;
-  }
-
-  public void setImageInfo(ImageInfo imageInfo) {
-    this.imageInfo = imageInfo;
-  }
-
-  public String getDashboardId() {
-    return dashboardId;
-  }
-
-  public void setDashboardId(String dashboardId) {
-    this.dashboardId = dashboardId;
-  }
-
-  public String getRev() {
-    return rev;
-  }
-
-  public void setRev(String rev) {
-    this.rev = rev;
-  }
-
-  @Override
-  public String getElementId() {
-    return this.dashboardId;
-  }
-
-  @Override
-  public void setElementId(String elementId) {
-    this.dashboardId = elementId;
-  }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/CanvasElement.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/CanvasElement.java
deleted file mode 100644
index a0cefd20ce..0000000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/CanvasElement.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.apache.streampipes.model.client.assetdashboard;
-
-import java.util.List;
-import java.util.Map;
-
-public class CanvasElement {
-
-  private Map<String, Object> attrs;
-  private String className;
-  private List<CanvasElement> children;
-
-  public CanvasElement() {
-  }
-
-  public Map<String, Object> getAttrs() {
-    return attrs;
-  }
-
-  public void setAttrs(Map<String, Object> attrs) {
-    this.attrs = attrs;
-  }
-
-  public String getClassName() {
-    return className;
-  }
-
-  public void setClassName(String className) {
-    this.className = className;
-  }
-
-  public List<CanvasElement> getChildren() {
-    return children;
-  }
-
-  public void setChildren(List<CanvasElement> children) {
-    this.children = children;
-  }
-}
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/ImageInfo.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/ImageInfo.java
deleted file mode 100644
index b80aeaf58b..0000000000
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/assetdashboard/ImageInfo.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.apache.streampipes.model.client.assetdashboard;
-
-public class ImageInfo {
-
-  private String imageName;
-  private float x;
-  private float y;
-  private float width;
-  private float height;
-  private float scaleX = 1;
-  private float scaleY = 1;
-  private float rotation = 0;
-
-  public ImageInfo() {
-  }
-
-  public float getX() {
-    return x;
-  }
-
-  public void setX(float x) {
-    this.x = x;
-  }
-
-  public float getY() {
-    return y;
-  }
-
-  public void setY(float y) {
-    this.y = y;
-  }
-
-  public float getWidth() {
-    return width;
-  }
-
-  public void setWidth(float width) {
-    this.width = width;
-  }
-
-  public float getHeight() {
-    return height;
-  }
-
-  public void setHeight(float height) {
-    this.height = height;
-  }
-
-  public float getScaleX() {
-    return scaleX;
-  }
-
-  public void setScaleX(float scaleX) {
-    this.scaleX = scaleX;
-  }
-
-  public float getScaleY() {
-    return scaleY;
-  }
-
-  public void setScaleY(float scaleY) {
-    this.scaleY = scaleY;
-  }
-
-  public String getImageName() {
-    return imageName;
-  }
-
-  public void setImageName(String imageName) {
-    this.imageName = imageName;
-  }
-
-  public float getRotation() {
-    return rotation;
-  }
-
-  public void setRotation(float rotation) {
-    this.rotation = rotation;
-  }
-}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java
deleted file mode 100644
index ed64308423..0000000000
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetDashboardResource.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.apache.streampipes.rest.impl;
-
-import org.apache.streampipes.manager.file.FileManager;
-import org.apache.streampipes.model.client.assetdashboard.AssetDashboardConfig;
-import org.apache.streampipes.rest.core.base.impl.AbstractRestResource;
-import org.apache.streampipes.rest.shared.exception.SpMessageException;
-import org.apache.streampipes.storage.api.CRUDStorage;
-import org.apache.streampipes.storage.management.StorageDispatcher;
-
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestPart;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.FileNameMap;
-import java.net.URLConnection;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.List;
-
-@RestController
-@RequestMapping("/api/v2/asset-dashboards")
-@Deprecated(forRemoval = true, since = "0.95.0")
-public class AssetDashboardResource extends AbstractRestResource {
-
-  private static final Logger LOG = LoggerFactory.getLogger(AssetDashboardResource.class);
-
-  private static final String APP_ID = "org.apache.streampipes.apps.assetdashboard";
-
-  @GetMapping(path = "/{dashboardId}", produces = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<AssetDashboardConfig> getAssetDashboard(@PathVariable("dashboardId") String dashboardId) {
-    return ok(getNoSqlStorage().getAssetDashboardStorage()
-                               .getElementById(dashboardId));
-  }
-
-  @PutMapping(
-      path = "/{dashboardId}",
-      produces = MediaType.APPLICATION_JSON_VALUE,
-      consumes = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<Void> updateAssetDashboard(
-      @PathVariable("dashboardId") String dashboardId,
-      @RequestBody AssetDashboardConfig dashboardConfig
-  ) {
-    AssetDashboardConfig dashboard = getAssetDashboardStorage().getElementById(dashboardId);
-    dashboardConfig.setRev(dashboard.getRev());
-    getNoSqlStorage().getAssetDashboardStorage()
-                     .updateElement(dashboardConfig);
-    return ok();
-  }
-
-  @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<List<AssetDashboardConfig>> getAllDashboards() {
-    return ok(getNoSqlStorage().getAssetDashboardStorage()
-                               .findAll());
-  }
-
-  @PostMapping(
-      produces = MediaType.APPLICATION_JSON_VALUE,
-      consumes = MediaType.APPLICATION_JSON_VALUE)
-  public ResponseEntity<Void> storeAssetDashboard(@RequestBody AssetDashboardConfig dashboardConfig) {
-    getNoSqlStorage().getAssetDashboardStorage()
-                     .persist(dashboardConfig);
-    return ok();
-  }
-
-  @DeleteMapping(path = "/{dashboardId}")
-  public ResponseEntity<Void> deleteAssetDashboard(@PathVariable("dashboardId") String dashboardId) {
-    getNoSqlStorage().getAssetDashboardStorage()
-                     .deleteElementById(dashboardId);
-    return ok();
-  }
-
-  @GetMapping(path = "/images/{imageName}")
-  public ResponseEntity<byte[]> getDashboardImage(@PathVariable("imageName") String imageName) {
-    try {
-      var sanitizedFileName = new FileManager().sanitizeFilename(imageName);
-      java.nio.file.Path path = Paths.get(getTargetFile(sanitizedFileName));
-      File file = new File(path.toString());
-      FileNameMap fileNameMap = URLConnection.getFileNameMap();
-      String mimeType = fileNameMap.getContentTypeFor(file.getName());
-      HttpHeaders headers = new HttpHeaders();
-      headers.setContentType(MediaType.parseMediaType(mimeType));
-      headers.setContentDispositionFormData("attachment", "filename"); // You can adjust the filename as needed
-
-      return new ResponseEntity<>(Files.readAllBytes(path), headers, org.springframework.http.HttpStatus.OK);
-    } catch (IOException e) {
-      LOG.error(e.getMessage(), e);
-      throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e);
-    }
-  }
-
-
-  @PostMapping(path = "/images", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-  public ResponseEntity<Void> storeDashboardImage(@RequestPart("file_upload") MultipartFile fileDetail) {
-    try {
-      var fileName = fileDetail.getName();
-
-      if (!new FileManager().validateFileType(fileName)) {
-        LOG.error("File type of file " + fileName + " is not supported");
-        fail();
-      }
-
-      storeFile(fileDetail.getName(), fileDetail.getInputStream());
-      return ok();
-    } catch (IOException e) {
-      LOG.error("Could not extract image input stream from request", e);
-      return fail();
-    }
-  }
-
-  private void storeFile(String fileName, InputStream fileInputStream) {
-
-    var targetDirectory = new File(getTargetDirectory());
-    if (!targetDirectory.exists()) {
-      targetDirectory.mkdirs();
-    }
-
-    var sanitizedFileName = new FileManager().sanitizeFilename(fileName);
-
-    var targetFile = new File(getTargetFile(sanitizedFileName));
-
-    try {
-      FileUtils.copyInputStreamToFile(fileInputStream, targetFile);
-    } catch (IOException e) {
-      LOG.error(e.getMessage(), e);
-      throw new SpMessageException(HttpStatus.INTERNAL_SERVER_ERROR, e);
-    }
-  }
-
-  private String getTargetDirectory() {
-    return System.getProperty("user.home") + File.separator + ".streampipes"
-        + File.separator + "assets" + File.separator + APP_ID;
-  }
-
-  private String getTargetFile(String filename) {
-    return getTargetDirectory() + File.separator + filename;
-  }
-
-  private CRUDStorage<AssetDashboardConfig> getAssetDashboardStorage() {
-    return StorageDispatcher.INSTANCE.getNoSqlStore()
-                                     .getAssetDashboardStorage();
-  }
-}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
index 2b8c0203d7..481bdd6871 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
@@ -17,7 +17,6 @@
  */
 package org.apache.streampipes.storage.api;
 
-import org.apache.streampipes.model.client.assetdashboard.AssetDashboardConfig;
 import org.apache.streampipes.model.client.user.Group;
 import org.apache.streampipes.model.client.user.PasswordRecoveryToken;
 import org.apache.streampipes.model.client.user.UserActivationToken;
@@ -49,8 +48,6 @@ public interface INoSqlStorage {
 
   INotificationStorage getNotificationStorageApi();
 
-  CRUDStorage<AssetDashboardConfig> getAssetDashboardStorage();
-
   CRUDStorage<DataLakeMeasure> getDataLakeStorage();
 
   CRUDStorage<FileMetadata> getFileMetadataStorage();
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
index 8f9cd5826b..c368713da7 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
@@ -17,7 +17,6 @@
  */
 package org.apache.streampipes.storage.couchdb;
 
-import org.apache.streampipes.model.client.assetdashboard.AssetDashboardConfig;
 import org.apache.streampipes.model.client.user.Group;
 import org.apache.streampipes.model.client.user.PasswordRecoveryToken;
 import org.apache.streampipes.model.client.user.UserActivationToken;
@@ -118,14 +117,6 @@ public enum CouchDbStorageManager implements INoSqlStorage {
     return new NotificationStorageImpl();
   }
 
-  @Override
-  public CRUDStorage<AssetDashboardConfig> getAssetDashboardStorage() {
-    return new DefaultCrudStorage<>(
-        () -> Utils.getCouchDbGsonClient("assetdashboard"),
-        AssetDashboardConfig.class
-    );
-  }
-
   @Override
   public CRUDStorage<DataLakeMeasure> getDataLakeStorage() {
     return new DefaultCrudStorage<>(
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/Approx.java
similarity index 68%
rename from ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts
rename to streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/Approx.java
index 16d3facbb7..7016681a65 100644
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.routes.ts
+++ b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/Approx.java
@@ -16,12 +16,13 @@
  *
  */
 
-import { SpBreadcrumbItem } from '@streampipes/shared-ui';
-import { SpAppRoutes } from '../app-overview/apps.routes';
+package org.apache.streampipes.test.executors;
 
-export class SpAppAssetMonitoringRoutes {
-    static BASE: SpBreadcrumbItem = {
-        label: 'Asset Monitoring',
-        link: [SpAppRoutes.APP_BASE_LINK, 'asset-monitoring'],
-    };
+/**
+ * This record can be used to define a double property that consides an epsilon for the assertion
+ *
+ * @param value   The numeric value of the event property.
+ * @param epsilon The tolerance level for the rounding operation, determining its precision for the assertion
+ */
+public record Approx(Double value, Double epsilon) {
 }
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
deleted file mode 100644
index 7fe7439dc4..0000000000
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-  ~ 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.
-  ~
-  -->
-
-<sp-basic-view showBackLink="true" [backLinkTarget]="['apps', 'overview']">
-    <ng-container nav>
-        <mat-tab-group
-            [selectedIndex]="selectedIndex"
-            (selectedIndexChange)="selectedIndexChange($event)"
-            color="accent"
-        >
-            <mat-tab label="Asset Dashboards"> </mat-tab>
-            <mat-tab id="all-adapters" label="New Asset Dashboard"> </mat-tab>
-        </mat-tab-group>
-    </ng-container>
-
-    <div fxLayout="column" fxFlex="100">
-        <sp-asset-dashboard-overview
-            *ngIf="selectedIndex === 0 && !dashboardSelected"
-            fxFlex="100"
-            (selectedDashboard)="openDashboard($event)"
-            (createDashboard)="selectedIndex = 1"
-        ></sp-asset-dashboard-overview>
-        <sp-view-asset
-            fxFlex="100"
-            *ngIf="selectedIndex === 0 && dashboardSelected"
-            [dashboardConfig]="selectedDashboard"
-            (dashboardClosed)="closeDashboard($event)"
-            (editDashboardEmitter)="editDashboard($event)"
-        ></sp-view-asset>
-        <sp-create-asset
-            *ngIf="selectedIndex === 1"
-            fxFlex="100"
-            (dashboardClosed)="closeDashboard($event)"
-            [dashboardConfig]="selectedDashboard"
-        ></sp-create-asset>
-    </div>
-</sp-basic-view>
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.scss b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.scss
deleted file mode 100644
index 618e5b0499..0000000000
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- *
- */
-
-.page-container-padding {
-    width: 100%;
-}
-
-.page-container-padding-inner {
-    padding: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts b/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts
deleted file mode 100644
index 945d1e5822..0000000000
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.component.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { DashboardConfiguration } from './model/dashboard-configuration.model';
-import { SpBreadcrumbService } from '@streampipes/shared-ui';
-import { SpAppRoutes } from '../app-overview/apps.routes';
-import { SpAppAssetMonitoringRoutes } from './app-asset-monitoring.routes';
-
-@Component({
-    selector: 'sp-app-asset-monitoring',
-    templateUrl: './app-asset-monitoring.component.html',
-    styleUrls: ['./app-asset-monitoring.component.scss'],
-})
-export class AppAssetMonitoringComponent implements OnInit {
-    selectedIndex = 0;
-    dashboardSelected = false;
-    selectedDashboard: DashboardConfiguration;
-    @Output() appOpened = new EventEmitter<boolean>();
-
-    constructor(private breadcrumbService: SpBreadcrumbService) {}
-
-    ngOnInit() {
-        this.breadcrumbService.updateBreadcrumb([
-            SpAppRoutes.BASE,
-            this.breadcrumbService.removeLink(SpAppAssetMonitoringRoutes.BASE),
-        ]);
-        this.appOpened.emit(true);
-    }
-
-    selectedIndexChange(index: number) {
-        this.selectedIndex = index;
-    }
-
-    openDashboard(dashboardConfig: DashboardConfiguration) {
-        this.selectedDashboard = dashboardConfig;
-        this.dashboardSelected = true;
-    }
-
-    closeDashboard(dashboardClosed: boolean) {
-        this.dashboardSelected = false;
-        this.selectedIndex = 0;
-    }
-
-    editDashboard(dashboardConfig: DashboardConfiguration) {
-        this.selectedDashboard = dashboardConfig;
-        this.selectedIndex = 1;
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts b/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
deleted file mode 100644
index df9d4bfe46..0000000000
--- a/ui/src/app/app-asset-monitoring/app-asset-monitoring.module.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { NgModule } from '@angular/core';
-import { FlexLayoutModule } from '@ngbracket/ngx-layout';
-import { CommonModule } from '@angular/common';
-
-import { AppAssetMonitoringComponent } from './app-asset-monitoring.component';
-
-import { ViewAssetComponent } from './components/view-asset/view-asset.component';
-import { CreateAssetComponent } from './components/create-asset/create-asset.component';
-import { AddPipelineDialogComponent } from './dialog/add-pipeline/add-pipeline-dialog.component';
-import { MatFormFieldModule } from '@angular/material/form-field';
-import { MatGridListModule } from '@angular/material/grid-list';
-import { MatInputModule } from '@angular/material/input';
-import { FormsModule } from '@angular/forms';
-import { ColorPickerModule } from 'ngx-color-picker';
-import { SaveDashboardDialogComponent } from './dialog/save-dashboard/save-dashboard-dialog.component';
-import { AssetDashboardOverviewComponent } from './components/dashboard-overview/dashboard-overview.component';
-import { AddLinkDialogComponent } from './dialog/add-link/add-link-dialog.component';
-import { RouterModule } from '@angular/router';
-import { SharedUiModule } from '@streampipes/shared-ui';
-import { MatDividerModule } from '@angular/material/divider';
-import { MatIconModule } from '@angular/material/icon';
-import { MatTabsModule } from '@angular/material/tabs';
-import { MatButtonModule } from '@angular/material/button';
-
-@NgModule({
-    imports: [
-        CommonModule,
-        FlexLayoutModule,
-        MatDividerModule,
-        MatGridListModule,
-        MatIconModule,
-        MatTabsModule,
-        MatButtonModule,
-        MatInputModule,
-        MatFormFieldModule,
-        FormsModule,
-        ColorPickerModule,
-        RouterModule.forChild([
-            {
-                path: '',
-                component: AppAssetMonitoringComponent,
-            },
-        ]),
-        SharedUiModule,
-    ],
-    declarations: [
-        AppAssetMonitoringComponent,
-        CreateAssetComponent,
-        ViewAssetComponent,
-        AddLinkDialogComponent,
-        AddPipelineDialogComponent,
-        SaveDashboardDialogComponent,
-        AssetDashboardOverviewComponent,
-    ],
-    providers: [],
-    exports: [AppAssetMonitoringComponent],
-})
-export class AppAssetMonitoringModule {}
diff --git a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.html b/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.html
deleted file mode 100644
index d5654571d5..0000000000
--- a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!--
-  ~ 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 fxLayout="column" fxFlex="100">
-    <input
-        type="file"
-        (change)="handleFileInput($event)"
-        accept="image/*"
-        #file
-        style="display: none"
-    />
-    <div class="sp-tab-bg sp-blue-bg page-container-nav">
-        <div fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
-            <div>
-                <button
-                    color="accent"
-                    class="mat-basic"
-                    mat-button
-                    (click)="prepareDashboard()"
-                    type="submit"
-                    [disabled]="!backgroundImagePresent || !measurementPresent"
-                >
-                    <mat-icon>save</mat-icon>&nbsp;Save
-                </button>
-            </div>
-            <div>
-                <button
-                    color="accent"
-                    mat-button
-                    (click)="file.click()"
-                    type="submit"
-                    [disabled]="backgroundImagePresent"
-                >
-                    <mat-icon>file_upload</mat-icon>&nbsp;<span>Add image</span>
-                </button>
-            </div>
-            <div>
-                <button
-                    color="accent"
-                    mat-button
-                    (click)="openAddPipelineDialog()"
-                >
-                    <mat-icon>add</mat-icon>&nbsp;Add value
-                </button>
-            </div>
-            <div>
-                <button color="accent" mat-button (click)="openAddLinkDialog()">
-                    <span fxLayoutAlign="start center"
-                        ><i class="material-icons">link</i>&nbsp;Add link</span
-                    >
-                </button>
-            </div>
-            <div fxFlex fxLayout="row" fxLayoutAlign="end center">
-                <button
-                    color="accent"
-                    mat-icon-button
-                    (click)="clearCanvas()"
-                    matTooltip="Clear"
-                >
-                    <i class="material-icons"> clear </i>
-                </button>
-            </div>
-        </div>
-    </div>
-    <div id="outerAssemblyArea" class="asset-configuration-board-panel">
-        <div
-            id="asset-configuration-board-canvas"
-            class="asset-configuration-board-canvas"
-            fxLayoutAlign="center center"
-        ></div>
-    </div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.scss b/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.scss
deleted file mode 100644
index 457e5201c8..0000000000
--- a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- *
- */
-
-.asset-configuration-board-panel {
-    min-height: calc(100vh - 70px);
-}
-
-.asset-configuration-board-canvas {
-    width: 1400px;
-    height: 900px;
-    border: 2px solid rgb(27, 20, 100);
-    margin: 20px auto;
-    background: white;
-}
diff --git a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.ts b/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.ts
deleted file mode 100644
index e3d1569bb6..0000000000
--- a/ui/src/app/app-asset-monitoring/components/create-asset/create-asset.component.ts
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * 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.
- *
- */
-
-import {
-    AfterViewInit,
-    Component,
-    EventEmitter,
-    HostListener,
-    Input,
-    Output,
-} from '@angular/core';
-import Konva from 'konva';
-import { AddPipelineDialogComponent } from '../../dialog/add-pipeline/add-pipeline-dialog.component';
-import { MatDialog } from '@angular/material/dialog';
-import { ShapeService } from '../../services/shape.service';
-import { SaveDashboardDialogComponent } from '../../dialog/save-dashboard/save-dashboard-dialog.component';
-import { PanelType, DialogService } from '@streampipes/shared-ui';
-import { DashboardConfiguration } from '../../model/dashboard-configuration.model';
-import { RestService } from '../../services/rest.service';
-import { AddLinkDialogComponent } from '../../dialog/add-link/add-link-dialog.component';
-import { IdGeneratorService } from '../../../core-services/id-generator/id-generator.service';
-
-interface Window {
-    Image: any;
-}
-
-declare const window: Window;
-
-@Component({
-    selector: 'sp-create-asset',
-    templateUrl: './create-asset.component.html',
-    styleUrls: ['./create-asset.component.scss'],
-})
-export class CreateAssetComponent implements AfterViewInit {
-    fileName: any;
-    selectedUploadFile: File;
-
-    mainCanvasStage: Konva.Stage;
-    backgroundImageLayer: any;
-    mainLayer: any;
-
-    currentlySelectedShape: any;
-
-    IMAGE_ID = 'main-image';
-
-    backgroundImagePresent = false;
-    measurementPresent = false;
-    editMode = false;
-
-    @Input()
-    dashboardConfig: DashboardConfiguration;
-
-    @Output() dashboardClosed = new EventEmitter<boolean>();
-
-    keyboardListenerActive = true;
-
-    constructor(
-        public dialog: MatDialog,
-        public shapeService: ShapeService,
-        private dialogService: DialogService,
-        private restService: RestService,
-        private idGeneratorService: IdGeneratorService,
-    ) {}
-
-    ngAfterViewInit() {
-        const width = 1400;
-        const height = 900;
-        if (!this.dashboardConfig) {
-            this.mainCanvasStage = new Konva.Stage({
-                container: 'asset-configuration-board-canvas',
-                width,
-                height,
-            });
-            this.initLayers();
-        } else {
-            this.editMode = true;
-            this.makeEditable();
-            this.mainCanvasStage = Konva.Node.create(
-                this.dashboardConfig,
-                'asset-configuration-board-canvas',
-            );
-            this.mainCanvasStage.draw();
-
-            this.backgroundImageLayer = this.mainCanvasStage.children[0];
-            this.mainLayer = this.mainCanvasStage.children[1];
-            const groups = this.mainLayer.getChildren().find('Group');
-            groups.forEach(g => {
-                const id = this.idGeneratorService.generate(6);
-                g.id(id);
-                g.setDraggable(true);
-                this.addTransformerToShape(id, g);
-            });
-            this.makeClickable();
-            this.showImage();
-            this.backgroundImageLayer.moveToBottom();
-            this.mainCanvasStage.draw();
-            this.measurementPresent = true;
-        }
-
-        const container = this.mainCanvasStage.container();
-        container.focus();
-    }
-
-    makeEditable() {
-        this.dashboardConfig.imageInfo.draggable = true;
-        this.dashboardConfig.imageInfo.id = this.IMAGE_ID;
-    }
-
-    initLayers() {
-        this.mainLayer = new Konva.Layer();
-        this.backgroundImageLayer = new Konva.Layer();
-
-        this.makeClickable();
-        this.mainCanvasStage.add(this.backgroundImageLayer);
-        this.mainCanvasStage.add(this.mainLayer);
-    }
-
-    makeClickable() {
-        this.backgroundImageLayer.on('click', evt => {
-            this.currentlySelectedShape = evt.target;
-        });
-        this.mainLayer.on('click', evt => {
-            let parentElement = evt.target.getParent();
-            while (!parentElement.id()) {
-                parentElement = parentElement.getParent();
-            }
-            this.currentlySelectedShape = parentElement;
-        });
-    }
-
-    handleFileInput(event: any) {
-        const files: any = event.target.files;
-        this.selectedUploadFile = files[0];
-        this.fileName = this.selectedUploadFile.name;
-
-        const image = new window.Image();
-        image.onload = () => {
-            const desiredWidth = Math.min(
-                this.mainCanvasStage.width(),
-                image.width,
-            );
-            const aspectRatio = image.width / image.height;
-            const desiredHeight =
-                image.width > image.height
-                    ? desiredWidth / aspectRatio
-                    : desiredWidth * aspectRatio;
-            const imageCanvas = new Konva.Image({
-                image,
-                width: desiredWidth,
-                height: desiredHeight,
-                x: 0,
-                y: 0,
-                draggable: true,
-                id: this.IMAGE_ID,
-            });
-
-            this.addImageTransformer(imageCanvas);
-            this.currentlySelectedShape = imageCanvas;
-        };
-
-        const reader = new FileReader();
-        reader.onload = e => (image.src = reader.result);
-
-        reader.readAsDataURL(this.selectedUploadFile);
-        event.target.value = null;
-    }
-
-    addImageTransformer(imageCanvas: any) {
-        this.backgroundImageLayer.add(imageCanvas);
-        this.backgroundImageLayer.draw();
-
-        const tr = this.getNewTransformer(this.IMAGE_ID);
-        this.backgroundImageLayer.add(tr);
-        tr.attachTo(imageCanvas);
-        this.backgroundImageLayer.moveToBottom();
-        this.backgroundImageLayer.draw();
-        this.backgroundImagePresent = true;
-    }
-
-    prepareDashboard() {
-        const dialogRef = this.dialogService.open(
-            SaveDashboardDialogComponent,
-            {
-                panelType: PanelType.SLIDE_IN_PANEL,
-                title: 'Save asset dashboard',
-                width: '50vw',
-                data: {
-                    dashboardCanvas: this.mainCanvasStage as any,
-                    file: this.selectedUploadFile,
-                    editMode: this.editMode,
-                    dashboardConfig: this.dashboardConfig,
-                },
-            },
-        );
-        dialogRef.afterClosed().subscribe(closed => {
-            this.dashboardClosed.emit(true);
-        });
-    }
-
-    clearCanvas() {
-        this.backgroundImageLayer.destroy();
-        this.mainLayer.destroy();
-        this.initLayers();
-        this.backgroundImagePresent = false;
-        this.measurementPresent = false;
-    }
-
-    openAddPipelineDialog(): void {
-        this.keyboardListenerActive = false;
-        const dialogRef = this.dialogService.open(AddPipelineDialogComponent, {
-            panelType: PanelType.SLIDE_IN_PANEL,
-            title: 'Add visualization',
-            width: '50vw',
-            data: {},
-        });
-
-        dialogRef.afterClosed().subscribe(result => {
-            if (result) {
-                const visGroup =
-                    this.shapeService.makeNewMeasurementShape(result);
-                this.addNewVisulizationItem(visGroup);
-                this.measurementPresent = true;
-                this.mainLayer.draw();
-            }
-            this.keyboardListenerActive = true;
-        });
-    }
-
-    openAddLinkDialog() {
-        this.keyboardListenerActive = false;
-        const dialogRef = this.dialogService.open(AddLinkDialogComponent, {
-            panelType: PanelType.SLIDE_IN_PANEL,
-            title: 'Add link',
-            width: '50vw',
-            data: {},
-        });
-
-        dialogRef.afterClosed().subscribe(result => {
-            if (result) {
-                console.log(result);
-                this.addNewVisulizationItem(result);
-            }
-            this.keyboardListenerActive = true;
-        });
-    }
-
-    @HostListener('document:keydown', ['$event'])
-    handleKeyboardEvent(event: KeyboardEvent) {
-        if (this.keyboardListenerActive) {
-            const delta = 4;
-            if (event.code === 'Delete') {
-                const id = this.currentlySelectedShape.id();
-                this.mainCanvasStage
-                    .findOne('#' + id + '-transformer')
-                    .destroy();
-                this.currentlySelectedShape.destroy();
-                if (id === this.IMAGE_ID) {
-                    this.backgroundImagePresent = false;
-                } else {
-                    const remainingElementIds = this.mainLayer.find('Group');
-                    if (remainingElementIds.length === 0) {
-                        this.measurementPresent = false;
-                    }
-                }
-            } else if (event.code === 'ArrowLeft') {
-                this.currentlySelectedShape.x(
-                    this.currentlySelectedShape.x() - delta,
-                );
-            } else if (event.code === 'ArrowRight') {
-                this.currentlySelectedShape.x(
-                    this.currentlySelectedShape.x() + delta,
-                );
-            } else if (event.code === 'ArrowDown') {
-                this.currentlySelectedShape.y(
-                    this.currentlySelectedShape.y() + delta,
-                );
-            } else if (event.code === 'ArrowUp') {
-                this.currentlySelectedShape.y(
-                    this.currentlySelectedShape.y() - delta,
-                );
-            }
-            this.backgroundImageLayer.draw();
-            this.mainLayer.draw();
-        }
-    }
-
-    addNewVisulizationItem(visGroup) {
-        const id = this.idGeneratorService.generate(6);
-        visGroup.id(id);
-        this.mainLayer.add(visGroup);
-        this.addTransformerToShape(id, visGroup);
-    }
-
-    addTransformerToShape(id: string, visGroup: any) {
-        const tr = this.getNewTransformer(id);
-        this.mainLayer.add(tr);
-        tr.attachTo(visGroup);
-        this.mainLayer.draw();
-        this.currentlySelectedShape = visGroup;
-    }
-
-    getNewTransformer(id: string): Konva.Transformer {
-        return new Konva.Transformer({
-            anchorStroke: 'white',
-            anchorFill: '#39B54A',
-            anchorSize: 10,
-            borderStroke: 'green',
-            borderDash: [3, 3],
-            keepRatio: true,
-            id: id + '-transformer',
-        });
-    }
-
-    showImage() {
-        const image = new window.Image();
-        image.src = this.restService.getImageUrl(
-            this.dashboardConfig.imageInfo.imageName,
-        );
-        this.dashboardConfig.imageInfo.image = image;
-        image.onload = () => {
-            const imageCanvas = new Konva.Image(this.dashboardConfig.imageInfo);
-            this.addImageTransformer(imageCanvas);
-        };
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html
deleted file mode 100644
index 6724e0a4df..0000000000
--- a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!--
-  ~ 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 fxFlex="100" fxLayout="column" class="page-container-padding-inner">
-    <h1>Asset Dashboards</h1>
-    <mat-grid-list
-        [cols]="3"
-        [rowHeight]="500"
-        [gutterSize]="10"
-        fxFlex="100"
-        *ngIf="dashboardConfigs.length > 0"
-    >
-        <mat-grid-tile
-            class="gray"
-            *ngFor="let dashboardConfig of dashboardConfigs"
-        >
-            <mat-card class="example-card">
-                <mat-card-header>
-                    <mat-card-title>
-                        {{ dashboardConfig.dashboardName }}</mat-card-title
-                    >
-                    <mat-card-subtitle>{{
-                        dashboardConfig.dashboardDescription
-                    }}</mat-card-subtitle>
-                </mat-card-header>
-                <img mat-card-image [src]="getImageUrl(dashboardConfig)" />
-                <mat-card-content>
-                    <p></p>
-                </mat-card-content>
-                <mat-card-actions>
-                    <button
-                        mat-button
-                        mat-raised-button
-                        color="accent"
-                        (click)="openDashboard(dashboardConfig)"
-                    >
-                        Open Dashboard
-                    </button>
-                    <button
-                        mat-button
-                        mat-raised-button
-                        class="mat-basic"
-                        (click)="deleteDashboard(dashboardConfig.dashboardId)"
-                    >
-                        Delete
-                    </button>
-                </mat-card-actions>
-            </mat-card>
-        </mat-grid-tile>
-    </mat-grid-list>
-    <div
-        *ngIf="dashboardConfigs.length === 0"
-        fxLayoutAlign="center center"
-        fxFlex="100"
-        fxLayout="column"
-    >
-        <h4>No asset dashboards available</h4>
-        <button
-            mat-button
-            mat-raised-button
-            color="accent"
-            style="margin-top: 10px"
-            (click)="createDashboard.emit()"
-        >
-            Create new
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.scss b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.scss
deleted file mode 100644
index 39527e95b7..0000000000
--- a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- *
- */
-
-.example-card {
-    max-width: 400px;
-}
-
-mat-card {
-    box-shadow:
-        0 2px 1px -1px rgba(0, 0, 0, 0.2),
-        0 1px 1px 0 rgba(0, 0, 0, 0.14),
-        0 1px 3px 0 rgba(0, 0, 0, 0.12);
-    margin: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts b/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts
deleted file mode 100644
index 7f7748e946..0000000000
--- a/ui/src/app/app-asset-monitoring/components/dashboard-overview/dashboard-overview.component.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { RestService } from '../../services/rest.service';
-import { DashboardConfiguration } from '../../model/dashboard-configuration.model';
-
-@Component({
-    selector: 'sp-asset-dashboard-overview',
-    templateUrl: './dashboard-overview.component.html',
-    styleUrls: ['./dashboard-overview.component.scss'],
-})
-export class AssetDashboardOverviewComponent implements OnInit {
-    @Output() selectedDashboard = new EventEmitter<DashboardConfiguration>();
-    @Output() createDashboard = new EventEmitter<void>();
-
-    dashboardConfigs: DashboardConfiguration[] = [];
-
-    constructor(private restService: RestService) {}
-
-    ngOnInit() {
-        this.getDashboards();
-    }
-
-    getImageUrl(dashboardConfig: DashboardConfiguration) {
-        return this.restService.getImageUrl(
-            dashboardConfig.imageInfo.imageName,
-        );
-    }
-
-    getDashboards() {
-        this.restService.getDashboards().subscribe(response => {
-            this.dashboardConfigs = response;
-        });
-    }
-
-    openDashboard(dashboardConfig: DashboardConfiguration) {
-        this.selectedDashboard.emit(dashboardConfig);
-    }
-
-    deleteDashboard(dashboardId: string) {
-        this.restService.deleteDashboard(dashboardId).subscribe(response => {
-            this.getDashboards();
-        });
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.html b/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.html
deleted file mode 100644
index e9187a6c3b..0000000000
--- a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!--
-  ~ 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 fxFlex="100" fxLayout="column" class="page-container-padding-inner">
-    <div fxLayout="row">
-        <div fxLayout="fill">
-            <h1>{{ dashboardConfig.dashboardName }}</h1>
-        </div>
-        <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
-            <button
-                mat-button
-                mat-raised-button
-                color="accent"
-                (click)="editDashboard()"
-                class="mr-10"
-            >
-                Edit dashboard
-            </button>
-            <button
-                mat-button
-                mat-raised-button
-                class="mat-basic"
-                (click)="closeDashboard()"
-            >
-                Close dashboard
-            </button>
-        </div>
-    </div>
-    <div id="container" class="asset-view-canvas"></div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.scss b/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.scss
deleted file mode 100644
index 39b9d68bb7..0000000000
--- a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- *
- */
-
-.asset-view-canvas {
-    width: 1400px;
-    height: 900px;
-    border: 2px solid rgb(27, 20, 100);
-    margin: 20px auto;
-}
-
-.mr-10 {
-    margin-right: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts b/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts
deleted file mode 100644
index cd67c268b6..0000000000
--- a/ui/src/app/app-asset-monitoring/components/view-asset/view-asset.component.ts
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.
- *
- */
-
-import {
-    AfterViewInit,
-    Component,
-    EventEmitter,
-    Input,
-    OnDestroy,
-    Output,
-} from '@angular/core';
-
-import Konva from 'konva';
-import { DashboardConfiguration } from '../../model/dashboard-configuration.model';
-import { RestService } from '../../services/rest.service';
-import {
-    DatalakeQueryParameterBuilder,
-    DatalakeRestService,
-    SpQueryResult,
-    DashboardService,
-} from '@streampipes/platform-services';
-import { Subscription, timer } from 'rxjs';
-import { switchMap } from 'rxjs/operators';
-
-interface Window {
-    Image: any;
-}
-
-declare const window: Window;
-
-@Component({
-    selector: 'sp-view-asset',
-    templateUrl: './view-asset.component.html',
-    styleUrls: ['./view-asset.component.scss'],
-})
-export class ViewAssetComponent implements AfterViewInit, OnDestroy {
-    @Input() dashboardConfig: DashboardConfiguration;
-    @Output() dashboardClosed = new EventEmitter<boolean>();
-    @Output() editDashboardEmitter = new EventEmitter<DashboardConfiguration>();
-
-    mainCanvasStage: any;
-    mainLayer: any;
-    backgroundImageLayer: any;
-
-    subscriptions: Subscription[] = [];
-
-    constructor(
-        private restService: RestService,
-        private dashboardService: DashboardService,
-        private dataLakeRestService: DatalakeRestService,
-    ) {}
-
-    ngAfterViewInit() {
-        this.mainCanvasStage = Konva.Node.create(
-            this.dashboardConfig,
-            'container',
-        );
-        this.mainCanvasStage.draw();
-
-        this.backgroundImageLayer = new Konva.Layer();
-        this.showImage();
-        this.mainCanvasStage.add(this.backgroundImageLayer);
-        const labels = this.mainCanvasStage.find('Label');
-        labels.each(label => {
-            label.on('mouseenter', () => this.onMouseEnter(label));
-            label.on('mouseleave', () => this.onMouseLeave(label));
-            label.on('click', () => this.onLinkClicked(label));
-        });
-
-        this.backgroundImageLayer.moveToBottom();
-        this.mainCanvasStage.draw();
-        this.updateMeasurements();
-    }
-
-    onMouseEnter(label) {
-        label.children[0].attrs.fontStyle = 'bold';
-        this.mainCanvasStage.draw();
-    }
-
-    onMouseLeave(label) {
-        label.children[0].attrs.fontStyle = 'normal';
-        this.mainCanvasStage.draw();
-    }
-
-    onLinkClicked(label) {
-        const href = label.children[0].attrs.hyperlink;
-        const newWindow = label.children[0].attrs.newWindow;
-        newWindow
-            ? (window as any).open(href)
-            : ((window as any).location.href = href);
-    }
-
-    updateMeasurements() {
-        const dynamicShapes = this.mainCanvasStage.find('.dynamic-text');
-        dynamicShapes.forEach(ds => {
-            const monitoredField = ds.text();
-            const measurement = ds.attrs.dataLakeMeasure;
-            const subscription = timer(0, 2000)
-                .pipe(
-                    switchMap(() =>
-                        this.dataLakeRestService.getData(
-                            measurement,
-                            this.buildQuery(),
-                        ),
-                    ),
-                )
-                .subscribe(queryResult => {
-                    this.handleResponse(ds, monitoredField, queryResult);
-                });
-            this.subscriptions.push(subscription);
-        });
-    }
-
-    handleResponse(
-        ds: any,
-        monitoredField: string,
-        queryResult: SpQueryResult,
-    ): void {
-        if (queryResult.total > 0) {
-            if (queryResult.allDataSeries.length === 1) {
-                const series = queryResult.allDataSeries[0];
-                if (series.rows.length > 0) {
-                    const row = series.rows[0];
-                    const event = {};
-                    series.headers.forEach((fieldName, index) => {
-                        event[fieldName] = row[index];
-                    });
-                    ds.text(event[monitoredField]);
-                    this.mainCanvasStage.draw();
-                }
-            }
-        }
-    }
-
-    buildQuery() {
-        const queryBuilder = DatalakeQueryParameterBuilder.create();
-        return queryBuilder.withLimit(1).withOrdering('DESC').build();
-    }
-
-    showImage() {
-        const image = new window.Image();
-        image.src = this.restService.getImageUrl(
-            this.dashboardConfig.imageInfo.imageName,
-        );
-        this.dashboardConfig.imageInfo.image = image;
-        image.onload = () => {
-            const imageCanvas = new Konva.Image(this.dashboardConfig.imageInfo);
-            this.backgroundImageLayer.add(imageCanvas);
-            this.backgroundImageLayer.draw();
-        };
-    }
-
-    closeDashboard() {
-        this.dashboardClosed.emit(true);
-    }
-
-    editDashboard() {
-        this.editDashboardEmitter.emit(this.dashboardConfig);
-    }
-
-    ngOnDestroy(): void {
-        this.subscriptions.forEach(s => s.unsubscribe());
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.html b/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.html
deleted file mode 100644
index b2a3919fb7..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!--
-  ~ 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 class="sp-dialog-container">
-    <div class="sp-dialog-content p-15">
-        <div fxFlex="100" fxLayout="column">
-            <h4>New link</h4>
-            <div class="dialog-margin-bottom" fxLayout="column">
-                <mat-form-field class="dialog-margin-bottom" color="accent">
-                    <mat-label>Label</mat-label>
-                    <input
-                        matInput
-                        placeholder="Label"
-                        [(ngModel)]="linkLabel"
-                    />
-                    <mat-hint
-                        >The label that should be displayed as link</mat-hint
-                    >
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Target</mat-label>
-                    <input
-                        matInput
-                        placeholder="Label"
-                        [(ngModel)]="linkHref"
-                    />
-                    <mat-hint>The target URL of the link</mat-hint>
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Font Size</mat-label>
-                    <input
-                        matInput
-                        placeholder="Label"
-                        [(ngModel)]="labelFontSize"
-                    />
-                    <mat-hint>Font Size</mat-hint>
-                </mat-form-field>
-                <mat-checkbox [(ngModel)]="newWindow"
-                    >Open in new window</mat-checkbox
-                >
-            </div>
-        </div>
-    </div>
-    <mat-divider></mat-divider>
-    <div class="sp-dialog-actions">
-        <button
-            mat-button
-            mat-raised-button
-            class="mat-basic mr-10"
-            (click)="cancel()"
-        >
-            Cancel
-        </button>
-        <button mat-button mat-raised-button color="accent" (click)="add()">
-            Add
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.scss b/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.scss
deleted file mode 100644
index 0a5104be4d..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- *
- */
-
-@import '../../../../scss/sp/sp-dialog.scss';
-
-.mr-10 {
-    margin-right: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.ts b/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.ts
deleted file mode 100644
index 9dc2b03427..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-link/add-link-dialog.component.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Component } from '@angular/core';
-import { DialogRef } from '@streampipes/shared-ui';
-import { ShapeService } from '../../services/shape.service';
-import { HyperlinkConfig } from '../../model/selected-visualization-data.model';
-
-@Component({
-    selector: 'sp-add-link-dialog-component',
-    templateUrl: 'add-link-dialog.component.html',
-    styleUrls: ['./add-link-dialog.component.scss'],
-})
-export class AddLinkDialogComponent {
-    linkLabel: string;
-    linkHref: string;
-    labelFontSize = 12;
-    newWindow = false;
-
-    constructor(
-        private dialogRef: DialogRef<AddLinkDialogComponent>,
-        private shapeService: ShapeService,
-    ) {}
-
-    cancel() {
-        this.dialogRef.close();
-    }
-
-    add() {
-        const hyperlinkConfig: HyperlinkConfig = {
-            linkLabel: this.linkLabel,
-            linkHref: this.linkHref,
-            labelFontSize: this.labelFontSize,
-            newWindow: this.newWindow,
-        };
-
-        const group = this.shapeService.makeNewHyperlinkGroup(hyperlinkConfig);
-        this.dialogRef.close(group);
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.html b/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.html
deleted file mode 100644
index 5aef9519e6..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.html
+++ /dev/null
@@ -1,164 +0,0 @@
-<!--
-~ 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 class="sp-dialog-container">
-    <div class="sp-dialog-content p-15">
-        <div fxFlex="100">
-            <div fxFlex="100" style="margin: 5px; width: 100%">
-                <div *ngIf="page === 'select-pipeline'">
-                    <div *ngIf="page === 'select-pipeline'">
-                        <h4>{{ pages[0].description }}</h4>
-                        <mat-list>
-                            <mat-list-item
-                                *ngFor="let pipeline of visualizablePipelines"
-                                (click)="selectPipeline(pipeline)"
-                                class="list-item"
-                            >
-                                <div
-                                    matListItemAvatar
-                                    class="pipeline-avatar sp-accent-bg"
-                                >
-                                    {{ iconText(pipeline.pipelineName) }}
-                                </div>
-                                <span matListItemTitle>{{
-                                    pipeline.pipelineName
-                                }}</span>
-                                <p matListItemLine>
-                                    {{ pipeline.measureName }}
-                                </p>
-                            </mat-list-item>
-                        </mat-list>
-                    </div>
-                </div>
-
-                <!-- Select Type -->
-                <div *ngIf="page === 'select-measurement'" fxLayout="column">
-                    <h4>{{ pages[1].description }}</h4>
-                    <div fxFlex="100" fxLayout="column">
-                        <mat-radio-group
-                            fxLayout="column"
-                            class="example-radio-group"
-                            [(ngModel)]="selectedMeasurement"
-                        >
-                            <mat-radio-button
-                                class="example-radio-button"
-                                *ngFor="
-                                    let prop of selectedVisualization
-                                        .eventSchema.eventProperties
-                                "
-                                [value]="prop.runtimeName"
-                            >
-                                {{ prop.runtimeName }}
-                            </mat-radio-button>
-                        </mat-radio-group>
-                    </div>
-                </div>
-
-                <!-- Select Scheme -->
-                <div *ngIf="page === 'select-label'" fxLayout="column">
-                    <b
-                        ><h4>{{ pages[2].description }}</h4></b
-                    >
-                    <div fxFlex="100" fxLayout="column">
-                        <mat-form-field
-                            style="margin-bottom: 10px"
-                            color="accent"
-                        >
-                            <mat-label>Label</mat-label>
-                            <input
-                                matInput
-                                placeholder="Label"
-                                [(ngModel)]="selectedLabel"
-                                value="Label"
-                            />
-                            <mat-hint
-                                >Enter the label that will identify the
-                                measurement</mat-hint
-                            >
-                        </mat-form-field>
-                        <div fxLayout="row" class="element-margin">
-                            <mat-label fxFlex="50"
-                                >Label Background Color</mat-label
-                            >
-                            <input
-                                [(colorPicker)]="selectedLabelBackgroundColor"
-                                [style.background]="
-                                    selectedLabelBackgroundColor
-                                "
-                            />
-                        </div>
-                        <div fxLayout="row" class="element-margin">
-                            <mat-label fxFlex="50">Label Text Color</mat-label>
-                            <input
-                                [(colorPicker)]="selectedLabelTextColor"
-                                [style.background]="selectedLabelTextColor"
-                            />
-                        </div>
-                        <div fxLayout="row" class="element-margin">
-                            <mat-label fxFlex="50"
-                                >Measurement Value Background Color</mat-label
-                            >
-                            <input
-                                [(colorPicker)]="
-                                    selectedMeasurementBackgroundColor
-                                "
-                                [style.background]="
-                                    selectedMeasurementBackgroundColor
-                                "
-                            />
-                        </div>
-                        <div fxLayout="row" class="element-margin">
-                            <mat-label fxFlex="50"
-                                >Measurement Value Text Color</mat-label
-                            >
-                            <input
-                                [(colorPicker)]="selectedMeasurementTextColor"
-                                [style.background]="
-                                    selectedMeasurementTextColor
-                                "
-                            />
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <mat-divider></mat-divider>
-    <div class="sp-dialog-actions">
-        <button
-            mat-button
-            mat-raised-button
-            class="mat-basic mr-10"
-            (click)="onCancel()"
-        >
-            Cancel
-        </button>
-        <button
-            mat-button
-            mat-raised-button
-            class="mat-basic mr-10"
-            (click)="back()"
-            *ngIf="!('select-pipeline' === page)"
-        >
-            Back
-        </button>
-        <button mat-button mat-raised-button color="accent" (click)="next()">
-            Next
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.scss b/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.scss
deleted file mode 100644
index cdf80f50ad..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.scss
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- *
- */
-
-@import '../../../../scss/sp/sp-dialog.scss';
-
-.element-margin {
-    margin-top: 10px;
-    margin-bottom: 10px;
-}
-
-.mat-radio-button {
-    padding: 10px;
-}
-
-.mat-radio-button {
-    padding: 10px;
-}
-
-.pipeline-avatar {
-    align-items: center;
-    justify-content: center;
-    display: flex;
-    color: white;
-}
-
-.list-item:hover {
-    background: var(--color-bg-1);
-    cursor: pointer;
-}
-
-.list-item {
-    border-bottom: 1px solid #bdbdbd;
-}
-
-.mr-10 {
-    margin-right: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.ts b/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.ts
deleted file mode 100644
index a1508555e2..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/add-pipeline/add-pipeline-dialog.component.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Component, OnInit } from '@angular/core';
-import { RestApi } from '../../../services/rest-api.service';
-import { RestService } from '../../services/rest.service';
-import { ElementIconText } from '../../../services/get-element-icon-text.service';
-import { SelectedVisualizationData } from '../../model/selected-visualization-data.model';
-import { DialogRef } from '@streampipes/shared-ui';
-import {
-    DataLakeMeasure,
-    DatalakeRestService,
-    DataViewDataExplorerService,
-} from '@streampipes/platform-services';
-import { zip } from 'rxjs';
-
-@Component({
-    selector: 'sp-add-pipeline-dialog-component',
-    templateUrl: './add-pipeline-dialog.component.html',
-    styleUrls: ['./add-pipeline-dialog.component.scss'],
-})
-export class AddPipelineDialogComponent implements OnInit {
-    pages = [
-        {
-            type: 'select-pipeline',
-            title: 'Select Pipeline',
-            description: "Select a pipeline you'd like to visualize",
-        },
-        {
-            type: 'select-measurement',
-            title: 'Measurement Value',
-            description: 'Select measurement',
-        },
-        {
-            type: 'select-label',
-            title: 'Label',
-            description: 'Choose label',
-        },
-    ];
-
-    visualizablePipelines: DataLakeMeasure[] = [];
-
-    selectedVisualization: DataLakeMeasure;
-    selectedType: any;
-    selectedMeasurement: any;
-    page: any = 'select-pipeline';
-
-    selectedLabelBackgroundColor = '#FFFFFF';
-    selectedLabelTextColor = '#1B1464';
-    selectedMeasurementBackgroundColor = '#39B54A';
-    selectedMeasurementTextColor = '#FFFFFF';
-    selectedLabel: string;
-
-    constructor(
-        private dialogRef: DialogRef<AddPipelineDialogComponent>,
-        private restApi: RestApi,
-        private restService: RestService,
-        private dataLakeRestService: DatalakeRestService,
-        private dataExplorerService: DataViewDataExplorerService,
-        public elementIconText: ElementIconText,
-    ) {}
-
-    ngOnInit() {
-        this.loadVisualizablePipelines();
-    }
-
-    loadVisualizablePipelines() {
-        zip(
-            this.dataExplorerService.getAllPersistedDataStreams(),
-            this.dataLakeRestService.getAllMeasurementSeries(),
-        ).subscribe(res => {
-            const visualizablePipelines = res[0];
-            visualizablePipelines.forEach(p => {
-                const measurement = res[1].find(m => {
-                    return m.measureName === p.measureName;
-                });
-                p.eventSchema = measurement.eventSchema;
-            });
-            this.visualizablePipelines = visualizablePipelines;
-        });
-    }
-
-    onCancel(): void {
-        this.dialogRef.close();
-    }
-
-    getSelectedPipelineCss(vis) {
-        return this.getSelectedCss(this.selectedVisualization, vis);
-    }
-
-    getSelectedVisTypeCss(type) {
-        return this.getSelectedCss(this.selectedType, type);
-    }
-
-    getSelectedCss(selected, current) {
-        if (selected === current) {
-            return 'wizard-preview wizard-preview-selected';
-        } else {
-            return 'wizard-preview';
-        }
-    }
-
-    getTabCss(page) {
-        if (page === this.page) {
-            return 'md-fab md-accent';
-        } else {
-            return 'md-fab md-accent wizard-inactive';
-        }
-    }
-
-    selectPipeline(vis) {
-        this.selectedVisualization = vis;
-        this.next();
-    }
-
-    next() {
-        if (this.page === 'select-pipeline') {
-            this.page = 'select-measurement';
-        } else if (this.page === 'select-measurement') {
-            this.page = 'select-label';
-        } else {
-            const selectedConfig: SelectedVisualizationData =
-                {} as SelectedVisualizationData;
-            selectedConfig.labelBackgroundColor =
-                this.selectedLabelBackgroundColor;
-            selectedConfig.labelTextColor = this.selectedLabelTextColor;
-            selectedConfig.measurementBackgroundColor =
-                this.selectedMeasurementBackgroundColor;
-            selectedConfig.measurementTextColor =
-                this.selectedMeasurementTextColor;
-            selectedConfig.measurement = this.selectedMeasurement;
-            selectedConfig.visualizationId =
-                this.selectedVisualization.pipelineId;
-            selectedConfig.label = this.selectedLabel;
-            selectedConfig.dataLakeMeasure =
-                this.selectedVisualization.measureName;
-
-            this.dialogRef.close(selectedConfig);
-        }
-    }
-
-    back() {
-        if (this.page === 'select-measurement') {
-            this.page = 'select-pipeline';
-        } else if (this.page === 'select-label') {
-            this.page = 'select-measurement';
-        }
-    }
-
-    iconText(s) {
-        return this.elementIconText.getElementIconText(s);
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.html b/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.html
deleted file mode 100644
index 93d8183005..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
-  ~ 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 class="sp-dialog-container">
-    <div class="sp-dialog-content p-15">
-        <div fxFlex="100" fxLayout="column">
-            <h4>Dashboard Settings</h4>
-            <div class="dialog-margin-bottom" fxLayout="column">
-                <mat-form-field class="dialog-margin-bottom" color="accent">
-                    <mat-label>Dashboard Name</mat-label>
-                    <input
-                        matInput
-                        placeholder="Label"
-                        [(ngModel)]="dashboardName"
-                    />
-                    <mat-hint>The name of your new asset dashboard</mat-hint>
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Description</mat-label>
-                    <input
-                        matInput
-                        placeholder="Label"
-                        [(ngModel)]="dashboardDescription"
-                    />
-                    <mat-hint
-                        >The description of your new asset dashboard</mat-hint
-                    >
-                </mat-form-field>
-            </div>
-        </div>
-    </div>
-    <mat-divider></mat-divider>
-    <div class="sp-dialog-actions">
-        <button
-            mat-button
-            mat-raised-button
-            class="mat-basic mr-10"
-            (click)="cancel()"
-        >
-            Cancel
-        </button>
-        <button mat-button mat-raised-button color="accent" (click)="save()">
-            Save
-        </button>
-    </div>
-</div>
diff --git a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.scss b/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.scss
deleted file mode 100644
index da2aed864a..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- *
- */
-
-@import '../../../../scss/sp/sp-dialog.scss';
-
-.element-margin {
-    margin-top: 10px;
-    margin-bottom: 10px;
-}
-
-.mr-10 {
-    margin-right: 10px;
-}
-
-.dialog-margin-bottom {
-    margin-bottom: 10px;
-}
diff --git a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.ts b/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.ts
deleted file mode 100644
index 0a4a2cbf10..0000000000
--- a/ui/src/app/app-asset-monitoring/dialog/save-dashboard/save-dashboard-dialog.component.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Component, Input, OnInit } from '@angular/core';
-import { RestService } from '../../services/rest.service';
-import { DashboardConfiguration } from '../../model/dashboard-configuration.model';
-import { ImageInfo } from '../../model/image-info.model';
-import { DialogRef } from '@streampipes/shared-ui';
-import Konva from 'konva';
-import Stage = Konva.Stage;
-
-@Component({
-    selector: 'sp-save-dashboard-dialog-component',
-    templateUrl: 'save-dashboard-dialog.component.html',
-    styleUrls: ['./save-dashboard-dialog.component.scss'],
-})
-export class SaveDashboardDialogComponent implements OnInit {
-    dashboardName: string;
-    dashboardDescription: string;
-
-    @Input()
-    dashboardCanvas: Stage;
-
-    @Input()
-    file: File;
-
-    @Input()
-    editMode: boolean;
-
-    @Input()
-    dashboardConfig: DashboardConfiguration;
-
-    constructor(
-        private dialogRef: DialogRef<SaveDashboardDialogComponent>,
-        private restService: RestService,
-    ) {}
-
-    ngOnInit() {
-        if (this.editMode) {
-            this.dashboardName = this.dashboardConfig.dashboardName;
-            this.dashboardDescription =
-                this.dashboardConfig.dashboardDescription;
-        }
-    }
-
-    cancel() {
-        this.dialogRef.close();
-    }
-
-    save() {
-        // save image
-        if (this.file) {
-            this.restService.storeImage(this.file).subscribe(response => {});
-        }
-
-        // save dashboard
-        const imageInfo = this.makeImageInfo();
-        const dashboardConfig = this.makeDashboardConfig();
-        dashboardConfig.dashboardName = this.dashboardName;
-        dashboardConfig.dashboardDescription = this.dashboardDescription;
-        dashboardConfig.imageInfo = imageInfo;
-        dashboardConfig.imageInfo.draggable = false;
-        if (this.file) {
-            dashboardConfig.imageInfo.imageName = this.file.name;
-        }
-
-        if (this.editMode) {
-            dashboardConfig.dashboardId = this.dashboardConfig.dashboardId;
-        }
-
-        const observable = this.editMode
-            ? this.restService.updateDashboard(dashboardConfig)
-            : this.restService.storeDashboard(dashboardConfig);
-        observable.subscribe(response => {
-            this.dialogRef.close();
-        });
-    }
-
-    makeImageInfo(): ImageInfo {
-        const imageShape = this.dashboardCanvas.findOne('#main-image');
-        return imageShape.attrs as ImageInfo;
-    }
-
-    makeDashboardConfig(): DashboardConfiguration {
-        const canvas = this.dashboardCanvas;
-        const transformerShapes = Array.from(canvas.find('Transformer'));
-        transformerShapes.forEach(shape => {
-            shape.destroy();
-        });
-
-        const mainShape = canvas.findOne('#main-image');
-        mainShape.destroy();
-
-        return JSON.parse(canvas.toJSON());
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/model/canvas-attributes.model.ts b/ui/src/app/app-asset-monitoring/model/canvas-attributes.model.ts
deleted file mode 100644
index e65920f769..0000000000
--- a/ui/src/app/app-asset-monitoring/model/canvas-attributes.model.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- *
- */
-
-export interface CanvasAttributes {
-    x: number;
-    y: number;
-    visualizationId: string;
-    scaleX: number;
-    scaleY: number;
-    fill: string;
-    id: string;
-    text: string;
-    width: number;
-    height: number;
-    rotation: number;
-    brokerUrl: string;
-    topic: string;
-    name: string;
-    align: string;
-    fontSize: string;
-}
diff --git a/ui/src/app/app-asset-monitoring/model/canvas-configuration.model.ts b/ui/src/app/app-asset-monitoring/model/canvas-configuration.model.ts
deleted file mode 100644
index 30ee9ebdc8..0000000000
--- a/ui/src/app/app-asset-monitoring/model/canvas-configuration.model.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.
- *
- */
-
-import Konva from 'konva';
-
-export interface CanvasConfiguration {
-    file: File;
-    dashboardCanvas: Konva.Stage;
-}
diff --git a/ui/src/app/app-asset-monitoring/model/canvas-element.model.ts b/ui/src/app/app-asset-monitoring/model/canvas-element.model.ts
deleted file mode 100644
index 9bba980de4..0000000000
--- a/ui/src/app/app-asset-monitoring/model/canvas-element.model.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { CanvasAttributes } from './canvas-attributes.model';
-
-export interface CanvasElement {
-    attrs: CanvasAttributes;
-    className: string;
-    children: CanvasElement[];
-}
diff --git a/ui/src/app/app-asset-monitoring/model/dashboard-configuration.model.ts b/ui/src/app/app-asset-monitoring/model/dashboard-configuration.model.ts
deleted file mode 100644
index 6ab768c5db..0000000000
--- a/ui/src/app/app-asset-monitoring/model/dashboard-configuration.model.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { CanvasElement } from './canvas-element.model';
-import { CanvasAttributes } from './canvas-attributes.model';
-import { ImageInfo } from './image-info.model';
-
-export interface DashboardConfiguration {
-    dashboardName: string;
-    dashboardDescription: string;
-    dashboardId: string;
-    imageInfo: ImageInfo;
-    attrs: CanvasAttributes;
-    className: string;
-    children: CanvasElement[];
-}
diff --git a/ui/src/app/app-asset-monitoring/model/image-info.model.ts b/ui/src/app/app-asset-monitoring/model/image-info.model.ts
deleted file mode 100644
index ca011eb321..0000000000
--- a/ui/src/app/app-asset-monitoring/model/image-info.model.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- *
- */
-
-export interface ImageInfo {
-    imageName: string;
-    x: number;
-    y: number;
-    width: number;
-    height: number;
-    scaleX: number;
-    scaleY: number;
-    rotation: number;
-    image: any;
-    draggable: boolean;
-    id: string;
-}
diff --git a/ui/src/app/app-asset-monitoring/model/selected-visualization-data.model.ts b/ui/src/app/app-asset-monitoring/model/selected-visualization-data.model.ts
deleted file mode 100644
index 611bc0d6ef..0000000000
--- a/ui/src/app/app-asset-monitoring/model/selected-visualization-data.model.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- *
- */
-
-export interface SelectedVisualizationData {
-    labelBackgroundColor: string;
-    labelTextColor: string;
-    measurementBackgroundColor: string;
-    measurementTextColor: string;
-    visualizationId: string;
-    measurement: string;
-    label: string;
-    dataLakeMeasure: string;
-}
-
-export interface HyperlinkConfig {
-    linkLabel: string;
-    linkHref: string;
-    labelFontSize: number;
-    newWindow: boolean;
-}
diff --git a/ui/src/app/app-asset-monitoring/services/rest.service.ts b/ui/src/app/app-asset-monitoring/services/rest.service.ts
deleted file mode 100644
index 5e107245f3..0000000000
--- a/ui/src/app/app-asset-monitoring/services/rest.service.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { HttpClient } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-import { map } from 'rxjs/operators';
-import { Observable } from 'rxjs';
-import { DashboardConfiguration } from '../model/dashboard-configuration.model';
-import { PlatformServicesCommons } from '@streampipes/platform-services';
-
-@Injectable({ providedIn: 'root' })
-export class RestService {
-    constructor(
-        private http: HttpClient,
-        private platformServicesCommons: PlatformServicesCommons,
-    ) {}
-
-    getVisualizablePipelines(): Observable<any> {
-        return this.http.get(
-            '/visualizablepipeline/_all_docs?include_docs=true',
-        );
-    }
-
-    getPipeline(pipelineId): Observable<any> {
-        return this.http.get('/pipeline/' + pipelineId);
-    }
-
-    storeImage(file: File): Observable<any> {
-        const data: FormData = new FormData();
-        data.append('file_upload', file, file.name);
-        return this.http.post(this.imagePath, data).pipe(
-            map(res => {
-                return res;
-            }),
-        );
-    }
-
-    deleteDashboard(dashboardId: string) {
-        return this.http.delete(`${this.url}/${dashboardId}`);
-    }
-
-    storeDashboard(dashboardConfig: DashboardConfiguration) {
-        return this.http.post(this.url, dashboardConfig);
-    }
-
-    updateDashboard(dashboardConfig: DashboardConfiguration) {
-        return this.http.put(
-            this.url + '/' + dashboardConfig.dashboardId,
-            dashboardConfig,
-        );
-    }
-
-    getDashboards(): Observable<DashboardConfiguration[]> {
-        return this.http.get(this.url).pipe(
-            map(response => {
-                return response as DashboardConfiguration[];
-            }),
-        );
-    }
-
-    getImageUrl(imageName: string): string {
-        return `${this.imagePath}/${imageName}`;
-    }
-
-    private get url() {
-        return `${this.platformServicesCommons.apiBasePath}/asset-dashboards`;
-    }
-
-    private get imagePath() {
-        return `${this.url}/images`;
-    }
-}
diff --git a/ui/src/app/app-asset-monitoring/services/shape.service.ts b/ui/src/app/app-asset-monitoring/services/shape.service.ts
deleted file mode 100644
index 07fd333db0..0000000000
--- a/ui/src/app/app-asset-monitoring/services/shape.service.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.
- *
- */
-
-import { Injectable } from '@angular/core';
-
-import Konva from 'konva';
-import {
-    HyperlinkConfig,
-    SelectedVisualizationData,
-} from '../model/selected-visualization-data.model';
-
-@Injectable({ providedIn: 'root' })
-export class ShapeService {
-    constructor() {}
-
-    makeNewHyperlinkGroup(hyperlinkConfig: HyperlinkConfig) {
-        const group = this.makeGroup(true);
-        group.add(this.makeHyperlinkLabel(hyperlinkConfig));
-        return group;
-    }
-
-    makeHyperlinkLabel(hyperlinkConfig: HyperlinkConfig): Konva.Label {
-        const label = new Konva.Label({
-            x: 200,
-            y: 40,
-        });
-        label.add(this.makeHyperlinkText(hyperlinkConfig));
-        return label;
-    }
-
-    makeHyperlinkText(hyperlinkConfig: HyperlinkConfig): Konva.Text {
-        const settings: any = {
-            text: hyperlinkConfig.linkLabel,
-            width: 'auto',
-            height: 'auto',
-            hyperlink: hyperlinkConfig.linkHref,
-            newWindow: hyperlinkConfig.newWindow,
-            textDecoration: 'underline',
-            fill: '#62e497',
-            fontSize: hyperlinkConfig.labelFontSize,
-        };
-        return new Konva.Text(settings);
-    }
-
-    makeNewMeasurementShape(
-        visualizationConfig: SelectedVisualizationData,
-    ): Konva.Group {
-        const visualizationGroup = this.makeGroup(true);
-        visualizationGroup.add(this.makeLabelGroup(visualizationConfig));
-        visualizationGroup.add(this.makeMeasurementGroup(visualizationConfig));
-        return visualizationGroup;
-    }
-
-    makeLabelGroup(config: SelectedVisualizationData): Konva.Group {
-        const labelGroup = this.makeGroup(false);
-        labelGroup.add(
-            this.makeRect(config.labelBackgroundColor, 120, 40, 140, 20),
-        );
-        labelGroup.add(
-            this.makeText(
-                config,
-                config.label,
-                config.labelTextColor,
-                120,
-                45,
-                140,
-                20,
-                false,
-            ),
-        );
-        return labelGroup;
-    }
-
-    makeMeasurementGroup(config: SelectedVisualizationData): Konva.Group {
-        const measurementGroup = this.makeGroup(false);
-        measurementGroup.add(
-            this.makeRect(config.measurementBackgroundColor, 120, 60, 140, 40),
-        );
-        measurementGroup.add(
-            this.makeText(
-                config,
-                config.measurement,
-                config.measurementTextColor,
-                120,
-                65,
-                140,
-                40,
-                true,
-            ),
-        );
-        return measurementGroup;
-    }
-
-    makeGroup(draggable: boolean): Konva.Group {
-        return new Konva.Group({
-            x: 120,
-            y: 40,
-            draggable,
-        });
-    }
-
-    makeRect(
-        fillColor: string,
-        x: number,
-        y: number,
-        width: number,
-        height: number,
-    ): Konva.Rect {
-        return new Konva.Rect({
-            x,
-            y,
-            fill: fillColor,
-            width,
-            height,
-        });
-    }
-
-    makeText(
-        config: SelectedVisualizationData,
-        text: string,
-        textColor: string,
-        x: number,
-        y: number,
-        width: number | string,
-        height: number | string,
-        dynamicContent: boolean,
-    ): Konva.Text {
-        const textSettings: any = {
-            text,
-            x,
-            y,
-            width,
-            height,
-            fill: textColor,
-            align: 'center',
-            fontSize: '15',
-        };
-
-        if (dynamicContent) {
-            textSettings.name = 'dynamic-text';
-            textSettings.dataLakeMeasure = config.dataLakeMeasure;
-            textSettings.fontSize = '30';
-        }
-
-        return new Konva.Text(textSettings);
-    }
-}
diff --git a/ui/src/app/app-overview/app-overview.module.ts b/ui/src/app/app-overview/app-overview.module.ts
index eef43de838..a4601deb08 100644
--- a/ui/src/app/app-overview/app-overview.module.ts
+++ b/ui/src/app/app-overview/app-overview.module.ts
@@ -24,7 +24,6 @@ import { FormsModule } from '@angular/forms';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatGridListModule } from '@angular/material/grid-list';
 import { MatInputModule } from '@angular/material/input';
-import { AppAssetMonitoringModule } from '../app-asset-monitoring/app-asset-monitoring.module';
 import { AppOverviewComponent } from './app-overview.component';
 import { RouterModule } from '@angular/router';
 import { AvailableAppsService } from './apps';
@@ -34,7 +33,6 @@ import { MatButtonModule } from '@angular/material/button';
 
 @NgModule({
     imports: [
-        AppAssetMonitoringModule,
         CommonModule,
         FlexLayoutModule,
         FormsModule,
diff --git a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
index 0b6e90b72c..8588640560 100644
--- a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
+++ b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.html
@@ -49,7 +49,7 @@
             (matSortChange)="sortData($event)"
             class="table-widget"
         >
-            <ng-container [cdkColumnDef]="'time'">
+            <ng-container [matColumnDef]="'time'">
                 <div>
                     <th
                         mat-header-cell
@@ -81,7 +81,7 @@
                     let element of dataExplorerWidget.visualizationConfig
                         .selectedColumns
                 "
-                [cdkColumnDef]="element.fullDbName"
+                [matColumnDef]="element.fullDbName"
             >
                 <div *ngIf="!(element.fullDbName === 'time')">
                     <th
@@ -112,6 +112,32 @@
                     </td>
                 </div>
             </ng-container>
+            <ng-container
+                *ngFor="let element of groupByColumnNames"
+                [matColumnDef]="element"
+            >
+                <th
+                    mat-header-cell
+                    mat-sort-header
+                    *matHeaderCellDef
+                    [ngStyle]="{
+                        background:
+                            dataExplorerWidget.baseAppearanceConfig
+                                .backgroundColor,
+                        color: dataExplorerWidget.baseAppearanceConfig.textColor
+                    }"
+                >
+                    <label class="column-header">{{ element }}</label>
+                </th>
+                <td
+                    mat-cell
+                    *matCellDef="let row"
+                    [attr.data-cy]="'data-explorer-table-row-' + element"
+                    style="text-align: left"
+                >
+                    {{ row[element] }}
+                </td>
+            </ng-container>
 
             <tr
                 mat-header-row
diff --git a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
index 8cc42a7154..a156b11b14 100644
--- a/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/table/table-widget.component.ts
@@ -41,31 +41,56 @@ export class TableWidgetComponent
 
     dataSource = new MatTableDataSource();
     columnNames: string[];
+    groupByColumnNames: string[];
 
     ngOnInit(): void {
         super.ngOnInit();
         this.dataSource.sort = this.sort;
         this.dataSource.paginator = this.paginator;
+        this.regenerateColumnNames();
+    }
+
+    regenerateColumnNames(): void {
+        this.groupByColumnNames = this.makeGroupByColumns();
         this.columnNames = ['time'].concat(
             this.dataExplorerWidget.visualizationConfig.selectedColumns.map(
                 c => c.fullDbName,
             ),
+            ...this.groupByColumnNames,
         );
     }
 
+    makeGroupByColumns(): string[] {
+        return this.dataExplorerWidget.dataConfig.sourceConfigs.flatMap(sc => {
+            return sc.queryConfig.groupBy
+                .filter(g => g.selected)
+                .map(g => g.runtimeName);
+        });
+    }
+
     transformData(spQueryResult: SpQueryResult) {
         return spQueryResult.allDataSeries.flatMap(series =>
             series.rows.map(row =>
-                this.createTableObject(spQueryResult.headers, row),
+                this.createTableObject(spQueryResult.headers, row, series.tags),
             ),
         );
     }
 
-    createTableObject(keys, values) {
-        return keys.reduce((object, key, index) => {
+    createTableObject(
+        keys: string[],
+        values: any[],
+        tags: Record<string, string>,
+    ) {
+        const row = keys.reduce((object, key, index) => {
             object[key] = values[index];
             return object;
         }, {});
+        if (tags !== null) {
+            Object.keys(tags).forEach(key => {
+                row[key] = tags[key];
+            });
+        }
+        return row;
     }
 
     ngOnDestroy(): void {
@@ -116,11 +141,7 @@ export class TableWidgetComponent
     }
 
     onDataReceived(spQueryResults: SpQueryResult[]) {
-        this.columnNames = ['time'].concat(
-            this.dataExplorerWidget.visualizationConfig.selectedColumns.map(
-                c => c.fullDbName,
-            ),
-        );
+        this.regenerateColumnNames();
         const transformedData = spQueryResults
             .map(spQueryResult => this.transformData(spQueryResult))
             .flat();
@@ -148,10 +169,6 @@ export class TableWidgetComponent
     refreshColumns(): void {
         this.dataSource.filter =
             this.dataExplorerWidget.visualizationConfig.searchValue;
-        this.columnNames = ['time'].concat(
-            this.dataExplorerWidget.visualizationConfig.selectedColumns.map(
-                c => c.fullDbName,
-            ),
-        );
+        this.regenerateColumnNames();
     }
 }
diff --git a/ui/src/app/data-explorer/echarts-renderer/echarts-dataset-generator.service.ts b/ui/src/app/data-explorer/echarts-renderer/echarts-dataset-generator.service.ts
index 22debf01ee..ba64bb6a1b 100644
--- a/ui/src/app/data-explorer/echarts-renderer/echarts-dataset-generator.service.ts
+++ b/ui/src/app/data-explorer/echarts-renderer/echarts-dataset-generator.service.ts
@@ -19,6 +19,7 @@
 import { Injectable } from '@angular/core';
 import {
     DataExplorerWidgetModel,
+    DataSeries,
     SpQueryResult,
 } from '@streampipes/platform-services';
 import {
@@ -82,9 +83,15 @@ export class EchartsDatasetGeneratorService<T extends DataExplorerWidgetModel> {
             index: number,
         ) => DataTransformOption[],
     ): PreparedDataset {
-        const data = [
+        const headers = this.makeHeaders(
             queryResult.headers,
-            ...queryResult.allDataSeries.flatMap(series => series.rows),
+            queryResult.allDataSeries,
+        );
+        const data = [
+            headers,
+            ...queryResult.allDataSeries.flatMap(series => {
+                return this.makeRows(series.rows, series.tags);
+            }),
         ];
         const initialTransforms = getInitialTransforms(widgetConfig, index).map(
             transform => ({
@@ -112,7 +119,7 @@ export class EchartsDatasetGeneratorService<T extends DataExplorerWidgetModel> {
             sourceIndex: index,
             tagValues: tags,
             groupedDatasets: groupTransforms,
-            rawDataset: { source: data, dimensions: queryResult.headers },
+            rawDataset: { source: data, dimensions: headers },
             initialTransformDatasets: initialTransforms,
             meta: {
                 preparedDataStartIndex,
@@ -121,6 +128,27 @@ export class EchartsDatasetGeneratorService<T extends DataExplorerWidgetModel> {
         };
     }
 
+    private makeRows(rows: any[][], tags: Record<string, any>): any[][] {
+        const tagValues = tags !== null ? Object.values(tags) : [];
+        return rows.map(row => {
+            return [...row, ...tagValues];
+        });
+    }
+
+    private makeHeaders(
+        headers: string[],
+        allDataSeries: DataSeries[],
+    ): string[] {
+        let tagHeaders = [];
+        if (allDataSeries.length > 0) {
+            const tags = allDataSeries[0].tags;
+            if (tags !== null) {
+                tagHeaders = Object.keys(tags);
+            }
+        }
+        return [...headers, ...tagHeaders];
+    }
+
     increaseDatasetIndex(
         preparedDataset: PreparedDataset,
         currentDatasetIndex: number,


Test patch:
diff --git a/streampipes-data-explorer/src/test/java/org/apache/streampipes/dataexplorer/param/WhereStatementParamsTest.java b/streampipes-data-explorer/src/test/java/org/apache/streampipes/dataexplorer/param/WhereStatementParamsTest.java
index 52b5552d07..4a9a69dc55 100644
--- a/streampipes-data-explorer/src/test/java/org/apache/streampipes/dataexplorer/param/WhereStatementParamsTest.java
+++ b/streampipes-data-explorer/src/test/java/org/apache/streampipes/dataexplorer/param/WhereStatementParamsTest.java
@@ -50,6 +50,14 @@ public class WhereStatementParamsTest {
     assertWhereCondition(result, expected);
   }
 
+  @Test
+  public void filterString2() {
+    WhereClauseParams result = WhereClauseParams.from("[fieldName;=;3312476503F]");
+    FilterCondition expected = new FilterCondition("fieldName", "=", "3312476503F");
+
+    assertWhereCondition(result, expected);
+  }
+
   private void assertWhereCondition(WhereClauseParams result, FilterCondition expected) {
     assertEquals(1, result.getWhereConditions().size());
     FilterCondition resultingFilterCondition = result.getWhereConditions().get(0);
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/TestSizeMeasureProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/TestSizeMeasureProcessor.java
index eb168a7e56..7f2c182d21 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/TestSizeMeasureProcessor.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/sizemeasure/TestSizeMeasureProcessor.java
@@ -19,99 +19,75 @@
 package org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure;
 
 
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure.SizeMeasureProcessor.BYTES_OPTION;
+import static org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure.SizeMeasureProcessor.EVENT_SIZE;
+import static org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure.SizeMeasureProcessor.KILO_BYTES_OPTION;
+import static org.apache.streampipes.processors.enricher.jvm.processor.sizemeasure.SizeMeasureProcessor.SIZE_UNIT;
+
 public class TestSizeMeasureProcessor {
-//
-//  private static final Logger LOG = LoggerFactory.getLogger(TestSizeMeasureProcessor.class);
-//
-//  @org.junit.runners.Parameterized.Parameters
-//  public static Iterable<Object[]> data() {
-//
-//    /*
-//    249 bytes is the base size of an object when first tested.
-//    Allowing up to 250 bytes comparison error in case of inconsistent base sizes across platforms
-//     */
-//    return Arrays.asList(new Object[][]{
-//            { BYTE_SIZE, 10240 - 249, 10240.0, 250.0},
-//            { KILOBYTE_SIZE, 10240 - 249, 10.0, 0.025},
-//            { MEGABYTE_SIZE, (1024 * 1024) - 249, 1.0, 0.0025}
-//    });
-//  }
-//
-//  @Parameterized.Parameter
-//  public String sizeUnit;
-//
-//  @Parameterized.Parameter(1)
-//  public int numOfBytes;
-//
-//  @Parameterized.Parameter(2)
-//  public double expectedSize;
-//
-//  @Parameterized.Parameter(3)
-//  public double allowableError;
-//
-//  @Test
-//  public void testSizeMeasureProcessor() {
-//    SizeMeasureProcessor processor = new SizeMeasureProcessor();
-//    DataProcessorDescription originalGraph = processor.declareModel();
-//    originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-//    DataProcessorInvocation graph =
-//            InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-//
-//
-//    ProcessorParams params = new ProcessorParams(graph);
-//    params.extractor().getStaticPropertyByName(SIZE_UNIT, OneOfStaticProperty.class).getOptions()
-//            .stream().filter(ot -> ot.getInternalName().equals(sizeUnit)).findFirst()
-//            .get().setSelected(true);
-//
-//
-//    SpOutputCollector eventCollector = new StoreEventCollector();
-//
-//    processor.onInvocation(params, eventCollector, null);
-//
-//    LOG.info("Sending event with numOfBytes "
-//        + numOfBytes + ", sizeUnit: " + sizeUnit);
-//    double size = sendEvents(processor, eventCollector);
-//
-//    LOG.info("Expected size is {}", expectedSize);
-//    LOG.info("Actual size is {}", size);
-//    LOG.info("Allowable error is {}", allowableError);
-//    assertEquals(expectedSize, size, allowableError);
-//  }
-//
-//  private Double sendEvents(SizeMeasureProcessor processor, SpOutputCollector spOut) {
-//    double size = 0.0;
-//    Event event = makeEvent(numOfBytes);
-//
-//    processor.onEvent(event, spOut);
-//    try {
-//      Thread.sleep(100);
-//    } catch (InterruptedException e) {
-//      e.printStackTrace();
-//    }
-//    try {
-//      size = event.getFieldBySelector(SizeMeasureProcessor.EVENT_SIZE)
-//              .getAsPrimitive()
-//              .getAsDouble();
-//    } catch (IllegalArgumentException e) {
-//      e.printStackTrace();
-//    }
-//    return size;
-//  }
-//  private Event makeEvent(int numOfBytes) {
-//    Map<String, Object> map = new HashMap<>();
-//    map.put("Test", new ObjectWithSize(numOfBytes));
-//    return EventFactory.fromMap(map,
-//            new SourceInfo("test" + "-topic", "s0"),
-//            new SchemaInfo(null, new ArrayList<>()));
-//  }
-//
-//  public static class ObjectWithSize implements Serializable {
-//    private final byte[] data;
-//
-//    public ObjectWithSize(int numOfBytes) {
-//      this.data = new byte[numOfBytes];
-//    }
-//  }
+  private static final String KEY = "key";
+  private static final String VALUE = "value";
+
+  private static Map<String, Object> inputEvent = Map.of(KEY, VALUE);
+
+  private SizeMeasureProcessor processor;
+
+  @BeforeEach
+  public void setup() {
+    processor = new SizeMeasureProcessor();
+  }
+
+
+  static Stream<Arguments> arguments() {
+    return Stream.of(
+        Arguments.of(
+            BYTES_OPTION,
+            inputEvent,
+            96.0
+        ),
+        Arguments.of(
+            KILO_BYTES_OPTION,
+            inputEvent,
+            0.09375
+        )
+    );
+  }
+
+  @ParameterizedTest
+  @MethodSource("arguments")
+  public void testStringToState(
+      String sizeUnit,
+      Map<String, Object> intpuEvent,
+      double expectedventSize
+  ) {
+
+    var inputEvents = List.of(intpuEvent);
+    List<Map<String, Object>> outputEvents = List.of(Map.of(
+        KEY, VALUE,
+        EVENT_SIZE, expectedventSize
+    ));
+
+    var configuration = TestConfiguration
+        .builder()
+        .config(SIZE_UNIT, sizeUnit)
+        .prefixStrategy(PrefixStrategy.SAME_PREFIX)
+        .build();
+
+    var testExecutor = new ProcessingElementTestExecutor(processor, configuration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
 }
\ No newline at end of file
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/booloperator/inverter/TestBooleanInverterProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/booloperator/inverter/TestBooleanInverterProcessor.java
index f760cb2f77..8a54684097 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/booloperator/inverter/TestBooleanInverterProcessor.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/booloperator/inverter/TestBooleanInverterProcessor.java
@@ -18,112 +18,65 @@
 
 package org.apache.streampipes.processors.transformation.jvm.processor.booloperator.inverter;
 
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.StreamPrefix;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.streampipes.processors.transformation.jvm.processor.booloperator.inverter.BooleanInverterProcessor.INVERT_FIELD_ID;
+
 public class TestBooleanInverterProcessor {
-//
-//  private static final Logger LOG = LoggerFactory.getLogger(TestBooleanInverterProcessor.class);
-//
-//  @org.junit.runners.Parameterized.Parameters
-//  public static Iterable<Object[]> data() {
-//    return Arrays.asList(new Object[][]{
-//        {"Test", Arrays.asList(false, true), false},
-//        {"Test", Arrays.asList(false, true, false), true},
-//        {"Test", Arrays.asList(false), true},
-//        {"Test", Arrays.asList(false, true, false, false, true), false},
-//        {"Test", Arrays.asList(true, false), true},
-//        {"Test", Arrays.asList(true), false},
-//    });
-//  }
-//
-//  @org.junit.runners.Parameterized.Parameter
-//  public String invertFieldName;
-//
-//  @org.junit.runners.Parameterized.Parameter(1)
-//  public List<Boolean> eventBooleans;
-//
-//  @org.junit.runners.Parameterized.Parameter(2)
-//  public Boolean expectedBooleanCount;
-//
-//  @Test
-//  public void testBoolenInverter() {
-//    BooleanInverterProcessor bip = new BooleanInverterProcessor();
-//    DataProcessorDescription originalGraph =  bip.declareModel();
-//    originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-//    DataProcessorInvocation graph =
-//        InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-//
-//    graph.setInputStreams(Collections
-//        .singletonList(EventStreamGenerator
-//            .makeStreamWithProperties(Collections.singletonList(invertFieldName))));
-//
-//    graph.setOutputStream(EventStreamGenerator.makeStreamWithProperties(Collections.singletonList(invertFieldName)));
-//
-//    graph.getOutputStream().getEventGrounding().getTransportProtocol().getTopicDefinition()
-//        .setActualTopicName("output-topic");
-//
-//    graph.getStaticProperties().stream()
-//        .filter(p -> p instanceof MappingPropertyUnary)
-//        .map((p -> (MappingPropertyUnary) p))
-//        .filter(p -> p.getInternalName().equals(BooleanInverterProcessor.INVERT_FIELD_ID))
-//        .findFirst().get().setSelectedProperty("s0::" + invertFieldName);
-//    ProcessorParams params = new ProcessorParams(graph);
-//    SpOutputCollector spOut = new SpOutputCollector() {
-//        @Override
-//        public void collect(Event event) {}
-//
-//        @Override
-//        public void registerConsumer(String routeId, InternalEventProcessor<Map<String, Object>> consumer) {}
-//
-//        @Override
-//        public void unregisterConsumer(String routeId) {}
-//
-//        @Override
-//        public void connect() throws SpRuntimeException {}
-//
-//        @Override
-//        public void disconnect() throws SpRuntimeException {}
-//    };
-//
-//    bip.onInvocation(params, spOut, null);
-//
-//    boolean result = sendEvents(bip, spOut);
-//
-//    LOG.info("Expected boolean is {}", expectedBooleanCount);
-//    LOG.info("Actual boolean is {}", result);
-//    assertEquals(expectedBooleanCount, result);
-//  }
-//
-//  private boolean sendEvents(BooleanInverterProcessor trend, SpOutputCollector spOut) {
-//    boolean result = false;
-//    List<Event> events = makeEvents();
-//    for (Event event : events) {
-//      LOG.info("Sending event with value "
-//          + event.getFieldBySelector("s0::" + invertFieldName).getAsPrimitive().getAsBoolean());
-//      trend.onEvent(event, spOut);
-//      try {
-//        Thread.sleep(100);
-//      } catch (InterruptedException e) {
-//        e.printStackTrace();
-//      }
-//      result = event.getFieldBySelector("s0::" + invertFieldName).getAsPrimitive().getAsBoolean();
-//    }
-//
-//    return result;
-//  }
-//
-//  private List<Event> makeEvents() {
-//    List<Event> events = new ArrayList<>();
-//    for (Boolean eventSetting : eventBooleans) {
-//      events.add(makeEvent(eventSetting));
-//    }
-//    return events;
-//  }
-//
-//  private Event makeEvent(Boolean value) {
-//    Map<String, Object> map = new HashMap<>();
-//    map.put(invertFieldName, value);
-//    return EventFactory.fromMap(map, new SourceInfo("test" + "-topic", "s0"),
-//            new SchemaInfo(null, new ArrayList<>()));
-//  }
+  private static final String KEY_1 = "key1";
+
+  private BooleanInverterProcessor processor;
+
+  @BeforeEach
+  public void setup() {
+    processor = new BooleanInverterProcessor();
+  }
+
+  static Stream<Arguments> arguments() {
+    return Stream.of(
+        Arguments.of(
+            List.of(Map.of(KEY_1, true)),
+            List.of(Map.of(KEY_1, false))
+        ),
+        Arguments.of(
+            List.of(Map.of(KEY_1, false)),
+            List.of(Map.of(KEY_1, true))
+        ),
+        Arguments.of(
+            List.of(Map.of(KEY_1, true), Map.of(KEY_1, false), Map.of(KEY_1, true)),
+            List.of(Map.of(KEY_1, false), Map.of(KEY_1, true), Map.of(KEY_1, false))
+        )
+    );
+  }
+
+  @ParameterizedTest
+  @MethodSource("arguments")
+  public void testStringToState(
+      List<Map<String, Object>> intpuEvents,
+      List<Map<String, Object>> outputEvents
+  ) {
+
+    var configuration = TestConfiguration
+        .builder()
+        .config(INVERT_FIELD_ID, StreamPrefix.s0(KEY_1))
+        .prefixStrategy(PrefixStrategy.SAME_PREFIX)
+        .build();
+
+    var testExecutor = new ProcessingElementTestExecutor(processor, configuration);
+
+    testExecutor.run(intpuEvents, outputEvents);
+  }
+
 }
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/datetime/TestDateTimeFromStringProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/datetime/TestDateTimeFromStringProcessor.java
index cdfc2163df..00a8e78d5f 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/datetime/TestDateTimeFromStringProcessor.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/datetime/TestDateTimeFromStringProcessor.java
@@ -18,200 +18,70 @@
 
 package org.apache.streampipes.processors.transformation.jvm.processor.datetime;
 
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.StreamPrefix;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.streampipes.processors.transformation.jvm.processor.datetime.DateTimeFromStringProcessor.OUTPUT_TIMESTAMP_RUNTIME_NAME;
+import static org.apache.streampipes.processors.transformation.jvm.processor.datetime.DateTimeFromStringProcessor.OUTPUT_TIMEZONE_RUNTIME_NAME;
+
 public class TestDateTimeFromStringProcessor {
-//  private static final Logger LOG = LoggerFactory.getLogger(TestDateTimeFromStringProcessor.class);
-//
-//  @org.junit.runners.Parameterized.Parameters
-//  public static Iterable<Object[]> data() {
-//
-//    var expectedTimestamp = 1700222655537L;
-//
-//    return Arrays.asList(new Object[][]{
-//        // the first test just demonstrates that the testing and the source code is
-//        // functioning
-//        {
-//            "inputField", "US/Eastern",
-//            List.of("2020-11-13T21:07:38.146120+01:00", "2023-11-14T16:17:01.286299-05:00",
-//                    "2023-11-14T14:05:57.519543100"
-//            ),
-//            List.of(1605298058146L, 1699996621286L, 1699988757519L)
-//        },
-//        /*
-//         * the next three tests demonstrate two things: (1) if the DateTime string has
-//         * the zone information already in it, the user input on the timezone will not
-//         * affect the DateTime variable. (2) The same instant in the real world will
-//         * result in the same instant in the datetime variable
-//         */
-//        {
-//            "inputField", "US/Pacific", List.of("2023-11-17T04:04:15.537187600-08:00[US/Pacific]"),
-//            List.of(expectedTimestamp)
-//        },
-//        {
-//            "inputField", "US/Pacific", List.of("2023-11-17T05:04:15.537187600-07:00[US/Arizona]"),
-//            List.of(expectedTimestamp)
-//        },
-//        {
-//            "inputField", "US/Pacific", List.of("2023-11-17T07:04:15.537187600-05:00[US/Eastern]"),
-//            List.of(expectedTimestamp)
-//        },
-//        /*
-//         * The next three tests demonstrate that if a localdatetime is given, when the
-//         * user selects a time zone. An instant in time will be created for that
-//         * specific timezone.
-//         */
-//        {
-//            "inputField", "US/Pacific", List.of("2023-11-17T04:04:15.537187600"),
-//            List.of(expectedTimestamp)
-//        },
-//        {
-//            "inputField", "US/Arizona", List.of("2023-11-17T04:04:15.537187600"),
-//            List.of(1700219055537L)
-//        },
-//        {
-//            "inputField", "US/Eastern", List.of("2023-11-17T04:04:15.537187600"),
-//            List.of(1700211855537L)
-//        },
-//
-//        });
-//  }
-//
-//  @org.junit.runners.Parameterized.Parameter
-//  public String streamInputDateTimeFieldName;
-//
-//  @org.junit.runners.Parameterized.Parameter(1)
-//  public String selectedTimeZone;
-//
-//  @org.junit.runners.Parameterized.Parameter(2)
-//  public List<String> eventsString;
-//
-//  @org.junit.runners.Parameterized.Parameter(3)
-//  public List<String> expectedValues;
-//
-//  public static final String DEFAULT_STREAM_PREFIX = "Stream";
-//
-//  @Test
-//  public void testDateTime() {
-//    DateTimeFromStringProcessor dateTime = new DateTimeFromStringProcessor();
-//    DataProcessorDescription originalGraph = dateTime.declareModel();
-//    originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-//    DataProcessorInvocation graph = InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-//    graph.setInputStreams(Collections.singletonList(
-//        EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("in-stream"))));
-//    graph.setOutputStream(
-//        EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("out-stream")));
-//    graph.getOutputStream()
-//         .getEventGrounding()
-//         .getTransportProtocol()
-//         .getTopicDefinition()
-//         .setActualTopicName("output-topic");
-//
-//    MappingPropertyUnary mappingPropertyUnary = graph.getStaticProperties()
-//                                                     .stream()
-//                                                     .filter(p -> p instanceof MappingPropertyUnary)
-//                                                     .map(p -> (MappingPropertyUnary) p)
-//                                                     .filter(p -> DateTimeFromStringProcessor.FIELD_ID.equals(
-//                                                                 p.getInternalName()
-//                                                             )
-//                                                     )
-//                                                     .findFirst()
-//                                                     .orElse(null);
-//
-//    assert mappingPropertyUnary != null;
-//    mappingPropertyUnary.setSelectedProperty(DEFAULT_STREAM_PREFIX + "::" + streamInputDateTimeFieldName);
-//
-//    OneOfStaticProperty selectedTimeZoneProperty = graph.getStaticProperties()
-//                                                        .stream()
-//                                                        .filter(p -> p instanceof OneOfStaticProperty)
-//                                                        .map(p -> (OneOfStaticProperty) p)
-//                                                        .filter(p -> (
-//                                                            DateTimeFromStringProcessor.INPUT_TIMEZONE_KEY.equals(
-//                                                                p.getInternalName()
-//                                                            )
-//                                                        ))
-//                                                        .findFirst()
-//                                                        .orElse(null);
-//    assert selectedTimeZoneProperty != null;
-//    Option selectedTimeZoneOption = selectedTimeZoneProperty.getOptions()
-//                                                            .stream()
-//                                                            .filter(item -> item.getName()
-//                                                                                .equals(selectedTimeZone))
-//                                                            .findFirst()
-//                                                            .orElse(null);
-//    assert selectedTimeZoneOption != null;
-//    selectedTimeZoneOption.setSelected(true);
-//
-//    ProcessorParams params = new ProcessorParams(graph);
-//    SpOutputCollector spOut = new StoreEventCollector();
-//    dateTime.onInvocation(params, spOut, null);
-//    Tuple2<String, List<Long>> res = sendEvents(dateTime, spOut);
-//    List<Long> resValues = res.v;
-//    assert eventsString.size() == expectedValues.size();
-//    int size = eventsString.size();
-//    for (int i = 0; i < size; i++) {
-//      LOG.info("Expected value is {}.", expectedValues.get(i));
-//      LOG.info(
-//          "Actual value is {}.",
-//          resValues.get(i)
-//                   .toString()
-//      );
-//      assertEquals(
-//          expectedValues.get(i),
-//          resValues.get(i)
-//      );
-//    }
-//  }
-//
-//  private Tuple2<String, List<Long>> sendEvents(DateTimeFromStringProcessor dateTime, SpOutputCollector spOut) {
-//    String field = "";
-//    Long timestampValue = null;
-//    List<Event> events = makeEvents();
-//    List<Long> dateTimeValueList = new ArrayList<>();
-//    for (Event event : events) {
-//      LOG.info("sending event with value "
-//                   + event.getFieldBySelector(DEFAULT_STREAM_PREFIX + "::" + streamInputDateTimeFieldName)
-//                          .getAsPrimitive()
-//                          .getAsString());
-//      dateTime.onEvent(event, spOut);
-//
-//      try {
-//        TimeUnit.MILLISECONDS.sleep(100);
-//      } catch (InterruptedException e) {
-//        throw new RuntimeException(e);
-//      }
-//      try {
-//        field = event.getFieldBySelector(DEFAULT_STREAM_PREFIX + "::" + DateTimeFromStringProcessor.FIELD_ID)
-//                     .getAsPrimitive()
-//                     .getAsString();
-//        timestampValue = event
-//            .getFieldBySelector(DateTimeFromStringProcessor.OUTPUT_TIMESTAMP_RUNTIME_NAME)
-//            .getAsPrimitive()
-//            .getAsLong();
-//        LOG.info(field + ":" + timestampValue);
-//      } catch (IllegalArgumentException e) {
-//        throw new RuntimeException(e);
-//      }
-//      dateTimeValueList.add(timestampValue);
-//    }
-//    return new Tuple2<>(field, dateTimeValueList);
-//  }
-//
-//  private List<Event> makeEvents() {
-//    List<Event> events = new ArrayList<>();
-//    for (String eventString : eventsString) {
-//      events.add(makeEvent(eventString));
-//    }
-//    return events;
-//  }
-//
-//  private Event makeEvent(String value) {
-//    Map<String, Object> map = new HashMap<>();
-//    map.put(streamInputDateTimeFieldName, value);
-//    return EventFactory.fromMap(
-//        map,
-//        new SourceInfo("test-topic", DEFAULT_STREAM_PREFIX),
-//        new SchemaInfo(null, new ArrayList<>())
-//    );
-//  }
+
+  private static final String KEY_1 = "key1";
+  private static final String TIMEZONE = "US/Eastern";
+
+  private DateTimeFromStringProcessor processor;
+
+  @BeforeEach
+  public void setup() {
+    processor = new DateTimeFromStringProcessor();
+  }
+
+  private static final Map<String, Long> cases = Map.of(
+      "2020-11-13T21:07:38.146120+01:00", 1605298058146L,
+      "2023-11-14T16:17:01.286299-05:00", 1699996621286L,
+      "2023-11-14T14:05:57.519543100", 1699988757519L
+  );
+
+  static Stream<Arguments> arguments() {
+    return cases.entrySet().stream().map(entry -> {
+      Map<String, Object> inputEvent = Map.of(KEY_1, entry.getKey());
+      Map<String, Object> outputEvent = Map.of(
+          KEY_1, entry.getKey(),
+          OUTPUT_TIMEZONE_RUNTIME_NAME, TIMEZONE,
+          OUTPUT_TIMESTAMP_RUNTIME_NAME, entry.getValue()
+      );
+      return Arguments.of(List.of(inputEvent), List.of(outputEvent));
+    });
+  }
+
+  @ParameterizedTest
+  @MethodSource("arguments")
+  public void testStringToState(
+      List<Map<String, Object>> intpuEvents,
+      List<Map<String, Object>> outputEvents
+  ) {
+
+    var configuration = TestConfiguration
+        .builder()
+        .config(DateTimeFromStringProcessor.FIELD_ID, StreamPrefix.s0(KEY_1))
+        .config(DateTimeFromStringProcessor.INPUT_TIMEZONE_KEY, TIMEZONE)
+        .prefixStrategy(PrefixStrategy.SAME_PREFIX)
+        .build();
+
+    var testExecutor = new ProcessingElementTestExecutor(processor, configuration);
+
+    testExecutor.run(intpuEvents, outputEvents);
+  }
+
 }
diff --git a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/TestStringTimerProcessor.java b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/TestStringTimerProcessor.java
index 54f2017630..4f0ccc302e 100644
--- a/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/TestStringTimerProcessor.java
+++ b/streampipes-extensions/streampipes-processors-transformation-jvm/src/test/java/org/apache/streampipes/processors/transformation/jvm/processor/stringoperator/timer/TestStringTimerProcessor.java
@@ -18,163 +18,79 @@
 
 package org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer;
 
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.test.executors.Approx;
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.StreamPrefix;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.FIELD_ID;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.FIELD_VALUE_RUNTIME_NAME;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.MEASURED_TIME_FIELD_RUNTIME_NAME;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.MILLISECONDS;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.ON_INPUT_EVENT;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.OUTPUT_FREQUENCY;
+import static org.apache.streampipes.processors.transformation.jvm.processor.stringoperator.timer.StringTimerProcessor.OUTPUT_UNIT_ID;
+
 public class TestStringTimerProcessor {
-//
-//  private static final Logger LOG = LoggerFactory.getLogger(TestStringTimerProcessor.class);
-//
-//  @org.junit.runners.Parameterized.Parameters
-//  public static Iterable<Object[]> data() {
-//    return Arrays.asList(new Object[][] {
-//        {"select_field", "On Input Event", "Milliseconds", List.of(""), ""},
-//        {"select_field", "On Input Event", "Milliseconds", List.of("t1"), ""},
-//        {"select_field", "On Input Event", "Milliseconds", List.of("t1", "t1"), "t1"},
-//        {"select_field", "On Input Event", "Seconds", List.of("t1", "t1", "t2"), "t1"},
-//        {"select_field", "On Input Event", "Minutes", List.of("t1", "t2", "t3"), "t2"},
-//        {"select_field", "When String Value Changes", "Milliseconds", List.of(""), ""},
-//        {"select_field", "When String Value Changes", "Milliseconds", List.of("t1"), ""},
-//        {"select_field", "When String Value Changes", "Milliseconds", List.of("t1", "t2"), "t1"},
-//        {"select_field", "When String Value Changes", "Seconds", List.of("t1", "t1", "t2"), "t1"},
-//        {"select_field", "When String Value Changes", "Minutes", List.of("t1", "t2", "t3"), "t2"}
-//    });
-//  }
-//
-//  @org.junit.runners.Parameterized.Parameter
-//  public String selectedFieldName;
-//
-//  @org.junit.runners.Parameterized.Parameter(1)
-//  public String outputFrequency;
-//
-//  @org.junit.runners.Parameterized.Parameter(2)
-//  public String outputUnit;
-//
-//  @org.junit.runners.Parameterized.Parameter(3)
-//  public List<String> eventStrings;
-//
-//  @org.junit.runners.Parameterized.Parameter(4)
-//  public String expectedValue;
-//
-//  public static final String DEFAULT_STREAM_PREFIX = "stream";
-//
-//  @Test
-//  public void testStringTimer() {
-//    StringTimerProcessor stringTimer = new StringTimerProcessor();
-//    DataProcessorDescription originalGraph = stringTimer.declareModel();
-//    originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-//    DataProcessorInvocation graph = InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-//    graph.setInputStreams(Collections.singletonList(
-//        EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("in-stream"))));
-//    graph.setOutputStream(
-//        EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("out-stream")));
-//    graph.getOutputStream().getEventGrounding().getTransportProtocol().getTopicDefinition()
-//        .setActualTopicName("output-topic");
-//
-//    MappingPropertyUnary mappingPropertyUnary = graph.getStaticProperties().stream()
-//        .filter(p -> p instanceof MappingPropertyUnary)
-//        .map(p -> (MappingPropertyUnary) p)
-//        .filter(p -> (StringTimerProcessor.FIELD_ID).equals(p.getInternalName()))
-//        .findFirst().orElse(null);
-//
-//    assert mappingPropertyUnary != null;
-//    mappingPropertyUnary.setSelectedProperty(DEFAULT_STREAM_PREFIX + "::" + selectedFieldName);
-//
-//    OneOfStaticProperty outputFrequencyStaticProperty = graph.getStaticProperties().stream()
-//        .filter(p -> p instanceof OneOfStaticProperty)
-//        .map(p -> (OneOfStaticProperty) p)
-//        .filter(p -> (StringTimerProcessor.OUTPUT_FREQUENCY.equals(p.getInternalName())))
-//        .findFirst().orElse(null);
-//    assert outputFrequencyStaticProperty != null;
-//    Option outputFrequencyOption = outputFrequencyStaticProperty.getOptions().stream()
-//        .filter(item -> item.getName().equals(outputFrequency))
-//        .findFirst().orElse(null);
-//    assert  outputFrequencyOption != null;
-//    outputFrequencyOption.setSelected(true);
-//
-//    OneOfStaticProperty outputUnitStaticProperty = graph.getStaticProperties().stream()
-//        .filter(p -> p instanceof OneOfStaticProperty)
-//        .map(p -> (OneOfStaticProperty) p)
-//        .filter(p -> (StringTimerProcessor.OUTPUT_UNIT_ID.equals(p.getInternalName())))
-//        .findFirst().orElse(null);
-//    assert  outputUnitStaticProperty != null;
-//    Option outputUnitOption = outputUnitStaticProperty.getOptions().stream()
-//        .filter(item -> item.getName().equals(outputUnit))
-//        .findFirst().orElse(null);
-//    assert outputUnitOption != null;
-//    outputUnitOption.setSelected(true);
-//
-//    ProcessorParams params = new ProcessorParams(graph);
-//
-//    SpOutputCollector spOut = new SpOutputCollector() {
-//      @Override
-//      public void registerConsumer(String routeId, InternalEventProcessor<Map<String, Object>> consumer) {
-//      }
-//
-//      @Override
-//      public void unregisterConsumer(String routeId) {
-//      }
-//
-//      @Override
-//      public void connect() throws SpRuntimeException {
-//      }
-//
-//      @Override
-//      public void disconnect() throws SpRuntimeException {
-//      }
-//
-//      @Override
-//      public void collect(Event event) {
-//      }
-//    };
-//    stringTimer.onInvocation(params, spOut, null);
-//    Tuple2<String, Double> res = sendEvents(stringTimer, spOut);
-//    LOG.info("Expected value is {}.", expectedValue);
-//    LOG.info("Actual value is {}.", res.k);
-//    assertEquals(expectedValue, res.k);
-//  }
-//
-//  private Tuple2<String, Double> sendEvents(StringTimerProcessor stringTimer, SpOutputCollector spOut) {
-//    String field = "";
-//    double timeDiff = 0.0;
-//    List<Event> events = makeEvents();
-//    for (Event event : events) {
-//      LOG.info("Sending event with value "
-//          + event.getFieldBySelector(DEFAULT_STREAM_PREFIX + "::"
-//          + selectedFieldName).getAsPrimitive().getAsString());
-//      stringTimer.onEvent(event, spOut);
-//      try {
-//        TimeUnit.MILLISECONDS.sleep(100);
-//      } catch (InterruptedException e) {
-//        throw new RuntimeException(e);
-//      }
-//      try {
-//        field = event.getFieldBySelector(StringTimerProcessor.FIELD_VALUE_RUNTIME_NAME)
-//            .getAsPrimitive()
-//            .getAsString();
-//        timeDiff = event.getFieldBySelector(StringTimerProcessor.MEASURED_TIME_FIELD_RUNTIME_NAME)
-//            .getAsPrimitive()
-//                .getAsDouble();
-//        LOG.info(field + " time: " + timeDiff);
-//      } catch (IllegalArgumentException e) {
-//
-//      }
-//    }
-//    return new Tuple2<>(field, timeDiff);
-//  }
-//
-//  private List<Event> makeEvents() {
-//    List<Event> events = Lists.newArrayList();
-//    for (String eventString : eventStrings) {
-//      events.add(makeEvent(eventString));
-//    }
-//    return events;
-//  }
-//  private Event makeEvent(String value) {
-//    Map<String, Object> map = Maps.newHashMap();
-//    map.put(selectedFieldName, value);
-//    return EventFactory.fromMap(map,
-//        new SourceInfo("test-topic", DEFAULT_STREAM_PREFIX),
-//        new SchemaInfo(null, Lists.newArrayList())
-//    );
-//  }
+  private static final String KEY_1 = "key1";
+  private static final String VALUE_1 = "v1";
+  private static final String VALUE_2 = "v2";
+
+  private StringTimerProcessor processor;
+
+  @BeforeEach
+  public void setup() {
+    processor = new StringTimerProcessor();
+  }
+
+  static Stream<Arguments> arguments() {
+    return Stream.of(
+        Arguments.of(
+            List.of(Map.of(KEY_1, VALUE_1), Map.of(KEY_1, VALUE_1), Map.of(KEY_1, VALUE_2)),
+            List.of(
+                Map.of(
+                    FIELD_VALUE_RUNTIME_NAME, VALUE_1,
+                    MEASURED_TIME_FIELD_RUNTIME_NAME, new Approx(0.0, 2.0),
+                    KEY_1, VALUE_1
+                ),
+                Map.of(
+                    FIELD_VALUE_RUNTIME_NAME, VALUE_1,
+                    MEASURED_TIME_FIELD_RUNTIME_NAME,  new Approx(1.0, 2.0),
+                    KEY_1, VALUE_2
+                )
+            )
+        )
+    );
+  }
+
+  @ParameterizedTest
+  @MethodSource("arguments")
+  public void testStringToState(
+      List<Map<String, Object>> intpuEvents,
+      List<Map<String, Object>> outputEvents
+  ) {
+
+    var configuration = TestConfiguration
+        .builder()
+        .config(OUTPUT_FREQUENCY, ON_INPUT_EVENT)
+        .config(OUTPUT_UNIT_ID, MILLISECONDS)
+        .config(FIELD_ID, StreamPrefix.s0(KEY_1))
+        .prefixStrategy(PrefixStrategy.SAME_PREFIX)
+        .build();
+
+    var testExecutor = new ProcessingElementTestExecutor(processor, configuration);
+
+    testExecutor.run(intpuEvents, outputEvents);
+  }
+
 }
diff --git a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
index b27f0e887a..2dbe384d13 100644
--- a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
+++ b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
@@ -32,7 +32,6 @@ import org.apache.streampipes.model.template.PipelineElementTemplateConfig;
 import org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
 import org.apache.streampipes.test.generator.EventStreamGenerator;
 
-import org.junit.jupiter.api.Assertions;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -44,6 +43,7 @@ import java.util.Map;
 import java.util.function.Consumer;
 import java.util.stream.IntStream;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -51,32 +51,28 @@ import static org.mockito.Mockito.when;
 public class ProcessingElementTestExecutor {
 
   private final IStreamPipesDataProcessor processor;
-  private TestConfiguration testConfiguration;
+  private final TestConfiguration testConfiguration;
   private Iterator<String> selectorPrefixes;
   private Consumer<DataProcessorInvocation> invocationConfig;
 
-  public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor, TestConfiguration testConfiguration,
-                                       Consumer<DataProcessorInvocation> invocationConfig) {
+  public ProcessingElementTestExecutor(
+      IStreamPipesDataProcessor processor, TestConfiguration testConfiguration,
+      Consumer<DataProcessorInvocation> invocationConfig
+  ) {
     this.processor = processor;
     this.testConfiguration = testConfiguration;
-    this.selectorPrefixes = testConfiguration.getPrefixes().iterator();
+    this.selectorPrefixes = testConfiguration.getPrefixes()
+                                             .iterator();
     this.invocationConfig = invocationConfig;
   }
 
   public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor, TestConfiguration testConfiguration) {
     this.processor = processor;
     this.testConfiguration = testConfiguration;
-    this.selectorPrefixes = testConfiguration.getPrefixes().iterator();
-  }
-
-  public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor,
-                                       Consumer<DataProcessorInvocation> invocationConfig) {
-    this.processor = processor;
-    this.invocationConfig = invocationConfig;
-    this.selectorPrefixes = List.of("").iterator();
+    this.selectorPrefixes = testConfiguration.getPrefixes()
+                                             .iterator();
   }
 
-
   /**
    * This method is used to run a data processor with a given configuration and a list of input events.
    * It then verifies the output events against the expected output events.
@@ -92,7 +88,7 @@ public class ProcessingElementTestExecutor {
 
     // initialize the extractor with the provided configuration of the user input
     var dataProcessorInvocation = getProcessorInvocation();
-    if (invocationConfig != null){
+    if (invocationConfig != null) {
       invocationConfig.accept(dataProcessorInvocation);
     }
 
@@ -116,11 +112,14 @@ public class ProcessingElementTestExecutor {
     }
 
     // Validate the output of the processor
-    Mockito.verify(mockCollector,
-        Mockito.times(expectedOutputEvents.size())).collect(spOutputCollectorCaptor.capture());
+    Mockito.verify(
+               mockCollector,
+               Mockito.times(expectedOutputEvents.size())
+           )
+           .collect(spOutputCollectorCaptor.capture());
     var resultingEvents = spOutputCollectorCaptor.getAllValues();
     IntStream.range(0, expectedOutputEvents.size())
-             .forEach(i -> Assertions.assertEquals(
+             .forEach(i -> assertEventEquality(
                  expectedOutputEvents.get(i),
                  resultingEvents.get(i)
                                 .getRaw()
@@ -130,6 +129,37 @@ public class ProcessingElementTestExecutor {
     processor.onPipelineStopped();
   }
 
+  /**
+   * Asserts the equality of expected and actual event.
+   * Iterates through each key-value pair in the expected map and compares the value
+   * with the corresponding value in the actual map.
+   *
+   * @param expected The expected event
+   * @param actual   The actual event
+   */
+  private void assertEventEquality(Map<String, Object> expected, Map<String, Object> actual) {
+    expected.forEach((key, value) -> {
+      if (value instanceof Approx roundValue) {
+        assertEquals(
+            roundValue.value(),
+            (Double) actual.get(key),
+            roundValue.epsilon(),
+            () -> getAssertionErrorMessage(key, expected, actual));
+      } else {
+        assertEquals(
+            value,
+            actual.get(key),
+            () -> getAssertionErrorMessage(key, expected, actual)
+        );
+      }
+
+    });
+  }
+
+  private String getAssertionErrorMessage(String key, Map<String, Object> expected, Map<String, Object> actual) {
+    return "Assertion failed for key: %s. Expected: %s, Actual: %s".formatted(key, expected, actual);
+  }
+
   private static ProcessingElementParameterExtractor getProcessingElementParameterExtractor(
       DataProcessorInvocation dataProcessorInvocation
   ) {
@@ -166,7 +196,8 @@ public class ProcessingElementTestExecutor {
     var configs = new HashMap<String, PipelineElementTemplateConfig>();
 
     staticProperties.forEach(staticProperty -> {
-      var value = testConfiguration.getFieldConfiguration().get(staticProperty.getInternalName());
+      var value = testConfiguration.getFieldConfiguration()
+                                   .get(staticProperty.getInternalName());
       configs.put(
           staticProperty.getInternalName(),
           new PipelineElementTemplateConfig(true, true, value)
@@ -178,8 +209,9 @@ public class ProcessingElementTestExecutor {
 
   private Event getEvent(Map<String, Object> rawEvent) {
 
-    if (!selectorPrefixes.hasNext()){
-      selectorPrefixes = testConfiguration.getPrefixes().iterator();
+    if (!selectorPrefixes.hasNext()) {
+      selectorPrefixes = testConfiguration.getPrefixes()
+                                          .iterator();
     }
 
     String selectorPrefix = selectorPrefixes.next();
diff --git a/ui/src/app/app-asset-monitoring/model/test-data.json b/ui/src/app/app-asset-monitoring/model/test-data.json
deleted file mode 100644
index 4c2d5ed6d9..0000000000
--- a/ui/src/app/app-asset-monitoring/model/test-data.json
+++ /dev/null
@@ -1,126 +0,0 @@
-{
-  "attrs": {
-    "width": 1200,
-    "height": 900
-  },
-  "className": "Stage",
-  "children": [
-    {
-      "attrs": {},
-      "className": "Layer",
-      "children": [
-        {
-          "attrs": {
-            "x": -372,
-            "y": -316,
-            "draggable": true
-          },
-          "className": "Image"
-        },
-        {
-          "attrs": {
-            "anchorStroke": "red",
-            "anchorFill": "yellow",
-            "anchorSize": 20,
-            "borderStroke": "green",
-            "borderDash": [3, 3]
-          },
-          "className": "Transformer"
-        }
-      ]
-    },
-    {
-      "attrs": {},
-      "className": "Layer",
-      "children": [
-        {
-          "attrs": {
-            "x": -495.3078833627492,
-            "y": -165.10262778758306,
-            "draggable": true,
-            "pipelineId": "123",
-            "scaleX": 3.5637828473447883,
-            "scaleY": 3.5637828473447883
-          },
-          "className": "Group",
-          "children": [
-            {
-              "attrs": {
-                "x": 120,
-                "y": 40,
-                "pipelineId": "123"
-              },
-              "className": "Group",
-              "children": [
-                {
-                  "attrs": {
-                    "x": 120,
-                    "y": 40,
-                    "fill": "#FFFFFF",
-                    "width": 120,
-                    "height": 30,
-                    "id": "hi-id"
-                  },
-                  "className": "Rect"
-                },
-                {
-                  "attrs": {
-                    "x": 120,
-                    "y": 40,
-                    "width": 120,
-                    "height": 30,
-                    "fill": "#000000",
-                    "id": "my-text"
-                  },
-                  "className": "Text"
-                }
-              ]
-            },
-            {
-              "attrs": {
-                "x": 120,
-                "y": 40,
-                "pipelineId": "123"
-              },
-              "className": "Group",
-              "children": [
-                {
-                  "attrs": {
-                    "x": 120,
-                    "y": 70,
-                    "fill": "#FFFFFF",
-                    "width": 80,
-                    "height": 15,
-                    "id": "hi-id"
-                  },
-                  "className": "Rect"
-                },
-                {
-                  "attrs": {
-                    "text": "randomString",
-                    "x": 120,
-                    "y": 70,
-                    "width": 80,
-                    "height": 15,
-                    "fill": "#000000",
-                    "id": "my-text"
-                  },
-                  "className": "Text"
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "attrs": {
-            "anchorStroke": "red",
-            "anchorFill": "yellow",
-            "borderStroke": "green",
-            "borderDash": [3, 3]
-          },
-          "className": "Transformer"
-        }
-      ]
-    }
-  ]
-}