Repository: apache/streampipes
Pull request #3318 (2024-10-31 02:22:39)

chore(deps): bump actions/cache from 2 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 2 to 4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/actions/cache/releases">actions/cache's releases</a>.</em></p>
<blockquote>
<h2>v4.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update action to node20 by <a href="https://github.com/takost"><code>@​takost</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1284">actions/cache#1284</a></li>
<li>feat: save-always flag by <a href="https://github.com/to-s"><code>@​to-s</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1242">actions/cache#1242</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/takost"><code>@​takost</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1284">actions/cache#1284</a></li>
<li><a href="https://github.com/to-s"><code>@​to-s</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1242">actions/cache#1242</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v3...v4.0.0">https://github.com/actions/cache/compare/v3...v4.0.0</a></p>
<h2>v3.3.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Cache v3.3.3 by <a href="https://github.com/robherley"><code>@​robherley</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1302">actions/cache#1302</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/robherley"><code>@​robherley</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1302">actions/cache#1302</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v3...v3.3.3">https://github.com/actions/cache/compare/v3...v3.3.3</a></p>
<h2>v3.3.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fixed readme with new segment timeout values by <a href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1133">actions/cache#1133</a></li>
<li>Readme fixes by <a href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1134">actions/cache#1134</a></li>
<li>Updated description of the lookup-only input for main action by <a href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1130">actions/cache#1130</a></li>
<li>Change two new actions mention as quoted text by <a href="https://github.com/bishal-pdMSFT"><code>@​bishal-pdMSFT</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1131">actions/cache#1131</a></li>
<li>Update Cross-OS Caching tips by <a href="https://github.com/pdotl"><code>@​pdotl</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1122">actions/cache#1122</a></li>
<li>Bazel example (Take <a href="https://redirect.github.com/actions/cache/issues/2">#2</a>️⃣) by <a href="https://github.com/vorburger"><code>@​vorburger</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1132">actions/cache#1132</a></li>
<li>Remove actions to add new PRs and issues to a project board by <a href="https://github.com/jorendorff"><code>@​jorendorff</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1187">actions/cache#1187</a></li>
<li>Consume latest toolkit and fix dangling promise bug by <a href="https://github.com/chkimes"><code>@​chkimes</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1217">actions/cache#1217</a></li>
<li>Bump action version to 3.3.2 by <a href="https://github.com/bethanyj28"><code>@​bethanyj28</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1236">actions/cache#1236</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/vorburger"><code>@​vorburger</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1132">actions/cache#1132</a></li>
<li><a href="https://github.com/jorendorff"><code>@​jorendorff</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1187">actions/cache#1187</a></li>
<li><a href="https://github.com/chkimes"><code>@​chkimes</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1217">actions/cache#1217</a></li>
<li><a href="https://github.com/bethanyj28"><code>@​bethanyj28</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1236">actions/cache#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v3...v3.3.2">https://github.com/actions/cache/compare/v3...v3.3.2</a></p>
<h2>v3.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Reduced download segment size to 128 MB and timeout to 10 minutes by <a href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1129">actions/cache#1129</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v3...v3.3.1">https://github.com/actions/cache/compare/v3...v3.3.1</a></p>
<h2>v3.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bug: Permission is missing in cache delete example by <a href="https://github.com/kotokaze"><code>@​kotokaze</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1123">actions/cache#1123</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/actions/cache/blob/main/RELEASES.md">actions/cache's changelog</a>.</em></p>
<blockquote>
<h1>Releases</h1>
<h3>4.1.2</h3>
<ul>
<li>Add GitHub Enterprise Cloud instances hostname filters to inform API endpoint choices - <a href="https://redirect.github.com/actions/cache/pull/1474">#1474</a></li>
<li>Security fix: Bump braces from 3.0.2 to 3.0.3 - <a href="https://redirect.github.com/actions/cache/pull/1475">#1475</a></li>
</ul>
<h3>4.1.1</h3>
<ul>
<li>Restore original behavior of <code>cache-hit</code> output - <a href="https://redirect.github.com/actions/cache/pull/1467">#1467</a></li>
</ul>
<h3>4.1.0</h3>
<ul>
<li>Ensure <code>cache-hit</code> output is set when a cache is missed - <a href="https://redirect.github.com/actions/cache/pull/1404">#1404</a></li>
<li>Deprecate <code>save-always</code> input - <a href="https://redirect.github.com/actions/cache/pull/1452">#1452</a></li>
</ul>
<h3>4.0.2</h3>
<ul>
<li>Fixed restore <code>fail-on-cache-miss</code> not working.</li>
</ul>
<h3>4.0.1</h3>
<ul>
<li>Updated <code>isGhes</code> check</li>
</ul>
<h3>4.0.0</h3>
<ul>
<li>Updated minimum runner version support from node 12 -&gt; node 20</li>
</ul>
<h3>3.3.3</h3>
<ul>
<li>Updates <code>@​actions/cache</code> to v3.2.3 to fix accidental mutated path arguments to <code>getCacheVersion</code> <a href="https://redirect.github.com/actions/toolkit/pull/1378">actions/toolkit#1378</a></li>
<li>Additional audit fixes of npm package(s)</li>
</ul>
<h3>3.3.2</h3>
<ul>
<li>Fixes bug with Azure SDK causing blob downloads to get stuck.</li>
</ul>
<h3>3.3.1</h3>
<ul>
<li>Reduced segment size to 128MB and segment timeout to 10 minutes to fail fast in case the cache download is stuck.</li>
</ul>
<h3>3.3.0</h3>
<ul>
<li>Added option to lookup cache without downloading it.</li>
</ul>
<h3>3.2.6</h3>
<ul>
<li>Fix zstd not being used after zstd version upgrade to 1.5.4 on hosted runners.</li>
</ul>
<h3>3.2.5</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/actions/cache/commit/6849a6489940f00c2f30c0fb92c6274307ccb58a"><code>6849a64</code></a> Release 4.1.2 <a href="https://redirect.github.com/actions/cache/issues/1477">#1477</a></li>
<li><a href="https://github.com/actions/cache/commit/5a1720c49e91718f5d0ce7f154997c93e0f6159a"><code>5a1720c</code></a> Merge branch 'Link-/prep-4.1.2' of <a href="https://github.com/actions/cache">https://github.com/actions/cache</a> into Link...</li>
<li><a href="https://github.com/actions/cache/commit/d9fef48d24d529bac46adcc1e42f49649de07ca9"><code>d9fef48</code></a> Merge branch 'main' into Link-/prep-4.1.2</li>
<li><a href="https://github.com/actions/cache/commit/a50e8d027b022a55ef85ffa721ebd97d2b22bcda"><code>a50e8d0</code></a> Merge branch 'main' into Link-/prep-4.1.2</li>
<li><a href="https://github.com/actions/cache/commit/acc9ae5c1401b6c072a7c89ff4c48ea7e30f4dbf"><code>acc9ae5</code></a> Merge pull request <a href="https://redirect.github.com/actions/cache/issues/1481">#1481</a> from actions/dependabot/github_actions/actions/setup...</li>
<li><a href="https://github.com/actions/cache/commit/1ea5f18c31265ef251b3eb51ce8b857be5e7b044"><code>1ea5f18</code></a> Merge branch 'main' into Link-/prep-4.1.2</li>
<li><a href="https://github.com/actions/cache/commit/cc679ff3baee71867c711040a5c21af61b262806"><code>cc679ff</code></a> Merge branch 'main' into dependabot/github_actions/actions/setup-node-4</li>
<li><a href="https://github.com/actions/cache/commit/366d43d6f8aa1f3e5d28b2c98959d557d78ffa3f"><code>366d43d</code></a> Merge pull request <a href="https://redirect.github.com/actions/cache/issues/1483">#1483</a> from actions/dependabot/github_actions/github/codeql...</li>
<li><a href="https://github.com/actions/cache/commit/02bf31969bcc471fd5f91b5896ae17beb0973413"><code>02bf319</code></a> Bump github/codeql-action from 2 to 3</li>
<li><a href="https://github.com/actions/cache/commit/6f6220be5af96ba6940aca960265218cae17e8fd"><code>6f6220b</code></a> Merge branch 'main' into dependabot/github_actions/actions/setup-node-4</li>
<li>Additional commits viewable in <a href="https://github.com/actions/cache/compare/v2...v4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/cache&package-manager=github_actions&previous-version=2&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.idea/runConfigurations/all_extensions_jvm.xml b/.idea/runConfigurations/all_extensions_jvm.xml
deleted file mode 100644
index 103f85d7e1..0000000000
--- a/.idea/runConfigurations/all_extensions_jvm.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="all-extensions-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_COUCHDB_HOST" value="localhost" />
-      <env name="SP_DATA_LAKE_HOST" value="localhost" />
-      <env name="SP_DATA_LAKE_PORT" value="8086" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_IMAGE_STORAGE_LOCATION" value=".streampipes/spImages/" />
-      <env name="SP_JMS_HOST" value="localhost" />
-      <env name="SP_JMS_PORT" value="61616" />
-      <env name="SP_PORT" value="7023" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.extensions.all.jvm.AllExtensionsInit" />
-    <module name="streampipes-extensions-all-jvm" />
-    <shortenClasspath name="MANIFEST" />
-    <extension name="net.ashald.envfile">
-      <option name="IS_ENABLED" value="false" />
-      <option name="IS_SUBST" value="false" />
-      <option name="IS_PATH_MACRO_SUPPORTED" value="false" />
-      <option name="IS_IGNORE_MISSING_FILES" value="false" />
-      <option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
-      <ENTRIES>
-        <ENTRY IS_ENABLED="true" PARSER="runconfig" />
-      </ENTRIES>
-    </extension>
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/all_pipeline_elements_flink.xml b/.idea/runConfigurations/all_pipeline_elements_flink.xml
deleted file mode 100644
index 5675eac01d..0000000000
--- a/.idea/runConfigurations/all_pipeline_elements_flink.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="all-pipeline-elements-flink" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="8005" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_FLINK_DEBUG" value="true" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.pe.flink.AllFlinkPipelineElementsInit" />
-    <module name="streampipes-pipeline-elements-experimental-flink" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/all_pipeline_elements_jvm.xml b/.idea/runConfigurations/all_pipeline_elements_jvm.xml
deleted file mode 100644
index 60c64ead6a..0000000000
--- a/.idea/runConfigurations/all_pipeline_elements_jvm.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="all-pipeline-elements-jvm" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="7023" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_COUCHDB_HOST" value="localhost" />
-      <env name="SP_JMS_HOST" value="localhost" />
-      <env name="SP_JMS_PORT" value="61616" />
-      <env name="SP_DATA_LAKE_HOST" value="localhost" />
-      <env name="SP_DATA_LAKE_PORT" value="8086" />
-      <env name="SP_BACKEND_HOST" value="localhost" />
-      <env name="SP_BACKEND_PORT" value="8030" />
-      <env name="SP_IMAGE_STORAGE_LOCATION" value=".streampipes/spImages/" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.pe.jvm.AllPipelineElementsInit" />
-    <module name="streampipes-pipeline-elements-all-jvm" />
-    <extension name="net.ashald.envfile">
-      <option name="IS_ENABLED" value="false" />
-      <option name="IS_SUBST" value="false" />
-      <option name="IS_PATH_MACRO_SUPPORTED" value="false" />
-      <option name="IS_IGNORE_MISSING_FILES" value="false" />
-      <option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
-      <ENTRIES>
-        <ENTRY IS_ENABLED="true" PARSER="runconfig" />
-      </ENTRIES>
-    </extension>
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/connect_adapters.xml b/.idea/runConfigurations/connect_adapters.xml
deleted file mode 100644
index 7f920ddd31..0000000000
--- a/.idea/runConfigurations/connect_adapters.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="connect-adapters" type="Application" factoryName="Application">
-    <envs>
-      <env name="SP_PORT" value="8001" />
-      <env name="SP_DATA_LOCATION" value="./test_data/" />
-      <env name="SP_DEBUG" value="true" />
-      <env name="SP_DEBUG_CONNECT" value="false" />
-    </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.connect.ConnectAdapterInit" />
-    <module name="streampipes-connect-adapters" />
-    <method v="2">
-      <option name="Make" enabled="true" />
-    </method>
-  </configuration>
-</component>
diff --git a/.idea/runConfigurations/connect_adapters_iiot.xml b/.idea/runConfigurations/connect_adapters_iiot.xml
deleted file mode 100644
index ace168629a..0000000000
--- a/.idea/runConfigurations/connect_adapters_iiot.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-    <configuration default="false" name="connect-adapters-iiot" type="Application" factoryName="Application">
-        <envs>
-            <env name="SP_PORT" value="8002" />
-            <env name="SP_DATA_LOCATION" value="./test_data/" />
-            <env name="SP_DEBUG" value="true" />
-            <env name="SP_DEBUG_CONNECT" value="false" />
-        </envs>
-        <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.connect.iiot.ConnectAdapterIiotInit" />
-        <module name="streampipes-connect-adapters-iiot" />
-        <method v="2">
-            <option name="Make" enabled="true" />
-        </method>
-    </configuration>
-</component>
diff --git a/.idea/runConfigurations/core.xml b/.idea/runConfigurations/sp_core.xml
similarity index 85%
rename from .idea/runConfigurations/core.xml
rename to .idea/runConfigurations/sp_core.xml
index 77258ea6bb..d05d151b77 100644
--- a/.idea/runConfigurations/core.xml
+++ b/.idea/runConfigurations/sp_core.xml
@@ -1,5 +1,5 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="core" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
+  <configuration default="false" name="sp_core" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
     <envs>
       <env name="SP_BACKEND_HOST" value="localhost" />
       <env name="SP_COUCHDB_HOST" value="localhost" />
diff --git a/.idea/runConfigurations/sinks_internal_jvm.xml b/.idea/runConfigurations/sp_extensions.xml
similarity index 62%
rename from .idea/runConfigurations/sinks_internal_jvm.xml
rename to .idea/runConfigurations/sp_extensions.xml
index 0a5d75aca8..1100b2a8f0 100644
--- a/.idea/runConfigurations/sinks_internal_jvm.xml
+++ b/.idea/runConfigurations/sp_extensions.xml
@@ -1,21 +1,20 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="sinks-internal-jvm" type="Application" factoryName="Application">
+  <configuration default="false" name="sp_extensions" type="Application" factoryName="Application">
     <envs>
-      <env name="SP_PORT" value="7020" />
-      <env name="SP_DEBUG" value="true" />
       <env name="SP_COUCHDB_HOST" value="localhost" />
-      <env name="SP_JMS_HOST" value="localhost" />
-      <env name="SP_JMS_PORT" value="61616" />
       <env name="SP_DATA_LAKE_HOST" value="localhost" />
       <env name="SP_DATA_LAKE_PORT" value="8086" />
-      <env name="SP_BACKEND_HOST" value="localhost" />
-      <env name="SP_BACKEND_PORT" value="8030" />
+      <env name="SP_DEBUG" value="true" />
       <env name="SP_IMAGE_STORAGE_LOCATION" value=".streampipes/spImages/" />
+      <env name="SP_JMS_HOST" value="localhost" />
+      <env name="SP_JMS_PORT" value="61616" />
+      <env name="SP_PORT" value="7023" />
     </envs>
-    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.sinks.internal.jvm.SinksInternalJvmInit" />
-    <module name="streampipes-sinks-internal-jvm" />
+    <option name="MAIN_CLASS_NAME" value="org.apache.streampipes.extensions.all.jvm.AllExtensionsInit" />
+    <module name="streampipes-extensions-all-jvm" />
+    <shortenClasspath name="MANIFEST" />
     <method v="2">
       <option name="Make" enabled="true" />
     </method>
   </configuration>
-</component>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/sp_extensions_iiot.xml b/.idea/runConfigurations/sp_extensions_iiot.xml
new file mode 100644
index 0000000000..b3dd30bc4d
--- /dev/null
+++ b/.idea/runConfigurations/sp_extensions_iiot.xml
@@ -0,0 +1,20 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="sp_extensions_iiot" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
+    <envs>
+      <env name="SP_BACKEND_HOST" value="localhost" />
+      <env name="SP_COUCHDB_HOST" value="localhost" />
+      <env name="SP_DEBUG" value="true" />
+      <env name="SP_INFLUX_HOST" value="localhost" />
+      <env name="SP_INFLUX_PORT" value="8086" />
+      <env name="SP_JMS_HOST" value="localhost" />
+      <env name="SP_KAFKA_HOST" value="localhost" />
+      <env name="SP_KAFKA_PORT" value="9094" />
+      <env name="SP_PRIORITIZED_PROTOCOL" value="kafka" />
+    </envs>
+    <module name="streampipes-extensions-all-iiot" />
+    <option name="SPRING_BOOT_MAIN_CLASS" value="org.apache.streampipes.extensions.all.iiot.AllExtensionsIIoTInit" />
+    <method v="2">
+      <option name="Make" enabled="true" />
+    </method>
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/.idea/runConfigurations/ui.xml b/.idea/runConfigurations/ui.xml
deleted file mode 100644
index b2d00f6ceb..0000000000
--- a/.idea/runConfigurations/ui.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="ui" type="js.build_tools.npm">
-    <package-json value="$PROJECT_DIR$/ui/package.json" />
-    <command value="start" />
-    <node-interpreter value="project" />
-    <envs />
-    <method v="2" />
-  </configuration>
-</component>
\ No newline at end of file
diff --git a/streampipes-client-go/docs/content/en/docs/getting-started/first-steps.md b/streampipes-client-go/docs/content/en/docs/getting-started/first-steps.md
index 2d28e4391f..b4cf2ca010 100644
--- a/streampipes-client-go/docs/content/en/docs/getting-started/first-steps.md
+++ b/streampipes-client-go/docs/content/en/docs/getting-started/first-steps.md
@@ -52,9 +52,9 @@ Once these requirements are met, you are ready to proceed with the next step Qui
 
 The StreamPipes Go library is meant to work with Go 1.21 and above. You can install the latest development version from GitHub, as so:
 
-```bash
+```shell
 go get https://github.com/apache/streampipes
 // if you want to have the current development state you can also execute
 go get https://github.com/apache/streampipes/streampipes-client-go
 // the corresponding documentation can be found here: https://streampipes.apache.org/docs/docs/python/dev/
-```
\ No newline at end of file
+```
diff --git a/streampipes-client-go/docs/content/en/docs/tutorials/ManageAdapter.md b/streampipes-client-go/docs/content/en/docs/tutorials/ManageAdapter.md
index 059700c2c6..cc11a0a286 100644
--- a/streampipes-client-go/docs/content/en/docs/tutorials/ManageAdapter.md
+++ b/streampipes-client-go/docs/content/en/docs/tutorials/ManageAdapter.md
@@ -1,3 +1,8 @@
+---
+title: Manage Adapter
+description: >
+  Manage Adapter.
+---
 <!--
   // Licensed to the Apache Software Foundation (ASF) under one or more
   // contributor license agreements.  See the NOTICE file distributed with
@@ -16,10 +21,10 @@
   //
   -->
 
-###  Manage StreamPipes Adapter
+#  Manage StreamPipes Adapter
 ---
 ## Initialize Go-Client
-```bash
+```go
 import (
 	"log"
 	"github.com/apache/streampipes/streampipes-client-go/streampipes"
@@ -33,7 +38,7 @@ func main() {
                 ApiKey:   "<Your-API-Key>",
             },
         }
-    
+
       streamPipesClient, err := streampipes.NewStreamPipesClient(clientConfig)
       if err != nil {
           log.Fatal(err)
@@ -44,29 +49,29 @@ func main() {
 
 ### Create a StreamPipes Adapter
 
-```bash
+```go
       // Populating go-model as a data source is not supported at this time,This is because the inheritance of the model has not been resolved for the time being.
       adapterData = `json`
-      adapter = []byte(adapterData) 
-	  err := streamPipesClient.Adapter().CreateAdapter(adapterData) 
+      adapter = []byte(adapterData)
+	  err := streamPipesClient.Adapter().CreateAdapter(adapterData)
 ```
 
 ### Get a StreamPipes Adapter
 
-```bash
+```go
 	streampipesAdapter, err := streamPipesClient.Adapter().GetSingleAdapter("adapterId")
 ```
 
 ### Start a StreamPipes Adapter
 
-```bash
+```go
 	err := streamPipesClient.Adapter().StartSingleAdapter("adapterId")
 ```
 
 ### Stop a StreamPipes Adapter
 
-```bash
+```go
 	err := streamPipesClient.Adapter().StopSingleAdapter("adapterId")
 ```
 
-### ... 
\ No newline at end of file
+### ...
diff --git a/streampipes-client-go/docs/content/en/docs/tutorials/ManagePipeline.md b/streampipes-client-go/docs/content/en/docs/tutorials/ManagePipeline.md
index 39bf323ecd..7807471ee9 100644
--- a/streampipes-client-go/docs/content/en/docs/tutorials/ManagePipeline.md
+++ b/streampipes-client-go/docs/content/en/docs/tutorials/ManagePipeline.md
@@ -1,3 +1,8 @@
+---
+title: Manage Pipeline
+description: >
+  Manage Pipeline.
+---
 <!--
   // Licensed to the Apache Software Foundation (ASF) under one or more
   // contributor license agreements.  See the NOTICE file distributed with
@@ -16,10 +21,10 @@
   //
   -->
 
-###  Manage StreamPipes Pipeline
+#  Manage StreamPipes Pipeline
 ---
 ## Initialize Go-Client
-```bash
+```go
 import (
 	"log"
 	"github.com/apache/streampipes/streampipes-client-go/streampipes"
@@ -33,7 +38,7 @@ func main() {
                 ApiKey:   "<Your-API-Key>",
             },
         }
-    
+
       streamPipesClient, err := streampipes.NewStreamPipesClient(clientConfig)
       if err != nil {
           log.Fatal(err)
@@ -44,29 +49,29 @@ func main() {
 
 ### Create a StreamPipes Pipeline
 
-```bash
+```go
       // Populating go-model as a data source is not supported at this time,This is because the inheritance of the model has not been resolved for the time being.
       pipelineData = `json`
-      pipeline = []byte(pipelineData) 
+      pipeline = []byte(pipelineData)
 	  responseMsg,err := streamPipesClient.Pipeline().CreatePipeline(pipelineData)
 ```
 
 ### Get a StreamPipes Pipeline
 
-```bash
+```go
 	streampipesPipeline, err := streamPipesClient.Pipeline().GetSinglePipelineStatus("pipelineId")
 ```
 
 ### Start a StreamPipes Pipeline
 
-```bash
+```go
 	operationStatus, err := streamPipesClient.Pipeline().StartSinglePipeline("pipelineId")
 ```
 
 ### Stop a StreamPipes Pipeline
 
-```bash
+```go
 	operationStatus, err := streamPipesClient.Pipeline().StopSinglePipeline("pipelineId")
 ```
 
-### ... 
\ No newline at end of file
+### ...
diff --git a/streampipes-client-python/poetry.lock b/streampipes-client-python/poetry.lock
index 904c11ed1b..c83e3dc6c2 100644
--- a/streampipes-client-python/poetry.lock
+++ b/streampipes-client-python/poetry.lock
@@ -1567,13 +1567,13 @@ mkdocs = ">=1.0.3"
 
 [[package]]
 name = "mkdocs-git-revision-date-localized-plugin"
-version = "1.2.6"
+version = "1.3.0"
 description = "Mkdocs plugin that enables displaying the localized date of the last git modification of a markdown file."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mkdocs_git_revision_date_localized_plugin-1.2.6-py3-none-any.whl", hash = "sha256:f015cb0f3894a39b33447b18e270ae391c4e25275cac5a626e80b243784e2692"},
-    {file = "mkdocs_git_revision_date_localized_plugin-1.2.6.tar.gz", hash = "sha256:e432942ce4ee8aa9b9f4493e993dee9d2cc08b3ea2b40a3d6b03ca0f2a4bcaa2"},
+    {file = "mkdocs_git_revision_date_localized_plugin-1.3.0-py3-none-any.whl", hash = "sha256:c99377ee119372d57a9e47cff4e68f04cce634a74831c06bc89b33e456e840a1"},
+    {file = "mkdocs_git_revision_date_localized_plugin-1.3.0.tar.gz", hash = "sha256:439e2f14582204050a664c258861c325064d97cdc848c541e48bb034a6c4d0cb"},
 ]
 
 [package.dependencies]
@@ -1582,6 +1582,11 @@ GitPython = "*"
 mkdocs = ">=1.0"
 pytz = "*"
 
+[package.extras]
+all = ["GitPython", "babel (>=2.7.0)", "click", "codecov", "mkdocs (>=1.0)", "mkdocs-gen-files", "mkdocs-git-authors-plugin", "mkdocs-material", "mkdocs-static-i18n", "pytest", "pytest-cov", "pytz"]
+base = ["GitPython", "babel (>=2.7.0)", "mkdocs (>=1.0)", "pytz"]
+dev = ["click", "codecov", "mkdocs-gen-files", "mkdocs-git-authors-plugin", "mkdocs-material", "mkdocs-static-i18n", "pytest", "pytest-cov"]
+
 [[package]]
 name = "mkdocs-jupyter"
 version = "0.24.0"
@@ -3879,4 +3884,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 = "c39c290ccabf05074d2589eb1015783a4ad1d501cb3e14a77d1776b63c576129"
+content-hash = "722f4fc3251b31c4742e93fceed39f1a56223f092d1fd86a15536c662932bc0a"
diff --git a/streampipes-client-python/pyproject.toml b/streampipes-client-python/pyproject.toml
index 108fd4daa4..01c32ca758 100644
--- a/streampipes-client-python/pyproject.toml
+++ b/streampipes-client-python/pyproject.toml
@@ -86,7 +86,7 @@ mike = { git = "https://github.com/jimporter/mike.git", rev = "872f72def32f58890
 mkdocs = "1.5.2"
 mkdocs-awesome-pages-plugin = "2.9.0"
 mkdocs-gen-files = "0.5.0"
-mkdocs-git-revision-date-localized-plugin = "1.2.6"
+mkdocs-git-revision-date-localized-plugin = "1.3.0"
 mkdocs-jupyter = "0.24.0"
 mkdocs-literate-nav = "0.6.0"
 mkdocs-material = "9.3.2"
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
index dd0afb7ef7..8b53e019f6 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/PersistPipelineHandler.java
@@ -94,6 +94,7 @@ public class PersistPipelineHandler {
         DATA_LAKE_CONNECTOR_ID,
         adapterDescription.getCorrespondingDataStreamElementId(),
         null,
+        null,
         null
     ));
     return pipelineElements;
diff --git a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/AdapterMasterManagement.java b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/AdapterMasterManagement.java
index 62c514b1e6..5c42478431 100644
--- a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/AdapterMasterManagement.java
+++ b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/AdapterMasterManagement.java
@@ -53,10 +53,11 @@ public class AdapterMasterManagement {
 
   private final DataStreamResourceManager dataStreamResourceManager;
 
-  public AdapterMasterManagement(IAdapterStorage adapterInstanceStorage,
-                                 AdapterResourceManager adapterResourceManager,
-                                 DataStreamResourceManager dataStreamResourceManager,
-                                 AdapterMetrics adapterMetrics
+  public AdapterMasterManagement(
+      IAdapterStorage adapterInstanceStorage,
+      AdapterResourceManager adapterResourceManager,
+      DataStreamResourceManager dataStreamResourceManager,
+      AdapterMetrics adapterMetrics
   ) {
     this.adapterInstanceStorage = adapterInstanceStorage;
     this.adapterMetrics = adapterMetrics;
@@ -64,28 +65,40 @@ public class AdapterMasterManagement {
     this.dataStreamResourceManager = dataStreamResourceManager;
   }
 
-  public void addAdapter(AdapterDescription ad,
-                           String adapterElementId,
-                           String principalSid)
+  public void addAdapter(
+      AdapterDescription adapterDescription,
+      String adapterId,
+      String principalSid
+  )
       throws AdapterException {
 
-    // Create elementId for adapter
+    // Create elementId for datastream
     var dataStreamElementId = ElementIdGenerator.makeElementId(SpDataStream.class);
-    ad.setElementId(adapterElementId);
-    ad.setCreatedAt(System.currentTimeMillis());
-    ad.setCorrespondingDataStreamElementId(dataStreamElementId);
+    adapterDescription.setElementId(adapterId);
+    adapterDescription.setCreatedAt(System.currentTimeMillis());
+    adapterDescription.setCorrespondingDataStreamElementId(dataStreamElementId);
 
     // Add EventGrounding to AdapterDescription
     var eventGrounding = GroundingUtils.createEventGrounding();
-    ad.setEventGrounding(eventGrounding);
+    adapterDescription.setEventGrounding(eventGrounding);
 
-    this.adapterResourceManager.encryptAndCreate(ad);
+    this.adapterResourceManager.encryptAndCreate(adapterDescription);
 
-    // Create stream
-    var storedDescription = new SourcesManagement().createAdapterDataStream(ad, dataStreamElementId);
-    storedDescription.setCorrespondingAdapterId(adapterElementId);
+    // Stream is only created if the adpater is successfully stored
+    createDataStreamForAdapter(adapterDescription, adapterId, dataStreamElementId, principalSid);
+  }
+
+  private void createDataStreamForAdapter(
+      AdapterDescription adapterDescription,
+      String adapterId,
+      String streamId,
+      String principalSid
+  ) throws AdapterException {
+    var storedDescription = new SourcesManagement()
+        .createAdapterDataStream(adapterDescription, streamId);
+    storedDescription.setCorrespondingAdapterId(adapterId);
     installDataSource(storedDescription, principalSid, true);
-    LOG.info("Install source (source URL: {} in backend", ad.getElementId());
+    LOG.info("Install source (source URL: {} in backend", adapterDescription.getElementId());
   }
 
   public AdapterDescription getAdapter(String elementId) throws AdapterException {
@@ -163,7 +176,8 @@ public class AdapterMasterManagement {
       var baseUrl = new ExtensionsServiceEndpointGenerator().getEndpointBaseUrl(
           ad.getAppId(),
           SpServiceUrlProvider.ADAPTER,
-          ad.getDeploymentConfiguration().getDesiredServiceTags()
+          ad.getDeploymentConfiguration()
+            .getDesiredServiceTags()
       );
 
       // Update selected endpoint URL of adapter
@@ -182,9 +196,11 @@ public class AdapterMasterManagement {
     }
   }
 
-  private void installDataSource(SpDataStream stream,
-                                 String principalSid,
-                                 boolean publicElement) throws AdapterException {
+  private void installDataSource(
+      SpDataStream stream,
+      String principalSid,
+      boolean publicElement
+  ) throws AdapterException {
     try {
       new DataStreamVerifier(stream).verifyAndAdd(principalSid, publicElement);
     } catch (SepaParseException e) {
diff --git a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataLakeMeasurementCounterInflux.java b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataLakeMeasurementCounterInflux.java
index db11222324..0a58b8b29a 100644
--- a/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataLakeMeasurementCounterInflux.java
+++ b/streampipes-data-explorer-influx/src/main/java/org/apache/streampipes/dataexplorer/influx/DataLakeMeasurementCounterInflux.java
@@ -22,16 +22,23 @@ import org.apache.streampipes.dataexplorer.query.DataLakeMeasurementCounter;
 import org.apache.streampipes.model.datalake.AggregationFunction;
 import org.apache.streampipes.model.datalake.DataLakeMeasure;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 
 public class DataLakeMeasurementCounterInflux extends DataLakeMeasurementCounter {
 
+  private static final Logger LOG = LoggerFactory.getLogger(DataLakeMeasurementCounterInflux.class);
+
   private static final String COUNT_FIELD = "count";
 
-  public DataLakeMeasurementCounterInflux(List<DataLakeMeasure> allMeasurements,
-                                          List<String> measurementNames) {
+  public DataLakeMeasurementCounterInflux(
+      List<DataLakeMeasure> allMeasurements,
+      List<String> measurementNames
+  ) {
     super(allMeasurements, measurementNames);
   }
 
@@ -39,15 +46,21 @@ public class DataLakeMeasurementCounterInflux extends DataLakeMeasurementCounter
   protected CompletableFuture<Integer> createQueryAsAsyncFuture(DataLakeMeasure measure) {
     return CompletableFuture.supplyAsync(() -> {
       var firstColumn = getFirstMeasurementProperty(measure);
+      if (firstColumn == null) {
+        LOG.error(
+            "Could not count events in measurement: {}, because no measurement property was found in event schema",
+            measure.getMeasureName()
+        );
+        return 0;
+      }
+
       var builder = DataLakeInfluxQueryBuilder
-          .create(measure.getMeasureName()).withEndTime(System.currentTimeMillis())
+          .create(measure.getMeasureName())
+          .withEndTime(System.currentTimeMillis())
           .withAggregatedColumn(firstColumn, AggregationFunction.COUNT);
       var queryResult = new DataExplorerInfluxQueryExecutor().executeQuery(builder.build(), Optional.empty(), true);
-      if (queryResult.getTotal() > 0) {
-        return extractResult(queryResult, COUNT_FIELD);
-      } else {
-        return 0;
-      }
+
+      return queryResult.getTotal() > 0 ? extractResult(queryResult, COUNT_FIELD) : 0;
     });
   }
 }
diff --git a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DataLakeMeasurementCounter.java b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DataLakeMeasurementCounter.java
index 844ce5b573..bc3a551ed7 100644
--- a/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DataLakeMeasurementCounter.java
+++ b/streampipes-data-explorer/src/main/java/org/apache/streampipes/dataexplorer/query/DataLakeMeasurementCounter.java
@@ -42,8 +42,10 @@ public abstract class DataLakeMeasurementCounter implements IDataLakeMeasurement
   protected final List<DataLakeMeasure> allMeasurements;
   protected final List<String> measurementNames;
 
-  public DataLakeMeasurementCounter(List<DataLakeMeasure> allMeasurements,
-                                         List<String> measurementNames) {
+  public DataLakeMeasurementCounter(
+      List<DataLakeMeasure> allMeasurements,
+      List<String> measurementNames
+  ) {
     this.allMeasurements = allMeasurements;
     this.measurementNames = measurementNames;
   }
@@ -52,12 +54,14 @@ public abstract class DataLakeMeasurementCounter implements IDataLakeMeasurement
   public Map<String, Integer> countMeasurementSizes() {
 
     // create async futures so that count queries can be executed parallel
-    Map<String, CompletableFuture<Integer>> countQueriesFutures = measurementNames.stream()
+    Map<String, CompletableFuture<Integer>> countQueriesFutures = measurementNames
+        .stream()
         .map(this::getMeasure)
         .filter(Objects::nonNull)
         .collect(Collectors.toMap(
-            DataLakeMeasure::getMeasureName,
-            this::createQueryAsAsyncFuture)
+                     DataLakeMeasure::getMeasureName,
+                     this::createQueryAsAsyncFuture
+                 )
         );
 
     return getQueryResults(countQueriesFutures);
@@ -72,7 +76,8 @@ public abstract class DataLakeMeasurementCounter implements IDataLakeMeasurement
   private DataLakeMeasure getMeasure(String measureName) {
     return allMeasurements
         .stream()
-        .filter(m -> m.getMeasureName().equals(measureName))
+        .filter(m -> m.getMeasureName()
+                      .equals(measureName))
         .findFirst()
         .orElse(null);
   }
@@ -83,7 +88,7 @@ public abstract class DataLakeMeasurementCounter implements IDataLakeMeasurement
    * @param queryFutures A Map containing the futures of
    *                     asynchronous count queries mapped by their respective keys.
    * @return A Map representing the results of the queries, where each key corresponds to
-   *         a measure name and the value is the count result.
+   * a measure name and the value is the count result.
    */
   private Map<String, Integer> getQueryResults(Map<String, CompletableFuture<Integer>> queryFutures) {
     Map<String, Integer> resultPerMeasure = new HashMap<>();
@@ -106,18 +111,34 @@ public abstract class DataLakeMeasurementCounter implements IDataLakeMeasurement
    * @return The runtime name of the first measurement property, or null if no such property is found.
    */
   protected String getFirstMeasurementProperty(DataLakeMeasure measure) {
-    return measure.getEventSchema().getEventProperties()
+    var propertyRuntimeName = measure
+        .getEventSchema()
+        .getEventProperties()
         .stream()
         .filter(ep -> ep.getPropertyScope() != null
-            && ep.getPropertyScope().equals(PropertyScope.MEASUREMENT_PROPERTY.name()))
+            && ep.getPropertyScope()
+                 .equals(PropertyScope.MEASUREMENT_PROPERTY.name()))
         .map(EventProperty::getRuntimeName)
         .findFirst()
         .orElse(null);
+
+    if (propertyRuntimeName == null) {
+      LOG.error("No measurement property was found in the event schema found for measure {}", measure.getMeasureName());
+    }
+
+    return propertyRuntimeName;
   }
 
   protected Integer extractResult(SpQueryResult queryResult, String fieldName) {
-    return ((Double) (
-        queryResult.getAllDataSeries().get(0).getRows().get(0).get(queryResult.getHeaders().indexOf(fieldName)))
+    return (
+        (Double) (
+            queryResult.getAllDataSeries()
+                       .get(0)
+                       .getRows()
+                       .get(0)
+                       .get(queryResult.getHeaders()
+                                       .indexOf(fieldName))
+        )
     ).intValue();
   }
 
diff --git a/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/adapter/generic/config/MetadataOptionGenerator.java b/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/adapter/generic/config/MetadataOptionGenerator.java
index 8efe5bda0c..8ef93dee6f 100644
--- a/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/adapter/generic/config/MetadataOptionGenerator.java
+++ b/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/adapter/generic/config/MetadataOptionGenerator.java
@@ -68,19 +68,23 @@ public class MetadataOptionGenerator {
   }
 
   private static StaticProperty getRuntimeResolvableGroup(String labelId) {
-    return StaticProperties.runtimeResolvableGroupStaticProperty(
+    var group = StaticProperties.runtimeResolvableGroupStaticProperty(
         Labels.withId(labelId),
         List.of(Plc4xLabels.SUPPORTED_TRANSPORTS)
     );
+    group.setHorizontalRendering(false);
+    return group;
   }
 
   private StaticProperty getGroup(List<Option> options,
                                   String labelId) {
-    return StaticProperties.group(
+    var group = StaticProperties.group(
         Labels.withId(labelId),
         false,
         getOptions(options)
     );
+    group.setHorizontalRendering(false);
+    return group;
   }
 
   public StaticProperty[] getOptions(List<Option> options) {
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java
index 7a2409d1b2..0571496f6b 100644
--- a/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/main/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessor.java
@@ -47,10 +47,10 @@ import org.apache.streampipes.wrapper.standalone.StreamPipesDataProcessor;
 
 public class MathOpProcessor extends StreamPipesDataProcessor {
 
-  private static final String RESULT_FIELD = "calculationResult";
-  private static final String LEFT_OPERAND = "leftOperand";
-  private static final String RIGHT_OPERAND = "rightOperand";
-  private static final String OPERATION = "operation";
+  protected static final String RESULT_FIELD = "calculationResult";
+  protected static final String LEFT_OPERAND = "leftOperand";
+  protected static final String RIGHT_OPERAND = "rightOperand";
+  protected static final String OPERATION = "operation";
 
   Operation arithmeticOperation = null;
   String leftOperand;
diff --git a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
index 17ed2b9c87..aaa444db3e 100644
--- a/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
+++ b/streampipes-extensions/streampipes-sinks-internal-jvm/src/main/java/org/apache/streampipes/sinks/internal/jvm/datalake/DataLakeDimensionProvider.java
@@ -55,10 +55,13 @@ public class DataLakeDimensionProvider {
   private void addFieldIfNotExists(EventPropertyPrimitive field,
                                    List<Option> options) {
     if (options.stream().noneMatch(o -> o.getName().equals(field.getRuntimeName()))) {
-      options.add(new Option(
-          field.getRuntimeName(),
-          PropertyScope.valueOf(field.getPropertyScope()) == PropertyScope.DIMENSION_PROPERTY)
-      );
+      if (field.getPropertyScope() != null) {
+        options.add(new Option(
+                field.getRuntimeName(),
+                PropertyScope.valueOf(field.getPropertyScope()) == PropertyScope.DIMENSION_PROPERTY
+            )
+        );
+      }
     }
   }
 
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notifications.java b/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notifications.java
index 4e14af9262..965a84257d 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notifications.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/message/Notifications.java
@@ -44,8 +44,12 @@ public class Notifications {
     return new ErrorMessage(new Notification(type.name(), type.description()));
   }
 
+  public static ErrorMessage error(String message, String description) {
+    return new ErrorMessage(new Notification(message, description));
+  }
+
   public static ErrorMessage error(String message) {
-    return new ErrorMessage(new Notification(message, ""));
+    return error(message, "");
   }
 
   public static ErrorMessage error(NotificationType type, String info) {
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/AppendOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/AppendOutputStrategy.java
index 9d22313bc4..fa7ccca3c4 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/AppendOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/AppendOutputStrategy.java
@@ -26,8 +26,6 @@ import java.util.List;
 
 public class AppendOutputStrategy extends OutputStrategy {
 
-  private static final long serialVersionUID = 7202888911899551012L;
-
   private List<EventProperty> eventProperties;
 
   public AppendOutputStrategy() {
@@ -35,6 +33,11 @@ public class AppendOutputStrategy extends OutputStrategy {
     eventProperties = new ArrayList<>();
   }
 
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
+
   public AppendOutputStrategy(AppendOutputStrategy other) {
     super(other);
     this.setEventProperties(new Cloner().properties(other.getEventProperties()));
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomOutputStrategy.java
index 4468ba14f2..fa859aeef4 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomOutputStrategy.java
@@ -23,8 +23,6 @@ import java.util.List;
 
 public class CustomOutputStrategy extends OutputStrategy {
 
-  private static final long serialVersionUID = -5858193127308435472L;
-
   private List<String> selectedPropertyKeys;
 
   private boolean outputRight;
@@ -77,4 +75,9 @@ public class CustomOutputStrategy extends OutputStrategy {
   public void setAvailablePropertyKeys(List<String> availablePropertyKeys) {
     this.availablePropertyKeys = availablePropertyKeys;
   }
+
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomTransformOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomTransformOutputStrategy.java
index 91d1a6ae3d..426a8d29eb 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomTransformOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/CustomTransformOutputStrategy.java
@@ -32,7 +32,6 @@ public class CustomTransformOutputStrategy extends OutputStrategy {
     this.eventProperties = new ArrayList<>();
   }
 
-
   public CustomTransformOutputStrategy(CustomTransformOutputStrategy other) {
     super(other);
     this.eventProperties = new Cloner().properties(other.getEventProperties());
@@ -45,4 +44,9 @@ public class CustomTransformOutputStrategy extends OutputStrategy {
   public void setEventProperties(List<EventProperty> eventProperties) {
     this.eventProperties = eventProperties;
   }
+
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/FixedOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/FixedOutputStrategy.java
index e698348efd..1558aada49 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/FixedOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/FixedOutputStrategy.java
@@ -50,5 +50,9 @@ public class FixedOutputStrategy extends OutputStrategy {
     this.eventProperties = eventProperties;
   }
 
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/KeepOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/KeepOutputStrategy.java
index d455e7b4c2..0c8b9b0e00 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/KeepOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/KeepOutputStrategy.java
@@ -63,4 +63,9 @@ public class KeepOutputStrategy extends OutputStrategy {
   public void setKeepBoth(boolean keepBoth) {
     this.keepBoth = keepBoth;
   }
+
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/ListOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/ListOutputStrategy.java
index 4040d9387c..b2e1f4ba51 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/ListOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/ListOutputStrategy.java
@@ -46,5 +46,9 @@ public class ListOutputStrategy extends OutputStrategy {
     this.propertyName = propertyName;
   }
 
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategy.java
index 05484f1679..ab19a8d89b 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategy.java
@@ -75,4 +75,6 @@ public abstract class OutputStrategy {
   public void setRenameRules(List<PropertyRenameRule> renameRules) {
     this.renameRules = renameRules;
   }
+
+  public abstract void accept(OutputStrategyVisitor visitor);
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategyVisitor.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategyVisitor.java
new file mode 100644
index 0000000000..024e22b994
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/OutputStrategyVisitor.java
@@ -0,0 +1,38 @@
+/*
+ * 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.output;
+
+public interface OutputStrategyVisitor {
+
+  void visit(AppendOutputStrategy appendOutputStrategy);
+
+  void visit(CustomOutputStrategy customOutputStrategy);
+
+  void visit(CustomTransformOutputStrategy customTransformOutputStrategy);
+
+  void visit(FixedOutputStrategy fixedOutputStrategy);
+
+  void visit(KeepOutputStrategy keepOutputStrategy);
+
+  void visit(ListOutputStrategy listOutputStrategy);
+
+  void visit(TransformOutputStrategy transformOutputStrategy);
+
+  void visit(UserDefinedOutputStrategy userDefinedOutputStrategy);
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/TransformOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/TransformOutputStrategy.java
index 1ca951654b..7e9de992ad 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/TransformOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/TransformOutputStrategy.java
@@ -43,4 +43,9 @@ public class TransformOutputStrategy extends OutputStrategy {
   public void setTransformOperations(List<TransformOperation> transformOperations) {
     this.transformOperations = transformOperations;
   }
+
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/output/UserDefinedOutputStrategy.java b/streampipes-model/src/main/java/org/apache/streampipes/model/output/UserDefinedOutputStrategy.java
index 7f8f725eef..622d1e25ec 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/output/UserDefinedOutputStrategy.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/output/UserDefinedOutputStrategy.java
@@ -42,4 +42,9 @@ public class UserDefinedOutputStrategy extends OutputStrategy {
   public void setEventProperties(List<EventProperty> eventProperties) {
     this.eventProperties = eventProperties;
   }
+
+  @Override
+  public void accept(OutputStrategyVisitor visitor) {
+    visitor.visit(this);
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/CompactPipelineElement.java b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/CompactPipelineElement.java
index b145c2aad3..f027e60e05 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/CompactPipelineElement.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/CompactPipelineElement.java
@@ -28,5 +28,6 @@ public record CompactPipelineElement(String type,
                                      String ref,
                                      String id,
                                      List<String> connectedTo,
-                                     List<Map<String, Object>> configuration) {
+                                     List<Map<String, Object>> configuration,
+                                     OutputConfiguration output) {
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/OutputConfiguration.java b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/OutputConfiguration.java
new file mode 100644
index 0000000000..f9d88fa97d
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/OutputConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.model.pipeline.compact;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.util.List;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public record OutputConfiguration(List<String> keep,
+                                  List<UserDefinedOutput> userDefined) {
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/UserDefinedOutput.java b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/UserDefinedOutput.java
new file mode 100644
index 0000000000..22b9b924a1
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/pipeline/compact/UserDefinedOutput.java
@@ -0,0 +1,24 @@
+/*
+ * 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.pipeline.compact;
+
+public record UserDefinedOutput(String fieldName,
+                                String runtimeType,
+                                String semanticType) {
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/pipeline/CheckCompletedVisitor.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/pipeline/CheckCompletedVisitor.java
index fadbd19ecb..63440e7ca5 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/pipeline/CheckCompletedVisitor.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/matching/v2/pipeline/CheckCompletedVisitor.java
@@ -21,6 +21,7 @@ package org.apache.streampipes.manager.matching.v2.pipeline;
 import org.apache.streampipes.model.pipeline.PipelineElementValidationInfo;
 import org.apache.streampipes.model.staticproperty.AnyStaticProperty;
 import org.apache.streampipes.model.staticproperty.CodeInputStaticProperty;
+import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
 import org.apache.streampipes.model.staticproperty.ColorPickerStaticProperty;
 import org.apache.streampipes.model.staticproperty.DefaultStaticPropertyVisitor;
 import org.apache.streampipes.model.staticproperty.FileStaticProperty;
@@ -66,6 +67,11 @@ public class CheckCompletedVisitor extends DefaultStaticPropertyVisitor {
     validateNull(codeInputStaticProperty, codeInputStaticProperty.getValue());
   }
 
+  @Override
+  public void visit(CollectionStaticProperty collectionStaticProperty) {
+    collectionStaticProperty.getMembers().forEach(sp -> sp.accept(this));
+  }
+
   @Override
   public void visit(ColorPickerStaticProperty colorPickerStaticProperty) {
     validateNull(colorPickerStaticProperty, colorPickerStaticProperty.getSelectedColor());
@@ -206,7 +212,7 @@ public class CheckCompletedVisitor extends DefaultStaticPropertyVisitor {
     validationInfos.add(
         PipelineElementValidationInfo.error(
             String.format(
-                "Configuration option \"%s\" as no value although it is marked as required",
+                "Configuration option \"%s\" has no value although it is marked as required",
                 sp.getInternalName()
             )
         )
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/CompactPipelineConverter.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/CompactPipelineConverter.java
index bebc3b9286..a31360e0cc 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/CompactPipelineConverter.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/CompactPipelineConverter.java
@@ -19,8 +19,15 @@
 package org.apache.streampipes.manager.pipeline.compact.generation;
 
 import org.apache.streampipes.manager.template.CompactConfigGenerator;
+import org.apache.streampipes.model.output.CustomOutputStrategy;
+import org.apache.streampipes.model.output.OutputStrategy;
+import org.apache.streampipes.model.output.UserDefinedOutputStrategy;
 import org.apache.streampipes.model.pipeline.Pipeline;
 import org.apache.streampipes.model.pipeline.compact.CompactPipelineElement;
+import org.apache.streampipes.model.pipeline.compact.OutputConfiguration;
+import org.apache.streampipes.model.pipeline.compact.UserDefinedOutput;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
 import org.apache.streampipes.model.staticproperty.StaticProperty;
 
 import java.util.ArrayList;
@@ -38,6 +45,7 @@ public class CompactPipelineConverter {
             stream.getDom(),
             stream.getElementId(),
             null,
+            null,
             null))
         .forEach(pipelineElements::add);
 
@@ -47,7 +55,8 @@ public class CompactPipelineConverter {
             processor.getDom(),
             processor.getAppId(),
             processor.getConnectedTo(),
-            getConfig(processor.getStaticProperties())))
+            getConfig(processor.getStaticProperties()),
+            getOutput(processor.getOutputStrategies().get(0))))
         .forEach(pipelineElements::add);
 
     pipeline.getActions().stream()
@@ -56,7 +65,8 @@ public class CompactPipelineConverter {
             sink.getDom(),
             sink.getAppId(),
             sink.getConnectedTo(),
-            getConfig(sink.getStaticProperties())))
+            getConfig(sink.getStaticProperties()),
+            null))
         .forEach(pipelineElements::add);
 
     return pipelineElements;
@@ -66,11 +76,12 @@ public class CompactPipelineConverter {
                                                String ref,
                                                String elementId,
                                                List<String> connectedTo,
-                                               List<Map<String, Object>> config) {
+                                               List<Map<String, Object>> config,
+                                               OutputConfiguration outputConfiguration) {
     var connections = connectedTo != null ? connectedTo.stream()
         .map(this::replaceId)
         .toList() : null;
-    return new CompactPipelineElement(type, replaceId(ref), elementId, connections, config);
+    return new CompactPipelineElement(type, replaceId(ref), elementId, connections, config, outputConfiguration);
   }
 
   public List<Map<String, Object>> getConfig(List<StaticProperty> staticProperties) {
@@ -79,7 +90,27 @@ public class CompactPipelineConverter {
     return configs;
   }
 
+  public OutputConfiguration getOutput(OutputStrategy outputStrategy) {
+    if (outputStrategy instanceof CustomOutputStrategy) {
+      return new OutputConfiguration(((CustomOutputStrategy) outputStrategy).getSelectedPropertyKeys(), null);
+    } else if (outputStrategy instanceof UserDefinedOutputStrategy) {
+      return new OutputConfiguration(
+          null,
+          toCustomConfig(((UserDefinedOutputStrategy) outputStrategy).getEventProperties())
+      );
+    } else {
+      return null;
+    }
+  }
+
+  private List<UserDefinedOutput> toCustomConfig(List<EventProperty> eventProperties) {
+    return eventProperties.stream().map(ep -> new UserDefinedOutput(
+        ep.getRuntimeName(),
+        ((EventPropertyPrimitive) ep).getRuntimeType(),
+        ep.getSemanticType())).toList();
+  }
+
   private String replaceId(String id) {
-    return id.replaceAll(InvocablePipelineElementGenerator.ID_PREFIX, "");
+    return id != null ? id.replaceAll(InvocablePipelineElementGenerator.ID_PREFIX, "") : null;
   }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/DataProcessorPipelineElementGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/DataProcessorPipelineElementGenerator.java
index c736293c20..89f7fd10dd 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/DataProcessorPipelineElementGenerator.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/DataProcessorPipelineElementGenerator.java
@@ -35,7 +35,13 @@ public class DataProcessorPipelineElementGenerator {
                                           CompactPipelineElement pipelineElement) {
     basicGenerator.apply(processor, pipelineElement);
     var template = basicGenerator.makeTemplate(processor, pipelineElement);
-    return new DataProcessorTemplateHandler(template, processor, false)
+    var element = new DataProcessorTemplateHandler(template, processor, false)
         .applyTemplateOnPipelineElement();
+
+    if (pipelineElement.output() != null) {
+      var outputStrategyGenerator = new OutputStrategyGenerator(pipelineElement.output());
+      element.getOutputStrategies().forEach(o -> o.accept(outputStrategyGenerator));
+    }
+    return element;
   }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/OutputStrategyGenerator.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/OutputStrategyGenerator.java
new file mode 100644
index 0000000000..2cb4cd6067
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/pipeline/compact/generation/OutputStrategyGenerator.java
@@ -0,0 +1,108 @@
+/*
+ * 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.manager.pipeline.compact.generation;
+
+import org.apache.streampipes.model.output.AppendOutputStrategy;
+import org.apache.streampipes.model.output.CustomOutputStrategy;
+import org.apache.streampipes.model.output.CustomTransformOutputStrategy;
+import org.apache.streampipes.model.output.FixedOutputStrategy;
+import org.apache.streampipes.model.output.KeepOutputStrategy;
+import org.apache.streampipes.model.output.ListOutputStrategy;
+import org.apache.streampipes.model.output.OutputStrategyVisitor;
+import org.apache.streampipes.model.output.TransformOutputStrategy;
+import org.apache.streampipes.model.output.UserDefinedOutputStrategy;
+import org.apache.streampipes.model.pipeline.compact.OutputConfiguration;
+import org.apache.streampipes.model.pipeline.compact.UserDefinedOutput;
+import org.apache.streampipes.model.schema.EventProperty;
+import org.apache.streampipes.model.schema.EventPropertyPrimitive;
+
+import java.util.List;
+
+public class OutputStrategyGenerator implements OutputStrategyVisitor {
+
+  private final OutputConfiguration config;
+
+  public OutputStrategyGenerator(OutputConfiguration outputConfiguration) {
+    this.config = outputConfiguration;
+  }
+
+  @Override
+  public void visit(AppendOutputStrategy appendOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(CustomOutputStrategy customOutputStrategy) {
+    var keepConfig = config.keep();
+    if (keepConfig != null && !keepConfig.isEmpty()) {
+      customOutputStrategy.setSelectedPropertyKeys(keepConfig);
+    }
+  }
+
+  @Override
+  public void visit(CustomTransformOutputStrategy customTransformOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(FixedOutputStrategy fixedOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(KeepOutputStrategy keepOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(ListOutputStrategy listOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(TransformOutputStrategy transformOutputStrategy) {
+
+  }
+
+  @Override
+  public void visit(UserDefinedOutputStrategy userDefinedOutputStrategy) {
+    var userDefinedConfig = config.userDefined();
+    if (userDefinedConfig != null && !userDefinedConfig.isEmpty()) {
+      userDefinedOutputStrategy.setEventProperties(
+          toEp(userDefinedConfig)
+      );
+    }
+  }
+
+  private List<EventProperty> toEp(List<UserDefinedOutput> userDefinedOutput) {
+    return userDefinedOutput
+        .stream()
+        .map(this::toPrimitive)
+        .toList();
+  }
+
+  private EventProperty toPrimitive(UserDefinedOutput u) {
+    var ep = new EventPropertyPrimitive();
+    ep.setRuntimeName(u.fieldName());
+    ep.setSemanticType(u.semanticType());
+    ep.setRuntimeType(u.runtimeType());
+
+    return ep;
+  }
+}
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/compact/CompactPipelineTemplateManagement.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/compact/CompactPipelineTemplateManagement.java
index 0bf308cfc4..1238a0aeda 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/compact/CompactPipelineTemplateManagement.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/compact/CompactPipelineTemplateManagement.java
@@ -57,7 +57,8 @@ public class CompactPipelineTemplateManagement {
             key,
             stream.getElementId(),
             List.of(),
-            List.of()
+            List.of(),
+            null
         ));
       });
     }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/instances/PersistDataLakePipelineTemplate.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/instances/PersistDataLakePipelineTemplate.java
index caa6e7bf94..00c768f4a7 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/instances/PersistDataLakePipelineTemplate.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/instances/PersistDataLakePipelineTemplate.java
@@ -52,7 +52,8 @@ public class PersistDataLakePipelineTemplate implements DefaultPipelineTemplateP
                 List.of(
                     Map.of("schema_update", "Update schema"),
                     Map.of("ignore_duplicates", false)
-                )
+                ),
+                null
             )
         )
     );
diff --git a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
index 72c77121aa..8e3d4d4a85 100644
--- a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
+++ b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.resource.management;
 
+import org.apache.streampipes.commons.exceptions.connect.AdapterException;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.util.Cloner;
 import org.apache.streampipes.resource.management.secret.SecretProvider;
@@ -30,7 +31,8 @@ public class AdapterResourceManager extends AbstractResourceManager<IAdapterStor
   }
 
   public AdapterResourceManager() {
-    super(StorageDispatcher.INSTANCE.getNoSqlStore().getAdapterInstanceStorage());
+    super(StorageDispatcher.INSTANCE.getNoSqlStore()
+                                    .getAdapterInstanceStorage());
   }
 
   /**
@@ -39,10 +41,15 @@ public class AdapterResourceManager extends AbstractResourceManager<IAdapterStor
    * @param adapterDescription input adapter description
    * @return the id of the created adapter
    */
-  public String encryptAndCreate(AdapterDescription adapterDescription) {
-    AdapterDescription encryptedAdapterDescription = cloneAndEncrypt(adapterDescription);
+  public String encryptAndCreate(AdapterDescription adapterDescription) throws AdapterException {
+    var encryptedAdapterDescription = cloneAndEncrypt(adapterDescription);
     encryptedAdapterDescription.setRev(null);
-    return db.persist(encryptedAdapterDescription).v;
+
+    try {
+      return db.persist(encryptedAdapterDescription).v;
+    } catch (org.lightcouch.DocumentConflictException e) {
+      throw new AdapterException("Conflict occurred while creating the adapter", e);
+    }
   }
 
   /**
@@ -50,8 +57,15 @@ public class AdapterResourceManager extends AbstractResourceManager<IAdapterStor
    *
    * @param adapterDescription input adapter description
    */
-  public void encryptAndUpdate(AdapterDescription adapterDescription) {
-    db.updateElement(cloneAndEncrypt(adapterDescription));
+  public void encryptAndUpdate(AdapterDescription adapterDescription) throws AdapterException {
+    try {
+      db.updateElement(cloneAndEncrypt(adapterDescription));
+    } catch (org.lightcouch.DocumentConflictException e) {
+      throw new AdapterException(
+          "Conflict occurred while editing the adapter with id: %s".formatted(adapterDescription.getElementId()),
+          e
+      );
+    }
   }
 
   public void delete(String elementId) {
@@ -63,7 +77,8 @@ public class AdapterResourceManager extends AbstractResourceManager<IAdapterStor
    */
   private AdapterDescription cloneAndEncrypt(AdapterDescription adapterDescription) {
     AdapterDescription encryptedAdapterDescription = new Cloner().adapterDescription(adapterDescription);
-    SecretProvider.getEncryptionService().apply(encryptedAdapterDescription);
+    SecretProvider.getEncryptionService()
+                  .apply(encryptedAdapterDescription);
     return encryptedAdapterDescription;
   }
 
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
index b972aaa7eb..372769a792 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
@@ -40,6 +40,7 @@ import org.apache.streampipes.rest.shared.constants.SpMediaType;
 import org.apache.streampipes.storage.api.IPipelineStorage;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.http.HttpStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -115,7 +116,7 @@ public class AdapterResource extends AbstractAdapterResource<AdapterMasterManage
       updateManager.updateAdapter(adapterDescription);
     } catch (AdapterException e) {
       LOG.error("Error while updating adapter with id {}", adapterDescription.getElementId(), e);
-      return ok(Notifications.error(e.getMessage()));
+      return ok(Notifications.error(e.getMessage(), ExceptionUtils.getStackTrace(e)));
     }
 
     return ok(Notifications.success(adapterDescription.getElementId()));
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/CompactAdapterResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/CompactAdapterResource.java
index 88424c2256..0e51f00927 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/CompactAdapterResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/CompactAdapterResource.java
@@ -37,6 +37,7 @@ import org.apache.streampipes.storage.management.StorageDispatcher;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -58,7 +59,7 @@ public class CompactAdapterResource extends AbstractAdapterResource<AdapterMaste
   public CompactAdapterResource() {
     super(() -> new AdapterMasterManagement(
         StorageDispatcher.INSTANCE.getNoSqlStore()
-            .getAdapterInstanceStorage(),
+                                  .getAdapterInstanceStorage(),
         new SpResourceManager().manageAdapters(),
         new SpResourceManager().manageDataStreams(),
         AdapterMetricsManager.INSTANCE.getAdapterMetrics()
@@ -82,11 +83,23 @@ public class CompactAdapterResource extends AbstractAdapterResource<AdapterMaste
     var adapterDescription = getGeneratedAdapterDescription(compactAdapter);
     var principalSid = getAuthenticatedUserSid();
 
+    var adapterId = adapterDescription.getElementId();
+
     try {
-      var adapterId = adapterDescription.getElementId();
       managementService.addAdapter(adapterDescription, adapterId, principalSid);
+    } catch (AdapterException e) {
+      LOG.error(
+          "Error while storing the adapterDescription with appId {}. An adapter with the given id already exists.",
+          adapterDescription.getAppId(), e
+      );
+      return ResponseEntity.status(HttpStatus.CONFLICT)
+                           .body(Notifications.error(e.getMessage()));
+    }
+
+    try {
       if (compactAdapter.createOptions() != null) {
-        if (compactAdapter.createOptions().persist()) {
+        if (compactAdapter.createOptions()
+                          .persist()) {
           var storedAdapter = managementService.getAdapter(adapterId);
           var status = new PersistPipelineHandler(
               getNoSqlStorage().getPipelineTemplateStorage(),
@@ -96,7 +109,8 @@ public class CompactAdapterResource extends AbstractAdapterResource<AdapterMaste
               getAuthenticatedUserSid()
           ).createAndStartPersistPipeline(storedAdapter);
         }
-        if (compactAdapter.createOptions().start()) {
+        if (compactAdapter.createOptions()
+                          .start()) {
           managementService.startStreamAdapter(adapterId);
         }
       }
@@ -143,8 +157,10 @@ public class CompactAdapterResource extends AbstractAdapterResource<AdapterMaste
     return new CompactAdapterManagement(generators).convertToAdapterDescription(compactAdapter);
   }
 
-  private AdapterDescription getGeneratedAdapterDescription(CompactAdapter compactAdapter,
-                                                            AdapterDescription existingAdapter) throws Exception {
+  private AdapterDescription getGeneratedAdapterDescription(
+      CompactAdapter compactAdapter,
+      AdapterDescription existingAdapter
+  ) throws Exception {
     var generators = adapterGenerationSteps.getGenerators();
     return new CompactAdapterManagement(generators).convertToAdapterDescription(compactAdapter, existingAdapter);
   }
diff --git a/ui/cypress/fixtures/connect/compact/fileReplay.yml b/ui/cypress/fixtures/connect/compact/fileReplay.yml
new file mode 100644
index 0000000000..3c57795f10
--- /dev/null
+++ b/ui/cypress/fixtures/connect/compact/fileReplay.yml
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+id: sp:adapterdescription:IfmzfQ
+name: File Stream Adapter Test
+description: ''
+appId: org.apache.streampipes.connect.iiot.protocol.stream.file
+configuration:
+    - filePath: compactTest.csv
+    - replaceTimestamp:
+          - ''
+    - replayOnce: 'no'
+    - speed: keepOriginalTime
+    - delimiter: ;
+      format: CSV
+      header:
+          - Header
+schema:
+    timestamp:
+        description: ''
+        propertyScope: HEADER_PROPERTY
+        semanticType: http://schema.org/DateTime
+transform:
+    rename: {}
+    measurementUnit: {}
+createOptions:
+    persist: true
+    start: true
diff --git a/ui/cypress/fixtures/connect/compact/machineDataSimulator.yml b/ui/cypress/fixtures/connect/compact/machineDataSimulator.yml
new file mode 100644
index 0000000000..128b249ca6
--- /dev/null
+++ b/ui/cypress/fixtures/connect/compact/machineDataSimulator.yml
@@ -0,0 +1,24 @@
+# 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.
+
+id: sp:adapterdescription:4pxl2w
+name: Test
+appId: org.apache.streampipes.connect.iiot.adapters.simulator.machine
+configuration:
+    - wait-time-ms: '1000'
+    - selected-simulator-option: flowrate
+createOptions:
+    persist: false
+    start: false
diff --git a/ui/cypress/support/builder/CompactAdapterBuilder.ts b/ui/cypress/support/builder/CompactAdapterBuilder.ts
new file mode 100644
index 0000000000..2325985032
--- /dev/null
+++ b/ui/cypress/support/builder/CompactAdapterBuilder.ts
@@ -0,0 +1,93 @@
+/*
+ *  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 { CompactAdapter } from '../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+
+export class CompactAdapterBuilder {
+    private compactAdapter: CompactAdapter;
+
+    constructor() {
+        this.compactAdapter = new CompactAdapter();
+        this.compactAdapter.configuration = [];
+        this.compactAdapter.createOptions = {
+            persist: false,
+            start: false,
+        };
+        this.compactAdapter.transform = {
+            rename: {},
+            measurementUnit: {},
+        };
+    }
+
+    public static create(appId: string) {
+        const builder = new CompactAdapterBuilder();
+        builder.compactAdapter.appId = appId;
+        return builder;
+    }
+
+    // Optional parameter, when not set a random id will be generated
+    public setId(id: string) {
+        this.compactAdapter.id = id;
+        return this;
+    }
+
+    public setName(name: string) {
+        this.compactAdapter.name = name;
+        return this;
+    }
+
+    public setDescription(description: string) {
+        this.compactAdapter.description = description;
+        return this;
+    }
+
+    public withRename(from: string, to: string) {
+        this.compactAdapter.transform.rename[from] = to;
+        return this;
+    }
+
+    public withMeasurementUnit(property: string, unit: string) {
+        this.compactAdapter.transform.measurementUnit[property] = unit;
+        return this;
+    }
+
+    public addConfiguration(key: string, value: string) {
+        const configuration = { [key]: value };
+        this.compactAdapter.configuration.push(configuration);
+        return this;
+    }
+
+    public setPersist() {
+        this.compactAdapter.createOptions.persist = true;
+        return this;
+    }
+
+    public setStart() {
+        this.compactAdapter.createOptions.start = true;
+        return this;
+    }
+
+    public build() {
+        if (!this.compactAdapter.id) {
+            this.compactAdapter.id =
+                'sp:adapterdescription:' +
+                Math.random().toString(36).substring(7);
+        }
+        return this.compactAdapter;
+    }
+}
diff --git a/ui/cypress/support/utils/CompactUtils.ts b/ui/cypress/support/utils/CompactUtils.ts
new file mode 100644
index 0000000000..38df176d86
--- /dev/null
+++ b/ui/cypress/support/utils/CompactUtils.ts
@@ -0,0 +1,27 @@
+/*
+ *  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 class CompactUtils {
+    public static ymlConfiguration() {
+        return cy.dataCy('yaml-configuration', { timeout: 5000 });
+    }
+
+    public static jsonConfiguration() {
+        return cy.dataCy('json-configuration', { timeout: 5000 });
+    }
+}
diff --git a/ui/cypress/support/utils/GeneralUtils.ts b/ui/cypress/support/utils/GeneralUtils.ts
new file mode 100644
index 0000000000..8db505e32b
--- /dev/null
+++ b/ui/cypress/support/utils/GeneralUtils.ts
@@ -0,0 +1,23 @@
+/*
+ *  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 class GeneralUtils {
+    public static tab(identifier: string) {
+        return cy.dataCy(`tab-${identifier}`).click();
+    }
+}
diff --git a/ui/cypress/support/utils/ThirdPartyIntegrationUtils.ts b/ui/cypress/support/utils/ThirdPartyIntegrationUtils.ts
index a9229a9a05..09a871c6fb 100644
--- a/ui/cypress/support/utils/ThirdPartyIntegrationUtils.ts
+++ b/ui/cypress/support/utils/ThirdPartyIntegrationUtils.ts
@@ -18,7 +18,7 @@
 
 import { ConnectUtils } from './connect/ConnectUtils';
 import { PipelineBuilder } from '../builder/PipelineBuilder';
-import { PipelineUtils } from './PipelineUtils';
+import { PipelineUtils } from './pipeline/PipelineUtils';
 import { PipelineElementInput } from '../model/PipelineElementInput';
 import { AdapterInput } from '../model/AdapterInput';
 import { AdapterBuilder } from '../builder/AdapterBuilder';
diff --git a/ui/cypress/support/utils/connect/CompactAdapterUtils.ts b/ui/cypress/support/utils/connect/CompactAdapterUtils.ts
new file mode 100644
index 0000000000..43757f580c
--- /dev/null
+++ b/ui/cypress/support/utils/connect/CompactAdapterUtils.ts
@@ -0,0 +1,81 @@
+/*
+ *  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 { CompactAdapter } from '../../../../projects/streampipes/platform-services/src/lib/model/gen/streampipes-model';
+import { CompactAdapterBuilder } from '../../builder/CompactAdapterBuilder';
+
+export class CompactAdapterUtils {
+    /**
+     * Stores a compact adapter by sending a POST request to the backend.
+     *
+     * @param {CompactAdapter} compactAdapter - The compact adapter to be stored.
+     * @param {boolean} [failOnStatusCode=true] - Whether to fail the request on a non-2xx status code.
+     * @returns {Cypress.Chainable} - The Cypress chainable object representing the request.
+     */
+    public static storeCompactAdapter(
+        compactAdapter: CompactAdapter,
+        failOnStatusCode: boolean = true,
+    ): Cypress.Chainable {
+        return this.postCompactAdapterRequest(
+            'application/json',
+            compactAdapter,
+            failOnStatusCode,
+        );
+    }
+
+    /**
+     * Stores a compact YAML adapter by sending a POST request to the backend.
+     *
+     * @param {string} body - The YAML string representing the compact adapter.
+     * @returns {Cypress.Chainable} - The Cypress chainable object representing the request.
+     */
+    public static storeCompactYmlAdapter(body: string) {
+        return this.postCompactAdapterRequest('application/yml', body);
+    }
+
+    private static postCompactAdapterRequest(
+        contentType: string,
+        body: any,
+        failOnStatusCode = true,
+    ) {
+        const token = window.localStorage.getItem('auth-token');
+        return cy.request({
+            method: 'POST',
+            url: '/streampipes-backend/api/v2/connect/compact-adapters',
+            body: body,
+            failOnStatusCode: failOnStatusCode,
+            headers: {
+                'Accept': contentType,
+                'Content-Type': contentType,
+                'Authorization': `Bearer ${token}`,
+            },
+        });
+    }
+
+    /**
+     * Creates a CompactAdapterBuilder instance configured for a machine data simulator.
+     */
+    public static getMachineDataSimulator(): CompactAdapterBuilder {
+        return CompactAdapterBuilder.create(
+            'org.apache.streampipes.connect.iiot.adapters.simulator.machine',
+        )
+            .setName('Test')
+            .addConfiguration('wait-time-ms', '1000')
+            .addConfiguration('selected-simulator-option', 'flowrate');
+    }
+}
diff --git a/ui/cypress/support/utils/connect/ConnectBtns.ts b/ui/cypress/support/utils/connect/ConnectBtns.ts
index 20bfd696c5..ea8b2d82c3 100644
--- a/ui/cypress/support/utils/connect/ConnectBtns.ts
+++ b/ui/cypress/support/utils/connect/ConnectBtns.ts
@@ -17,7 +17,11 @@
  */
 export class ConnectBtns {
     public static detailsAdapter() {
-        return cy.dataCy('details-adapter');
+        return cy.dataCy('details-adapter', { timeout: 10000 });
+    }
+
+    public static deleteAdapter() {
+        return cy.dataCy('delete-adapter', { timeout: 10000 });
     }
 
     public static editAdapter() {
@@ -69,6 +73,10 @@ export class ConnectBtns {
         return cy.dataCy('stop-all-adapters-btn');
     }
 
+    public static showCodeCheckbox() {
+        return cy.dataCy('show-code-checkbox');
+    }
+
     // ========================================================================
 
     // =====================  Event Schema buttons  ==========================
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts b/ui/cypress/support/utils/connect/ConnectUtils.ts
index aaeccff82c..0a0eae22c1 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -23,7 +23,7 @@ import { DataLakeUtils } from '../datalake/DataLakeUtils';
 import { ConnectBtns } from './ConnectBtns';
 import { AdapterBuilder } from '../../builder/AdapterBuilder';
 import { UserUtils } from '../UserUtils';
-import { PipelineUtils } from '../PipelineUtils';
+import { PipelineUtils } from '../pipeline/PipelineUtils';
 
 export class ConnectUtils {
     public static testAdapter(
@@ -76,9 +76,11 @@ export class ConnectUtils {
             );
         }
 
-        ConnectEventSchemaUtils.markPropertyAsTimestamp(
-            adapterConfiguration.timestampProperty,
-        );
+        if (adapterConfiguration.timestampProperty) {
+            ConnectEventSchemaUtils.markPropertyAsTimestamp(
+                adapterConfiguration.timestampProperty,
+            );
+        }
 
         ConnectEventSchemaUtils.finishEventSchemaConfiguration();
     }
@@ -356,6 +358,12 @@ export class ConnectUtils {
         ConnectUtils.validateEventsInPreview(amountOfProperties);
     }
 
+    public static getLivePreviewValue(runtimeName: string) {
+        return cy.dataCy(`live-preview-value-${runtimeName}`, {
+            timeout: 10000,
+        });
+    }
+
     public static validateEventsInPreview(amountOfProperties: number) {
         // View data
         ConnectBtns.detailsAdapter().click();
@@ -370,11 +378,25 @@ export class ConnectUtils {
             amountOfProperties,
         );
 
-        cy.wait(1000);
+        cy.dataCy('live-preview-table-no-data', { timout: 1000 }).should(
+            'not.exist',
+        );
+    }
+
+    /**
+     * Validates the event schema for an adapter by checking the amount of properties
+     * and the runtime names of the event properties
+     * @param runtimeNames runtime names of the event properties
+     */
+    public static validateEventSchema(runtimeNames: string[]) {
+        ConnectUtils.goToConnect();
+        ConnectBtns.detailsAdapter().click();
+
+        cy.get('tr.mat-mdc-row').should('have.length', runtimeNames.length);
 
-        cy.dataCy('live-preview-table-value')
-            .invoke('text')
-            .then(text => expect(text).not.to.include('no data'));
+        runtimeNames.forEach(name => {
+            cy.get('td.mat-column-runtimeName').contains(name).should('exist');
+        });
     }
 
     public static tearDownPreprocessingRuleTest(
@@ -403,4 +425,21 @@ export class ConnectUtils {
         // Close dialog
         cy.get('button').contains('Close').parent().click();
     }
+
+    public static validateAdapterIsRunning() {
+        ConnectUtils.goToConnect();
+        ConnectBtns.startAdapter().should('have.length', 0);
+        ConnectBtns.stopAdapter().should('have.length', 1);
+    }
+
+    public static validateAdapterIsStopped() {
+        ConnectUtils.goToConnect();
+        ConnectBtns.startAdapter().should('have.length', 1);
+        ConnectBtns.stopAdapter().should('have.length', 0);
+    }
+
+    public static checkAmountOfAdapters(amount: number) {
+        ConnectUtils.goToConnect();
+        ConnectBtns.deleteAdapter().should('have.length', amount);
+    }
 }
diff --git a/ui/cypress/support/utils/pipeline/PipelineBtns.ts b/ui/cypress/support/utils/pipeline/PipelineBtns.ts
new file mode 100644
index 0000000000..6ace82220f
--- /dev/null
+++ b/ui/cypress/support/utils/pipeline/PipelineBtns.ts
@@ -0,0 +1,23 @@
+/*
+ *  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 class PipelineBtns {
+    public static deletePipeline() {
+        return cy.dataCy('delete-pipeline', { timeout: 10000 });
+    }
+}
diff --git a/ui/cypress/support/utils/PipelineUtils.ts b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
similarity index 72%
rename from ui/cypress/support/utils/PipelineUtils.ts
rename to ui/cypress/support/utils/pipeline/PipelineUtils.ts
index b901e225de..0fa9ce4443 100644
--- a/ui/cypress/support/utils/PipelineUtils.ts
+++ b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
@@ -1,25 +1,26 @@
 /*
- * 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
+ *  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
+ *     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.
+ *  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 { PipelineInput } from '../model/PipelineInput';
-import { StaticPropertyUtils } from './userInput/StaticPropertyUtils';
-import { OutputStrategyUtils } from './OutputStrategyUtils';
-import { PipelineElementInput } from '../model/PipelineElementInput';
+import { PipelineInput } from '../../model/PipelineInput';
+import { StaticPropertyUtils } from '../userInput/StaticPropertyUtils';
+import { OutputStrategyUtils } from '../OutputStrategyUtils';
+import { PipelineElementInput } from '../../model/PipelineElementInput';
+import { PipelineBtns } from './PipelineBtns';
 
 export class PipelineUtils {
     public static addPipeline(pipelineInput: PipelineInput) {
@@ -131,21 +132,18 @@ export class PipelineUtils {
     }
 
     public static checkAmountOfPipelinesPipeline(amount: number) {
-        cy.visit('#/pipelines');
-        cy.dataCy('delete-pipeline').should('have.length', amount);
+        PipelineUtils.goToPipelines();
+        PipelineBtns.deletePipeline().should('have.length', amount);
     }
 
     public static deletePipeline() {
         // Delete pipeline
-        cy.visit('#/pipelines');
-        cy.dataCy('delete-pipeline').should('have.length', 1);
-        cy.dataCy('delete-pipeline').click({ force: true });
+        PipelineUtils.goToPipelines();
+        PipelineBtns.deletePipeline().should('have.length', 1);
+        PipelineBtns.deletePipeline().click({ force: true });
 
         cy.dataCy('sp-pipeline-stop-and-delete').click();
 
-        cy.dataCy('delete-pipeline', { timeout: 10000 }).should(
-            'have.length',
-            0,
-        );
+        PipelineBtns.deletePipeline().should('have.length', 0);
     }
 }
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
index 9f3cff7d29..f061e5daff 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/datalake/DateRange.ts
@@ -21,7 +21,50 @@ export interface TimeSettings {
     endTime: number;
     // deprecated
     dynamicSelection?: 15 | 60 | 1440 | 10080 | 43800 | 525600 | -1;
-    timeSelectionId?: TimeSelectionId;
+    timeSelectionId?: string;
+}
+
+export class TimeSelectionConstants {
+    static CUSTOM = 'custom';
+    static LAST_15_MINUTES = 'last-15-minutes';
+    static LAST_HOUR = 'last-hour';
+    static CURRENT_HOUR = 'current-hour';
+    static LAST_DAY = 'last-day';
+    static CURRENT_DAY = 'current-day';
+    static LAST_WEEK = 'last-week';
+    static CURRENT_WEEK = 'current-week';
+    static LAST_MONTH = 'last-month';
+    static CURRENT_MONTH = 'current-month';
+    static LAST_YEAR = 'last-year';
+    static CURRENT_YEAR = 'current-year';
+
+    static getLegacyTimeSelectionID(legacyID: number) {
+        if (legacyID === 0) {
+            return TimeSelectionConstants.CUSTOM;
+        } else if (legacyID === 1) {
+            return TimeSelectionConstants.LAST_15_MINUTES;
+        } else if (legacyID === 2) {
+            return TimeSelectionConstants.LAST_HOUR;
+        } else if (legacyID === 3) {
+            return TimeSelectionConstants.CURRENT_HOUR;
+        } else if (legacyID === 4) {
+            return TimeSelectionConstants.LAST_DAY;
+        } else if (legacyID === 5) {
+            return TimeSelectionConstants.CURRENT_DAY;
+        } else if (legacyID === 6) {
+            return TimeSelectionConstants.LAST_WEEK;
+        } else if (legacyID === 7) {
+            return TimeSelectionConstants.CURRENT_WEEK;
+        } else if (legacyID === 8) {
+            return TimeSelectionConstants.LAST_MONTH;
+        } else if (legacyID === 9) {
+            return TimeSelectionConstants.CURRENT_MONTH;
+        } else if (legacyID === 10) {
+            return TimeSelectionConstants.LAST_YEAR;
+        } else if (legacyID === 11) {
+            return TimeSelectionConstants.CURRENT_YEAR;
+        }
+    }
 }
 
 export interface WidgetTimeSettings {
@@ -34,6 +77,7 @@ export interface TimeString {
     startTime: string;
     endDate: string;
     endTime: string;
+    sameDay: boolean;
 }
 
 export enum TimeSelectionId {
@@ -53,7 +97,7 @@ export enum TimeSelectionId {
 
 export interface QuickTimeSelection {
     label: string;
-    timeSelectionId: TimeSelectionId;
+    timeSelectionId: string;
     startTime: (now: Date) => Date;
     endTime: (now: Date) => Date;
     addDividerAfter?: boolean;
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index cf07248af8..3aa23a65bf 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-10-11 10:41:46.
+// Generated using typescript-generator version 3.2.1263 on 2024-10-29 10:04:46.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -844,6 +844,7 @@ export class CompactPipelineElement {
     configuration: { [index: string]: any }[];
     connectedTo: string[];
     id: string;
+    output: OutputConfiguration;
     ref: string;
     type: string;
 
@@ -862,6 +863,7 @@ export class CompactPipelineElement {
             data.connectedTo,
         );
         instance.id = data.id;
+        instance.output = OutputConfiguration.fromData(data.output);
         instance.ref = data.ref;
         instance.type = data.type;
         return instance;
@@ -2605,6 +2607,26 @@ export class Option {
     }
 }
 
+export class OutputConfiguration {
+    keep: string[];
+    userDefined: UserDefinedOutput[];
+
+    static fromData(
+        data: OutputConfiguration,
+        target?: OutputConfiguration,
+    ): OutputConfiguration {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new OutputConfiguration();
+        instance.keep = __getCopyArrayFn(__identity<string>())(data.keep);
+        instance.userDefined = __getCopyArrayFn(UserDefinedOutput.fromData)(
+            data.userDefined,
+        );
+        return instance;
+    }
+}
+
 export class Pipeline implements Storable {
     _id: string;
     _rev: string;
@@ -4056,6 +4078,26 @@ export class UnitTransformRuleDescription extends ValueTransformationRuleDescrip
     }
 }
 
+export class UserDefinedOutput {
+    fieldName: string;
+    runtimeType: string;
+    semanticType: string;
+
+    static fromData(
+        data: UserDefinedOutput,
+        target?: UserDefinedOutput,
+    ): UserDefinedOutput {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new UserDefinedOutput();
+        instance.fieldName = data.fieldName;
+        instance.runtimeType = data.runtimeType;
+        instance.semanticType = data.semanticType;
+        return instance;
+    }
+}
+
 export class UserDefinedOutputStrategy extends OutputStrategy {
     '@class': 'org.apache.streampipes.model.output.UserDefinedOutputStrategy';
     'eventProperties': EventPropertyUnion[];
diff --git a/ui/projects/streampipes/shared-ui/package.json b/ui/projects/streampipes/shared-ui/package.json
index f2f8f4d9b5..6f8f27f9ef 100644
--- a/ui/projects/streampipes/shared-ui/package.json
+++ b/ui/projects/streampipes/shared-ui/package.json
@@ -10,7 +10,8 @@
     "@angular/material": "^17.3.3",
     "@angular/router": "^17.3.3",
     "@streampipes/platform-services": "0.0.1",
-    "rxjs": "^7.5.7"
+    "rxjs": "^7.5.7",
+    "date-fns": "^3.6.0"
   },
   "dependencies": {
     "tslib": "^2.6.2"
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html
index 68f9377e8f..c613d3cda3 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/basic-nav-tabs/basic-nav-tabs.component.html
@@ -42,6 +42,7 @@
                     *ngFor="let item of spNavigationItems"
                     (click)="navigateTo(item)"
                     [active]="activeLink === item.itemId"
+                    [attr.data-cy]="'tab-' + item.itemTitle"
                 >
                     <span>{{ item.itemTitle }}</span>
                 </a>
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.html
similarity index 96%
rename from ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.html
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.html
index 1a23450b84..36b2b76cfe 100644
--- a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.html
@@ -25,7 +25,7 @@
         matTooltip="Refresh interval"
     >
         <mat-icon>autorenew</mat-icon>
-        {{ dashboard.dashboardLiveSettings.label }}
+        {{ liveSettings.label }}
     </button>
     <mat-menu #menu="matMenu">
         <button
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.ts
similarity index 83%
rename from ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.ts
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.ts
index 9bd3b72d02..38327d1cb5 100644
--- a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/refresh-interval-settings/refresh-interval-settings.component.ts
@@ -17,22 +17,18 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import {
-    Dashboard,
-    DashboardLiveSettings,
-} from '@streampipes/platform-services';
+import { DashboardLiveSettings } from '@streampipes/platform-services';
 
 @Component({
     selector: 'sp-data-explorer-refresh-interval-settings-component',
     templateUrl: './refresh-interval-settings.component.html',
 })
 export class DataExplorerRefreshIntervalSettingsComponent implements OnInit {
-    @Input()
-    dashboard: Dashboard;
+    @Input() liveSettings: DashboardLiveSettings;
 
     @Output()
-    intervalSettingsChangedEmitter: EventEmitter<void> =
-        new EventEmitter<void>();
+    intervalSettingsChangedEmitter: EventEmitter<DashboardLiveSettings> =
+        new EventEmitter<DashboardLiveSettings>();
 
     availableOptions: DashboardLiveSettings[] = [
         {
@@ -82,13 +78,13 @@ export class DataExplorerRefreshIntervalSettingsComponent implements OnInit {
     ];
 
     ngOnInit() {
-        if (!this.dashboard.dashboardLiveSettings?.label) {
-            this.dashboard.dashboardLiveSettings = this.availableOptions[0];
+        if (!this.liveSettings?.label) {
+            this.liveSettings = this.availableOptions[0];
         }
     }
 
     modifyRefreshInterval(option: DashboardLiveSettings): void {
-        this.dashboard.dashboardLiveSettings = option;
-        this.intervalSettingsChangedEmitter.emit();
+        this.liveSettings = option;
+        this.intervalSettingsChangedEmitter.emit(option);
     }
 }
diff --git a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
similarity index 63%
rename from ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
index eb51825326..74d0a04ec4 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.html
@@ -30,25 +30,28 @@
             color="accent"
             [matMenuTriggerFor]="menu"
             #menuTrigger="matMenuTrigger"
-            matTooltip="Modify time"
+            [matTooltip]="labels.timeRangeSelectorTooltip"
             data-cy="time-selector-menu"
             (menuClosed)="menuTrigger.closeMenu()"
         >
-            <div *ngIf="timeStringMode === 'advanced'">
-                <div class="formatted-datetime">
-                    <span class="formatted-date">{{
-                        timeString.startDate
-                    }}</span
-                    >&nbsp;
-                    <span class="formatted-time">{{
+            <div
+                *ngIf="timeStringMode === 'advanced'"
+                class="formatted-datetime"
+            >
+                <span class="formatted-date">{{ timeString.startDate }}</span>
+                <span *ngIf="enableTimeChange">
+                    &nbsp;<span class="formatted-time">{{
                         timeString.startTime
                     }}</span>
-                </div>
-                -
-                <div class="formatted-datetime">
-                    <span class="formatted-date">{{ timeString.endDate }}</span
-                    >&nbsp;
-                    <span class="formatted-time">{{ timeString.endTime }}</span>
+                </span>
+                <div *ngIf="enableTimeChange || !timeString.sameDay">
+                    <span class="formatted-date">&nbsp;-&nbsp;</span>
+                    <span class="formatted-date">{{ timeString.endDate }}</span>
+                    <span *ngIf="enableTimeChange">
+                        &nbsp;<span class="formatted-time">{{
+                            timeString.endTime
+                        }}</span>
+                    </span>
                 </div>
             </div>
             <div class="formatted-datetime" *ngIf="timeStringMode === 'simple'">
@@ -63,7 +66,11 @@
             <sp-time-selector-menu
                 #timeSelectorMenu
                 [timeSettings]="timeSettings"
+                [labels]="labels"
                 (timeSettingsEmitter)="applyCurrentDateRange($event)"
+                [quickSelections]="quickSelections"
+                [enableTimeChange]="enableTimeChange"
+                [maxDayRange]="maxDayRange"
                 class="w-100"
             >
             </sp-time-selector-menu>
@@ -71,12 +78,22 @@
     </div>
     <div fxLayoutAlign="end center">
         <button
-            mat-button
+            mat-icon-button
+            matTooltip="Refresh"
             color="accent"
             (click)="updateTimeSettingsAndReload()"
         >
             <mat-icon>refresh</mat-icon>
-            Refresh
         </button>
     </div>
+    <div fxLayoutAlign="end center">
+        <sp-data-explorer-refresh-interval-settings-component
+            *ngIf="liveSettings"
+            [liveSettings]="liveSettings"
+            (intervalSettingsChangedEmitter)="
+                intervalSettingsChangedEmitter.emit($event)
+            "
+        >
+        </sp-data-explorer-refresh-interval-settings-component>
+    </div>
 </div>
diff --git a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
similarity index 96%
rename from ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
index aef8593a37..19107dc1c1 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.scss
@@ -16,8 +16,6 @@
  *
  */
 
-@import '../../../../scss/variables';
-
 .start-date-margin {
     margin-right: 5px;
 }
@@ -65,8 +63,9 @@
 }
 
 .formatted-datetime {
-    display: inline;
+    display: inline-flex;
     background: var(--color-bg-2);
     border-radius: 5px;
     padding: 5px;
+    white-space: nowrap;
 }
diff --git a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
similarity index 69%
rename from ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
index a2b663d5b3..465ae91373 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-range-selector.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-range-selector.component.ts
@@ -28,13 +28,17 @@ import {
     ViewEncapsulation,
 } from '@angular/core';
 import {
-    TimeSelectionId,
+    DashboardLiveSettings,
+    QuickTimeSelection,
+    TimeSelectionConstants,
     TimeSettings,
     TimeString,
 } from '@streampipes/platform-services';
 import { MatMenuTrigger } from '@angular/material/menu';
 import { TimeSelectionService } from '../../services/time-selection.service';
 import { TimeRangeSelectorMenuComponent } from './time-selector-menu/time-selector-menu.component';
+import { TimeSelectorLabel } from './time-selector.model';
+import { differenceInMilliseconds, isSameDay } from 'date-fns';
 
 @Component({
     selector: 'sp-time-range-selector',
@@ -49,24 +53,51 @@ export class TimeRangeSelectorComponent implements OnInit, OnChanges {
 
     @Output() dateRangeEmitter = new EventEmitter<TimeSettings>();
 
+    @Output()
+    intervalSettingsChangedEmitter = new EventEmitter<DashboardLiveSettings>();
+
     @Input()
     timeSettings: TimeSettings;
 
+    @Input()
+    liveSettings: DashboardLiveSettings;
+
     @Input()
     showTimeSelector = true;
 
+    @Input()
+    enableTimeChange = true;
+
+    @Input()
+    maxDayRange = 0;
+
+    @Input()
+    quickSelections: QuickTimeSelection[];
+
+    @Input()
+    labels: TimeSelectorLabel;
+
     simpleTimeString: string = '';
     timeString: TimeString;
     timeStringMode: 'simple' | 'advanced' = 'simple';
+    dateFormat: Intl.DateTimeFormatOptions = {
+        weekday: 'short',
+        year: 'numeric',
+        month: 'numeric',
+        day: 'numeric',
+    };
 
     constructor(private timeSelectionService: TimeSelectionService) {}
 
     ngOnInit() {
+        this.quickSelections ??=
+            this.timeSelectionService.defaultQuickTimeSelections;
+        this.labels ??= this.timeSelectionService.defaultLabels;
         this.createDateString();
     }
 
     ngOnChanges(changes: SimpleChanges) {
-        if (changes.timeSettings) {
+        if (changes.timeSettings && this.quickSelections !== undefined) {
             this.createDateString();
         }
     }
@@ -95,6 +126,7 @@ export class TimeRangeSelectorComponent implements OnInit, OnChanges {
 
     updateTimeSettingsAndReload() {
         this.timeSelectionService.updateTimeSettings(
+            this.quickSelections,
             this.timeSettings,
             new Date(),
         );
@@ -105,14 +137,19 @@ export class TimeRangeSelectorComponent implements OnInit, OnChanges {
     }
 
     private changeTimeByInterval(func: (a: number, b: number) => number) {
-        const difference =
-            this.timeSettings.endTime - this.timeSettings.startTime;
-        const newStartTime = func(this.timeSettings.startTime, difference);
-        const newEndTime = func(this.timeSettings.endTime, difference);
+        const timeDiff =
+            (differenceInMilliseconds(
+                this.timeSettings.startTime,
+                this.timeSettings.endTime,
+            ) -
+                1) *
+            -1;
+        const newStartTime = func(this.timeSettings.startTime, timeDiff);
+        const newEndTime = func(this.timeSettings.endTime, timeDiff);
 
         this.timeSettings.startTime = newStartTime;
         this.timeSettings.endTime = newEndTime;
-        this.timeSettings.timeSelectionId = TimeSelectionId.CUSTOM;
+        this.timeSettings.timeSelectionId = TimeSelectionConstants.CUSTOM;
         this.timeSelectorMenu.triggerDisplayUpdate();
         this.createDateString();
         this.reloadData();
@@ -126,8 +163,11 @@ export class TimeRangeSelectorComponent implements OnInit, OnChanges {
     }
 
     createDateString(): void {
-        if (this.timeSettings.timeSelectionId !== TimeSelectionId.CUSTOM) {
+        if (
+            this.timeSettings.timeSelectionId !== TimeSelectionConstants.CUSTOM
+        ) {
             this.simpleTimeString = this.timeSelectionService.getTimeSelection(
+                this.quickSelections,
                 this.timeSettings.timeSelectionId,
             ).label;
             this.timeStringMode = 'simple';
@@ -135,12 +175,20 @@ export class TimeRangeSelectorComponent implements OnInit, OnChanges {
             const startDate = new Date(this.timeSettings.startTime);
             const endDate = new Date(this.timeSettings.endTime);
             this.timeString = {
-                startDate: startDate.toLocaleDateString(),
-                endDate: endDate.toLocaleDateString(),
+                startDate: this.formatDate(startDate),
+                endDate: this.formatDate(endDate),
                 startTime: startDate.toLocaleTimeString(),
                 endTime: endDate.toLocaleTimeString(),
+                sameDay: isSameDay(startDate, endDate),
             };
+
             this.timeStringMode = 'advanced';
         }
     }
+
+    private formatDate(date: Date): string {
+        return this.enableTimeChange
+            ? date.toLocaleDateString()
+            : date.toLocaleDateString(navigator.language, this.dateFormat);
+    }
 }
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
similarity index 86%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
index 1564d9b5dc..38fba4f86d 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.html
@@ -26,7 +26,7 @@
             </mat-calendar>
         </mat-card>
 
-        <div fxLayout="column" class="mt-10 mr-5">
+        <div *ngIf="enableTimeChange" fxLayout="column" class="mt-10 mr-5">
             <div fxLayout="row" fxLayoutGap="10px">
                 <div fxFlex="30">
                     <span
@@ -73,6 +73,21 @@
             </div>
         </div>
     </div>
+    <div *ngIf="!enableTimeChange" fxLayout="row" class="mt-10 date-preview">
+        {{ dateRangeString }}
+    </div>
+    <div
+        fxLayout="row"
+        class="mt-5 max-date-range-error"
+        *ngIf="maxDateRangeError"
+    >
+        {{
+            labels.maxDayRangeErrorLabel.replace(
+                '${this.maxDayRange}',
+                maxDayRange.toString()
+            )
+        }}
+    </div>
     <div fxLayout="row" fxLayoutAlign="end center" class="mt-10">
         <ng-content> </ng-content>
         <button
@@ -81,6 +96,7 @@
             data-cy="apply-custom-time"
             (click)="saveSelection()"
             [disabled]="!dateSelectionComplete"
+            *ngIf="enableTimeChange"
         >
             Apply
         </button>
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
similarity index 91%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
index ce53cf59ea..d181ae05dd 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.scss
@@ -20,3 +20,8 @@
     font-family: inherit;
     font-size: 11pt;
 }
+
+.max-date-range-error {
+    font-size: 9pt;
+    color: var(--color-warn);
+}
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
similarity index 63%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
index 2129a521c9..5843f03a68 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component.ts
@@ -17,12 +17,17 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
-import { TimeSelectionId, TimeSettings } from '@streampipes/platform-services';
+import {
+    TimeSelectionConstants,
+    TimeSettings,
+} from '@streampipes/platform-services';
 import {
     DateRange,
     DefaultMatCalendarRangeStrategy,
     MatRangeDateSelectionModel,
 } from '@angular/material/datepicker';
+import { differenceInDays, endOfDay, startOfDay } from 'date-fns';
+import { TimeSelectorLabel } from '../../time-selector.model';
 
 @Component({
     selector: 'sp-custom-time-range-selection',
@@ -31,6 +36,15 @@ import {
 })
 export class CustomTimeRangeSelectionComponent implements OnInit {
     @Input() timeSettings: TimeSettings;
+
+    @Input() labels: TimeSelectorLabel;
+
+    @Input()
+    enableTimeChange: boolean;
+
+    @Input()
+    maxDayRange: number;
+
     @Output() timeSettingsEmitter = new EventEmitter<TimeSettings>();
 
     currentStartDate: string;
@@ -39,6 +53,9 @@ export class CustomTimeRangeSelectionComponent implements OnInit {
     currentEndTime: string;
     currentDateRange: DateRange<Date>;
     dateSelectionComplete = false;
+    dateRangeString: string;
+
+    maxDateRangeError = false;
 
     constructor(
         private readonly selectionModel: MatRangeDateSelectionModel<Date>,
@@ -75,13 +92,19 @@ export class CustomTimeRangeSelectionComponent implements OnInit {
     updateDateStrings(): void {
         this.currentStartDate = this.formatDate(this.currentDateRange.start);
         this.currentEndDate = this.formatDate(this.currentDateRange.end);
+        this.dateRangeString = `${this.currentStartDate} - ${this.currentEndDate}`;
     }
 
     formatDate(date: Date): string {
-        return date?.toLocaleDateString() || '-';
+        if (this.enableTimeChange === true) {
+            return date?.toLocaleDateString() || '-';
+        } else {
+            return date?.toLocaleDateString() || ' ';
+        }
     }
 
     onDateChange(selectedDate: Date): void {
+        this.maxDateRangeError = false;
         const newSelection = this.selectionStrategy.selectionFinished(
             selectedDate,
             this.selectionModel.selection,
@@ -91,16 +114,40 @@ export class CustomTimeRangeSelectionComponent implements OnInit {
             newSelection.start,
             newSelection.end,
         );
-        this.dateSelectionComplete = this.selectionModel.isComplete();
         this.updateDateStrings();
+        const daysDiff = differenceInDays(newSelection.end, newSelection.start);
+        if (this.selectionModel.isComplete()) {
+            if (this.maxDayRange === 0 || daysDiff + 1 <= this.maxDayRange) {
+                this.dateSelectionComplete = true;
+                if (!this.enableTimeChange) {
+                    this.saveSelection();
+                }
+            } else {
+                this.maxDateRangeError = true;
+                this.dateSelectionComplete = false;
+            }
+        }
     }
 
     saveSelection(): void {
-        this.updateDateTime(this.currentDateRange.start, this.currentStartTime);
-        this.updateDateTime(this.currentDateRange.end, this.currentEndTime);
-        this.timeSettings.startTime = this.currentDateRange.start.getTime();
-        this.timeSettings.endTime = this.currentDateRange.end.getTime();
-        this.timeSettings.timeSelectionId = TimeSelectionId.CUSTOM;
+        if (this.enableTimeChange === true) {
+            this.updateDateTime(
+                this.currentDateRange.start,
+                this.currentStartTime,
+            );
+            this.updateDateTime(this.currentDateRange.end, this.currentEndTime);
+            this.timeSettings.startTime = this.currentDateRange.start.getTime();
+            this.timeSettings.endTime = this.currentDateRange.end.getTime();
+        } else {
+            this.timeSettings.startTime = startOfDay(
+                this.currentDateRange.start,
+            ).getTime();
+            this.timeSettings.endTime = endOfDay(
+                this.currentDateRange.end,
+            ).getTime();
+        }
+
+        this.timeSettings.timeSelectionId = TimeSelectionConstants.CUSTOM;
         this.timeSettingsEmitter.emit(this.timeSettings);
     }
 
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
similarity index 84%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
index e53550aa43..2bfda05f10 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.html
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.html
@@ -16,11 +16,13 @@
   ~
   -->
 
-<div class="menu-content" (click)="$event.stopPropagation()">
+<div class="menu-content" (click)="$event.stopPropagation()" *ngIf="labels">
     <div fxLayout="column" fxLayoutGap="10px">
         <div fxLayout="row" fxFlex="100" fxLayoutGap="10px">
             <div fxLayout="column" fxFlex="50" fxLayoutGap="10px">
-                <div class="filter-header">Quick selection</div>
+                <div class="filter-header">
+                    {{ labels.quickSelectionLabel }}
+                </div>
                 <div fxLayout="column" fxLayoutGap="10px" fxFlex="100">
                     <div *ngFor="let quickSelection of quickSelections">
                         <span
@@ -39,11 +41,14 @@
                 </div>
             </div>
             <div fxLayout="column" fxFlex="50">
-                <div class="filter-header">Custom</div>
+                <div class="filter-header">{{ labels.customLabel }}</div>
                 <sp-custom-time-range-selection
                     #timeRangeSelection
                     [timeSettings]="timeSettings"
+                    [labels]="labels"
                     (timeSettingsEmitter)="timeSettingsEmitter.emit($event)"
+                    [enableTimeChange]="enableTimeChange"
+                    [maxDayRange]="maxDayRange"
                     class="w-100"
                 >
                     <ng-content> </ng-content>
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.scss b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.scss
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.scss
diff --git a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
similarity index 90%
rename from ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts
rename to ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
index a24958bb31..a2748d9a47 100644
--- a/ui/src/app/data-explorer/components/time-selector/time-selector-menu/time-selector-menu.component.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector-menu/time-selector-menu.component.ts
@@ -30,6 +30,7 @@ import {
 } from '@streampipes/platform-services';
 import { TimeSelectionService } from '../../../services/time-selection.service';
 import { CustomTimeRangeSelectionComponent } from './custom-time-range-selection/custom-time-range-selection.component';
+import { TimeSelectorLabel } from '../time-selector.model';
 
 @Component({
     selector: 'sp-time-selector-menu',
@@ -40,20 +41,28 @@ export class TimeRangeSelectorMenuComponent implements OnInit {
     @Input()
     timeSettings: TimeSettings;
 
+    @Input()
+    labels: TimeSelectorLabel;
+
+    @Input()
+    enableTimeChange: boolean;
+
+    @Input()
+    maxDayRange: number;
+
     @Output()
     timeSettingsEmitter: EventEmitter<TimeSettings> =
         new EventEmitter<TimeSettings>();
 
-    quickSelections: QuickTimeSelection[] = [];
+    @Input()
+    quickSelections: QuickTimeSelection[];
 
     @ViewChild('timeRangeSelection')
     timeRangeSelection: CustomTimeRangeSelectionComponent;
 
     constructor(private timeSelectionService: TimeSelectionService) {}
 
-    ngOnInit(): void {
-        this.quickSelections = this.timeSelectionService.quickTimeSelections;
-    }
+    ngOnInit(): void {}
 
     applyQuickSelection(quickSelection: QuickTimeSelection): void {
         const selectedDateRange =
diff --git a/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts
new file mode 100644
index 0000000000..7905f9ff09
--- /dev/null
+++ b/ui/projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 TimeSelectorLabel {
+    quickSelectionLabel: string;
+    customLabel: string;
+    maxDayRangeErrorLabel: string;
+    timeRangeSelectorTooltip: string;
+}
diff --git a/ui/src/app/data-explorer/services/time-selection.service.ts b/ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
similarity index 59%
rename from ui/src/app/data-explorer/services/time-selection.service.ts
rename to ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
index 5c55e7756a..bc23977e7f 100644
--- a/ui/src/app/data-explorer/services/time-selection.service.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/services/time-selection.service.ts
@@ -21,7 +21,7 @@ import { Subject } from 'rxjs';
 import {
     DateRange,
     QuickTimeSelection,
-    TimeSelectionId,
+    TimeSelectionConstants,
     TimeSettings,
     WidgetTimeSettings,
 } from '@streampipes/platform-services';
@@ -38,82 +38,91 @@ import {
     subWeeks,
     subYears,
 } from 'date-fns';
+import { TimeSelectorLabel } from '../components/time-selector/time-selector.model';
 
 @Injectable({ providedIn: 'root' })
 export class TimeSelectionService {
-    legacyMappings: Record<number, TimeSelectionId> = {
-        15: TimeSelectionId.LAST_15_MINUTES,
-        60: TimeSelectionId.LAST_HOUR,
-        1440: TimeSelectionId.LAST_DAY,
-        10080: TimeSelectionId.LAST_WEEK,
-        43200: TimeSelectionId.LAST_MONTH,
-        525600: TimeSelectionId.LAST_YEAR,
+    legacyMappings: Record<number, string> = {
+        15: TimeSelectionConstants.LAST_15_MINUTES,
+        60: TimeSelectionConstants.LAST_HOUR,
+        1440: TimeSelectionConstants.LAST_DAY,
+        10080: TimeSelectionConstants.LAST_WEEK,
+        43200: TimeSelectionConstants.LAST_MONTH,
+        525600: TimeSelectionConstants.LAST_YEAR,
     };
 
-    quickTimeSelections: QuickTimeSelection[] = [
+    defaultLabels: TimeSelectorLabel = {
+        quickSelectionLabel: 'Quick Selection',
+        customLabel: 'Custom',
+        maxDayRangeErrorLabel:
+            'Maximum of ${this.maxDayRange} days can be displayed. Please select a smaller range.',
+        timeRangeSelectorTooltip: 'Modify time range',
+    };
+
+    defaultQuickTimeSelections: QuickTimeSelection[] = [
         {
             label: 'Last 15 min',
-            timeSelectionId: TimeSelectionId.LAST_15_MINUTES,
+            timeSelectionId: TimeSelectionConstants.LAST_15_MINUTES,
             startTime: now => subMinutes(now, 15),
             endTime: now => now,
         },
         {
             label: 'Last 1 hour',
-            timeSelectionId: TimeSelectionId.LAST_HOUR,
+            timeSelectionId: TimeSelectionConstants.LAST_HOUR,
             startTime: now => subHours(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 day',
-            timeSelectionId: TimeSelectionId.LAST_DAY,
+            timeSelectionId: TimeSelectionConstants.LAST_DAY,
             startTime: now => subDays(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 week',
-            timeSelectionId: TimeSelectionId.LAST_WEEK,
+            timeSelectionId: TimeSelectionConstants.LAST_WEEK,
             startTime: now => subWeeks(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 month',
-            timeSelectionId: TimeSelectionId.LAST_MONTH,
+            timeSelectionId: TimeSelectionConstants.LAST_MONTH,
             startTime: now => subMonths(now, 1),
             endTime: now => now,
         },
         {
             label: 'Last 1 year',
-            timeSelectionId: TimeSelectionId.LAST_YEAR,
+            timeSelectionId: TimeSelectionConstants.LAST_YEAR,
             startTime: now => subYears(now, 1),
             endTime: now => now,
         },
         {
             label: 'Current day',
-            timeSelectionId: TimeSelectionId.CURRENT_DAY,
+            timeSelectionId: TimeSelectionConstants.CURRENT_DAY,
             startTime: now => startOfDay(now),
             endTime: now => now,
         },
         {
             label: 'Current hour',
-            timeSelectionId: TimeSelectionId.CURRENT_HOUR,
+            timeSelectionId: TimeSelectionConstants.CURRENT_HOUR,
             startTime: now => startOfHour(now),
             endTime: now => now,
         },
         {
             label: 'Current week',
-            timeSelectionId: TimeSelectionId.CURRENT_WEEK,
+            timeSelectionId: TimeSelectionConstants.CURRENT_WEEK,
             startTime: now => startOfWeek(now),
             endTime: now => now,
         },
         {
             label: 'Current month',
-            timeSelectionId: TimeSelectionId.CURRENT_MONTH,
+            timeSelectionId: TimeSelectionConstants.CURRENT_MONTH,
             startTime: now => startOfMonth(now),
             endTime: now => now,
         },
         {
             label: 'Current year',
-            timeSelectionId: TimeSelectionId.CURRENT_YEAR,
+            timeSelectionId: TimeSelectionConstants.CURRENT_YEAR,
             startTime: now => startOfYear(now),
             endTime: now => now,
         },
@@ -129,32 +138,55 @@ export class TimeSelectionService {
 
     public getDefaultTimeSettings(): TimeSettings {
         return this.getTimeSettings(
-            TimeSelectionId.LAST_15_MINUTES,
+            this.defaultQuickTimeSelections,
+            this.defaultQuickTimeSelections[0].timeSelectionId,
             new Date(),
         );
     }
 
     public getTimeSettings(
-        timeSelectionId: TimeSelectionId,
+        quickTimeSelections: QuickTimeSelection[],
+        timeSelectionId: string,
         now: Date,
     ): TimeSettings {
-        const selection = this.getTimeSelection(timeSelectionId);
+        const selection = this.getTimeSelection(
+            quickTimeSelections,
+            timeSelectionId,
+        );
         return {
             startTime: selection.startTime(now).getTime(),
             endTime: selection.endTime(now).getTime(),
             dynamicSelection: -1,
-            timeSelectionId: timeSelectionId,
+            timeSelectionId: selection.timeSelectionId,
         };
     }
 
-    public updateTimeSettings(timeSettings: TimeSettings, now: Date): void {
+    public updateTimeSettings(
+        quickTimeSelections: QuickTimeSelection[],
+        timeSettings: TimeSettings,
+        now: Date,
+    ): void {
         // for backwards compatibility
         if (timeSettings.timeSelectionId === undefined) {
             timeSettings.timeSelectionId =
                 this.findLegacyTimeSelectionId(timeSettings);
+        } else if (typeof timeSettings.timeSelectionId === 'number') {
+            timeSettings.timeSelectionId =
+                TimeSelectionConstants.getLegacyTimeSelectionID(
+                    timeSettings.timeSelectionId,
+                );
         }
-        if (timeSettings.timeSelectionId !== TimeSelectionId.CUSTOM) {
+        if (timeSettings.timeSelectionId !== TimeSelectionConstants.CUSTOM) {
+            if (
+                quickTimeSelections.find(
+                    s => s.timeSelectionId === timeSettings.timeSelectionId,
+                ) === undefined
+            ) {
+                timeSettings.timeSelectionId =
+                    quickTimeSelections[0].timeSelectionId;
+            }
             const updatedTimeSettings = this.getTimeSettings(
+                quickTimeSelections,
                 timeSettings.timeSelectionId,
                 now,
             );
@@ -163,19 +195,22 @@ export class TimeSelectionService {
         }
     }
 
-    public getTimeSelection(timeSelectionId: TimeSelectionId) {
-        return this.quickTimeSelections.find(
-            s => s.timeSelectionId === timeSelectionId,
+    public getTimeSelection(
+        quickTimeSelections: QuickTimeSelection[],
+        timeSelectionId: string,
+    ): QuickTimeSelection {
+        return (
+            quickTimeSelections.find(
+                s => s.timeSelectionId === timeSelectionId,
+            ) || quickTimeSelections[0]
         );
     }
 
-    private findLegacyTimeSelectionId(
-        timeSettings: TimeSettings,
-    ): TimeSelectionId {
+    private findLegacyTimeSelectionId(timeSettings: TimeSettings): string {
         if (timeSettings.dynamicSelection in this.legacyMappings) {
             return this.legacyMappings[timeSettings.dynamicSelection];
         } else {
-            return TimeSelectionId.CUSTOM;
+            return TimeSelectionConstants.CUSTOM;
         }
     }
 
diff --git a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
index d5b90cf68d..cdda6df485 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
@@ -17,7 +17,13 @@
  */
 
 import { NgModule } from '@angular/core';
+import {
+    DefaultMatCalendarRangeStrategy,
+    MatDatepickerModule,
+    MatRangeDateSelectionModel,
+} from '@angular/material/datepicker';
 import { ConfirmDialogComponent } from './dialog/confirm-dialog/confirm-dialog.component';
+import { MatCardModule } from '@angular/material/card';
 import { PanelDialogComponent } from './dialog/panel-dialog/panel-dialog.component';
 import { StandardDialogComponent } from './dialog/standard-dialog/standard-dialog.component';
 import { CommonModule } from '@angular/common';
@@ -55,6 +61,10 @@ import { AssetBrowserFilterTypeComponent } from './components/asset-browser/asse
 import { AssetBrowserHierarchyComponent } from './components/asset-browser/asset-browser-hierarchy/asset-browser-hierarchy.component';
 import { AssetBrowserNodeComponent } from './components/asset-browser/asset-browser-hierarchy/asset-browser-node/asset-browser-node.component';
 import { AssetBrowserNodeInfoComponent } from './components/asset-browser/asset-browser-hierarchy/asset-browser-node/asset-browser-node-info/asset-browser-node-info.component';
+import { TimeRangeSelectorComponent } from './components/time-selector/time-range-selector.component';
+import { TimeRangeSelectorMenuComponent } from './components/time-selector/time-selector-menu/time-selector-menu.component';
+import { CustomTimeRangeSelectionComponent } from './components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
+import { DataExplorerRefreshIntervalSettingsComponent } from './components/time-selector/refresh-interval-settings/refresh-interval-settings.component';
 import { MatSelectModule } from '@angular/material/select';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatMenuModule } from '@angular/material/menu';
@@ -74,6 +84,7 @@ import { MatTreeModule } from '@angular/material/tree';
         AssetBrowserNodeInfoComponent,
         AssetBrowserToolbarComponent,
         ConfirmDialogComponent,
+        CustomTimeRangeSelectionComponent,
         PanelDialogComponent,
         StandardDialogComponent,
         SpBasicFieldDescriptionComponent,
@@ -88,6 +99,9 @@ import { MatTreeModule } from '@angular/material/tree';
         SpTableComponent,
         SplitSectionComponent,
         SpWarningBoxComponent,
+        TimeRangeSelectorComponent,
+        TimeRangeSelectorMenuComponent,
+        DataExplorerRefreshIntervalSettingsComponent,
     ],
     imports: [
         CommonModule,
@@ -102,6 +116,8 @@ import { MatTreeModule } from '@angular/material/tree';
         MatTabsModule,
         MatTooltipModule,
         MatTreeModule,
+        MatDatepickerModule,
+        MatCardModule,
         PortalModule,
         OverlayModule,
         MatDialogModule,
@@ -109,6 +125,7 @@ import { MatTreeModule } from '@angular/material/tree';
         MatPaginator,
         MatSort,
     ],
+    providers: [DefaultMatCalendarRangeStrategy, MatRangeDateSelectionModel],
     exports: [
         AssetBrowserComponent,
         ConfirmDialogComponent,
@@ -126,6 +143,9 @@ import { MatTreeModule } from '@angular/material/tree';
         SpTableComponent,
         SplitSectionComponent,
         SpWarningBoxComponent,
+        CustomTimeRangeSelectionComponent,
+        TimeRangeSelectorComponent,
+        TimeRangeSelectorMenuComponent,
     ],
 })
 export class SharedUiModule {}
diff --git a/ui/projects/streampipes/shared-ui/src/public-api.ts b/ui/projects/streampipes/shared-ui/src/public-api.ts
index a923f5abbc..40fe20fa0a 100644
--- a/ui/projects/streampipes/shared-ui/src/public-api.ts
+++ b/ui/projects/streampipes/shared-ui/src/public-api.ts
@@ -39,6 +39,9 @@ export * from './lib/components/sp-exception-message/exception-details/exception
 export * from './lib/components/sp-label/sp-label.component';
 export * from './lib/components/sp-table/sp-table.component';
 export * from './lib/components/warning-box/warning-box.component';
+export * from './lib/components/time-selector/time-range-selector.component';
+export * from './lib/components/time-selector/time-selector-menu/time-selector-menu.component';
+export * from './lib/components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
 
 export * from './lib/models/sp-navigation.model';
 
@@ -47,4 +50,5 @@ export * from './lib/services/jwt-token-storage.service';
 export * from './lib/services/current-user.service';
 export * from './lib/services/echarts-toolbox.service';
 export * from './lib/services/colorization.service';
+export * from './lib/services/time-selection.service';
 export * from './lib/components/asset-browser/asset-browser.service';
diff --git a/ui/projects/streampipes/shared-ui/tsconfig.lib.json b/ui/projects/streampipes/shared-ui/tsconfig.lib.json
index e2c590dbbf..0b34959311 100644
--- a/ui/projects/streampipes/shared-ui/tsconfig.lib.json
+++ b/ui/projects/streampipes/shared-ui/tsconfig.lib.json
@@ -8,7 +8,7 @@
     "declarationMap": true,
     "inlineSources": true,
     "types": [],
-    "lib": ["dom", "es2018"]
+    "lib": ["dom", "es2020"]
   },
   "exclude": ["src/test.ts", "**/*.spec.ts"]
 }
diff --git a/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.html b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.html
index 8a05afabd3..6f553c63e3 100644
--- a/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.html
+++ b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.html
@@ -18,6 +18,7 @@
 
 <div fxFlex="100" *ngIf="compactAdapter" class="mt-10">
     <sp-configuration-code-panel
+        *ngIf="compactAdapter"
         [configuration]="compactAdapter"
         [maxHeight]="maxHeight"
     >
diff --git a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
index f7ff5b8c7b..d4eecdd6a7 100644
--- a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
+++ b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
@@ -150,6 +150,7 @@
             optionTitle="Show code"
             optionDescription="Show code to programmatically deploy this adapter over the API"
             optionIcon="code"
+            dataCy="show-code-checkbox"
             (optionSelectedEmitter)="showCode = $event"
         >
             @if (showCode) {
diff --git a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
index 598dae37ae..17cc830821 100644
--- a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
+++ b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
@@ -24,6 +24,7 @@ import {
     CompactPipeline,
     CompactPipelineElement,
     ErrorMessage,
+    Message,
     PipelineOperationStatus,
     PipelineTemplateService,
     PipelineUpdateInfo,
@@ -112,16 +113,22 @@ export class AdapterStartedDialog implements OnInit {
     updateAdapter(): void {
         this.loadingText = `Updating adapter ${this.adapter.name}`;
         this.loading = true;
-        this.adapterService.updateAdapter(this.adapter).subscribe(
-            res => {
-                this.onAdapterReady(
-                    `Adapter ${this.adapter.name} was successfully updated and is available in the pipeline editor.`,
-                );
+        this.adapterService.updateAdapter(this.adapter).subscribe({
+            next: status => {
+                if (status.success) {
+                    this.onAdapterReady(
+                        `Adapter ${this.adapter.name} was successfully updated and is available in the pipeline editor.`,
+                    );
+                } else {
+                    const errorLogMessage = this.getErrorLogMessage(status);
+
+                    this.onAdapterFailure(errorLogMessage);
+                }
             },
-            error => {
+            error: error => {
                 this.onAdapterFailure(error.error);
             },
-        );
+        });
     }
 
     addAdapter() {
@@ -137,16 +144,8 @@ export class AdapterStartedDialog implements OnInit {
                         this.startAdapter(adapterElementId, true);
                     }
                 } else {
-                    const errorMsg: SpLogMessage = {
-                        cause:
-                            status.notifications.length > 0
-                                ? status.notifications[0].title
-                                : 'Unknown Error',
-                        detail: '',
-                        fullStackTrace: '',
-                        level: 'ERROR',
-                        title: 'Unknown Error',
-                    };
+                    const errorMsg: SpLogMessage =
+                        this.getErrorLogMessage(status);
 
                     this.onAdapterFailure(errorMsg);
                 }
@@ -157,6 +156,20 @@ export class AdapterStartedDialog implements OnInit {
         );
     }
 
+    private getErrorLogMessage(status: Message): SpLogMessage {
+        const notification = status.notifications[0] || {
+            title: 'Unknown Error',
+            description: '',
+        };
+        return {
+            cause: notification.title,
+            detail: '',
+            fullStackTrace: notification.description,
+            level: 'ERROR',
+            title: 'Unknown Error',
+        };
+    }
+
     startAdapter(adapterElementId: string, showPreview = false) {
         const successMessage =
             'Your new data stream is now available in the pipeline editor.';
@@ -265,6 +278,7 @@ export class AdapterStartedDialog implements OnInit {
             configuration: undefined,
             id: adapter.correspondingDataStreamElementId,
             connectedTo: undefined,
+            output: undefined,
         });
         return template;
     }
diff --git a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.html b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.html
index 083d9291c7..7e232c3089 100644
--- a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.html
+++ b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.html
@@ -16,19 +16,47 @@
   ~
   -->
 
-<mat-tab-group color="accent" [mat-stretch-tabs]="false">
+<mat-tab-group
+    color="accent"
+    [mat-stretch-tabs]="false"
+    (selectedTabChange)="onTabChanged($event)"
+>
     <mat-tab label="YAML">
+        <div class="container-copy-button-container">
+            <div class="copy-button-container">
+                <button
+                    mat-icon-button
+                    [cdkCopyToClipboard]="currentConfiguration"
+                    matTooltip="Copy"
+                >
+                    <mat-icon>content_copy</mat-icon>
+                </button>
+            </div>
+        </div>
         <pre
             [innerHTML]="configuration | yamlpretty"
             class="preview-text"
             [ngStyle]="{ maxHeight: maxHeight }"
+            data-cy="yaml-configuration"
         ></pre>
     </mat-tab>
     <mat-tab label="JSON">
+        <div class="container-copy-button-container">
+            <div class="copy-button-container">
+                <button
+                    mat-icon-button
+                    [cdkCopyToClipboard]="currentConfiguration"
+                    matTooltip="Copy"
+                >
+                    <mat-icon>content_copy</mat-icon>
+                </button>
+            </div>
+        </div>
         <pre
             [innerHTML]="configuration | jsonpretty"
             class="preview-text"
             [ngStyle]="{ maxHeight: maxHeight }"
+            data-cy="json-configuration"
         ></pre>
     </mat-tab>
 </mat-tab-group>
diff --git a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.scss b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.scss
index c02ba8acc6..4025845c82 100644
--- a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.scss
+++ b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.scss
@@ -28,3 +28,17 @@
     overflow-y: scroll;
     white-space: pre-wrap;
 }
+
+.mat-mdc-icon-button {
+    color: #fff;
+}
+
+.copy-button-container {
+    position: absolute;
+    right: 20px;
+    top: 20px;
+}
+
+.container-copy-button-container {
+    position: relative;
+}
diff --git a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.ts b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.ts
index bf8deb6418..9c3a88a970 100644
--- a/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.ts
+++ b/ui/src/app/core-ui/configuration-code-panel/configuration-code-panel.component.ts
@@ -17,16 +17,37 @@
  */
 
 import { Component, Input, OnInit } from '@angular/core';
+import { stringify } from 'yaml';
+import { MatTabChangeEvent } from '@angular/material/tabs';
 
 @Component({
     selector: 'sp-configuration-code-panel',
     templateUrl: './configuration-code-panel.component.html',
     styleUrls: ['./configuration-code-panel.component.scss'],
 })
-export class ConfigurationCodePanelComponent {
+export class ConfigurationCodePanelComponent implements OnInit {
     @Input()
     configuration: any;
 
     @Input()
     maxHeight = '300px';
+
+    configurationYaml: string;
+    configurationJson: string;
+
+    currentConfiguration: string;
+
+    ngOnInit() {
+        this.configurationYaml = stringify(this.configuration);
+        this.configurationJson = JSON.stringify(this.configuration);
+        this.currentConfiguration = this.configurationYaml;
+    }
+
+    onTabChanged(event: MatTabChangeEvent) {
+        if (event.index === 0) {
+            this.currentConfiguration = this.configurationYaml;
+        } else {
+            this.currentConfiguration = this.configurationJson;
+        }
+    }
 }
diff --git a/ui/src/app/core-ui/core-ui.module.ts b/ui/src/app/core-ui/core-ui.module.ts
index 5a8815dce0..bd0c996d6e 100644
--- a/ui/src/app/core-ui/core-ui.module.ts
+++ b/ui/src/app/core-ui/core-ui.module.ts
@@ -26,6 +26,7 @@ import { MatNativeDateModule } from '@angular/material/core';
 import { MatDatepickerModule } from '@angular/material/datepicker';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 import { MatSnackBarModule } from '@angular/material/snack-bar';
+import { ClipboardModule } from '@angular/cdk/clipboard';
 
 import { MatChipsModule } from '@angular/material/chips';
 import { MatSliderModule } from '@angular/material/slider';
@@ -119,6 +120,7 @@ import { PipelineElementTemplateConfigItemComponent } from './pipeline-element-t
 import { ConfigurationCodePanelComponent } from './configuration-code-panel/configuration-code-panel.component';
 import { JsonPrettyPrintPipe } from './pipes/json-pretty-print.pipe';
 import { YamlPrettyPrintPipe } from './pipes/yaml-pretty-print.pipe';
+import { TopicsComponent } from './topics/topics.component';
 
 @NgModule({
     imports: [
@@ -151,6 +153,7 @@ import { YamlPrettyPrintPipe } from './pipes/yaml-pretty-print.pipe';
         ReactiveFormsModule,
         FormsModule,
         CdkTableModule,
+        ClipboardModule,
         MatAutocompleteModule,
         MatSnackBarModule,
         MatProgressSpinnerModule,
@@ -182,6 +185,7 @@ import { YamlPrettyPrintPipe } from './pipes/yaml-pretty-print.pipe';
         PipelineElementRuntimeInfoComponent,
         PipelineElementDocumentationComponent,
         HelpComponent,
+        TopicsComponent,
         StaticAnyInputComponent,
         StaticPropertyComponent,
         StaticFreeInputComponent,
@@ -236,6 +240,7 @@ import { YamlPrettyPrintPipe } from './pipes/yaml-pretty-print.pipe';
         PipelineElementRuntimeInfoComponent,
         PipelineElementDocumentationComponent,
         HelpComponent,
+        TopicsComponent,
         StaticAnyInputComponent,
         StaticPropertyComponent,
         StaticFreeInputComponent,
diff --git a/ui/src/app/core-ui/help/help.component.html b/ui/src/app/core-ui/help/help.component.html
index ecc82fc6a8..fcdfbe7332 100644
--- a/ui/src/app/core-ui/help/help.component.html
+++ b/ui/src/app/core-ui/help/help.component.html
@@ -17,18 +17,28 @@
   -->
 
 <div class="sp-dialog-container">
-    <div class="sp-dialog-content p-15">
-        <h4>{{ pipelineElement.name }}</h4>
-        <p>
-            {{ pipelineElement.description }}
-        </p>
-
+    <div class="sp-dialog-content p-15" fxLayout="column">
+        <div fxLayout="row" fxFlex="100">
+            <div fxLayout="column" fxFlex>
+                <h4>{{ pipelineElement.name }}</h4>
+                <small>
+                    {{ pipelineElement.description }}
+                </small>
+            </div>
+            <div class="element-id" fxLayoutAlign="end start">
+                <span>ID</span>&nbsp;<b>{{
+                    isDataStream
+                        ? pipelineElement.elementId
+                        : pipelineElement.appId
+                }}</b>
+            </div>
+        </div>
         <mat-tab-group
             color="accent"
             [selectedIndex]="selectedTabIndex"
             (selectedIndexChange)="selectedTabIndex = $event"
         >
-            <mat-tab *ngFor="let tab of tabs" label="{{ tab }}"> </mat-tab>
+            <mat-tab *ngFor="let tab of tabs" label="{{ tab }}"></mat-tab>
         </mat-tab-group>
 
         <sp-pipeline-element-runtime-info
diff --git a/ui/src/app/core-ui/help/help.component.scss b/ui/src/app/core-ui/help/help.component.scss
index ecf2724830..c077f68f35 100644
--- a/ui/src/app/core-ui/help/help.component.scss
+++ b/ui/src/app/core-ui/help/help.component.scss
@@ -17,3 +17,13 @@
  */
 
 @import '../../../scss/sp/sp-dialog.scss';
+
+.element-id {
+    border-radius: 5px;
+    margin-right: 10px;
+    margin-top: 5px;
+    margin-bottom: 5px;
+    font-size: small;
+    display: inline-block;
+    padding: 5px;
+}
diff --git a/ui/src/app/core-ui/help/help.component.ts b/ui/src/app/core-ui/help/help.component.ts
index 517a2c927d..fcfc5b8d2d 100644
--- a/ui/src/app/core-ui/help/help.component.ts
+++ b/ui/src/app/core-ui/help/help.component.ts
@@ -34,12 +34,14 @@ export class HelpComponent implements OnInit {
 
     @Input()
     pipelineElement: PipelineElementUnion;
+    isDataStream: boolean;
 
     constructor(private dialogRef: DialogRef<HelpComponent>) {}
 
     ngOnInit() {
         if (this.pipelineElement instanceof SpDataStream) {
             this.tabs = this.availableTabs;
+            this.isDataStream = true;
         } else {
             this.tabs.push(this.availableTabs[1]);
             this.selectedTabIndex = 1;
@@ -51,4 +53,6 @@ export class HelpComponent implements OnInit {
             this.dialogRef.close();
         });
     }
+
+    protected readonly SpDataStream = SpDataStream;
 }
diff --git a/ui/src/app/core-ui/pipeline-element-runtime-info/live-preview-table/live-preview-table.component.html b/ui/src/app/core-ui/pipeline-element-runtime-info/live-preview-table/live-preview-table.component.html
index ffaf3bd5b2..ceb6851ab4 100644
--- a/ui/src/app/core-ui/pipeline-element-runtime-info/live-preview-table/live-preview-table.component.html
+++ b/ui/src/app/core-ui/pipeline-element-runtime-info/live-preview-table/live-preview-table.component.html
@@ -57,7 +57,12 @@
             <th mat-header-cell *matHeaderCellDef><strong>Value</strong></th>
             <td mat-cell *matCellDef="let element" style="width: 200px">
                 @if (element.value === undefined) {
-                    <div class="value no-data">no data</div>
+                    <div
+                        data-cy="live-preview-table-no-data"
+                        class="value no-data"
+                    >
+                        no data
+                    </div>
                 } @else {
                     <ng-container *ngIf="element.isImage">
                         <img
@@ -75,7 +80,9 @@
                     </ng-container>
                     <ng-container *ngIf="element.hasNoDomainProperty">
                         <div
-                            data-cy="live-preview-table-value"
+                            [attr.data-cy]="
+                                'live-preview-value-' + element.runtimeName
+                            "
                             class="value"
                             [class.value-changed]="element.valueChanged"
                         >
diff --git a/ui/src/app/core-ui/pipes/yaml-pretty-print.pipe.ts b/ui/src/app/core-ui/pipes/yaml-pretty-print.pipe.ts
index 88f8b4b459..233bb6f11d 100644
--- a/ui/src/app/core-ui/pipes/yaml-pretty-print.pipe.ts
+++ b/ui/src/app/core-ui/pipes/yaml-pretty-print.pipe.ts
@@ -17,7 +17,7 @@
  */
 
 import { Injectable, Pipe, PipeTransform } from '@angular/core';
-import { parse, stringify } from 'yaml';
+import { stringify } from 'yaml';
 
 @Pipe({
     name: 'yamlpretty',
diff --git a/ui/src/app/core-ui/static-properties/static-one-of-input/static-one-of-input.component.html b/ui/src/app/core-ui/static-properties/static-one-of-input/static-one-of-input.component.html
index 5e56f24d4d..dc1e6742fe 100644
--- a/ui/src/app/core-ui/static-properties/static-one-of-input/static-one-of-input.component.html
+++ b/ui/src/app/core-ui/static-properties/static-one-of-input/static-one-of-input.component.html
@@ -17,47 +17,54 @@
   -->
 
 <div id="formWrapper" fxFlex="100" fxLayout="column">
-    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
-        <div fxFlex fxLayout="row">
-            <div fxLayout="column" style="margin-left: 10px">
-                <mat-radio-group class="radio-group" color="accent">
-                    <mat-radio-button
+    @if (
+        !staticProperty.horizontalRendering && staticProperty.options.length < 5
+    ) {
+        <div fxLayout="column">
+            <div fxFlex fxLayout="row">
+                <div fxLayout="column" style="margin-left: 10px">
+                    <mat-radio-group class="radio-group" color="accent">
+                        <mat-radio-button
+                            *ngFor="let option of staticProperty.options"
+                            style="margin-top: -10px"
+                            [value]="option"
+                            (click)="select(option.elementId)"
+                            [checked]="option.selected"
+                            [attr.data-cy]="
+                                staticProperty.internalName
+                                    .split(' ')
+                                    .join('_')
+                                    .toLowerCase() +
+                                '-' +
+                                option.name.split(' ').join('_').toLowerCase()
+                            "
+                        >
+                            <label style="font-weight: normal">
+                                {{ option.name }}
+                            </label>
+                        </mat-radio-button>
+                    </mat-radio-group>
+                </div>
+            </div>
+        </div>
+    } @else {
+        <div>
+            <mat-form-field style="width: 100%" color="accent">
+                <mat-select
+                    [(value)]="selectedOption"
+                    [attr.data-cy]="fieldName"
+                >
+                    <mat-option
                         *ngFor="let option of staticProperty.options"
-                        style="margin-top: -10px"
-                        [value]="option"
+                        [value]="option.elementId"
                         (click)="select(option.elementId)"
-                        [checked]="option.selected"
-                        [attr.data-cy]="
-                            staticProperty.internalName
-                                .split(' ')
-                                .join('_')
-                                .toLowerCase() +
-                            '-' +
-                            option.name.split(' ').join('_').toLowerCase()
-                        "
                     >
                         <label style="font-weight: normal">
                             {{ option.name }}
                         </label>
-                    </mat-radio-button>
-                </mat-radio-group>
-            </div>
+                    </mat-option>
+                </mat-select>
+            </mat-form-field>
         </div>
-    </div>
-
-    <div *ngIf="staticProperty.horizontalRendering">
-        <mat-form-field style="width: 100%" color="accent">
-            <mat-select [(value)]="selectedOption" [attr.data-cy]="fieldName">
-                <mat-option
-                    *ngFor="let option of staticProperty.options"
-                    [value]="option.elementId"
-                    (click)="select(option.elementId)"
-                >
-                    <label style="font-weight: normal">
-                        {{ option.name }}
-                    </label>
-                </mat-option>
-            </mat-select>
-        </mat-form-field>
-    </div>
+    }
 </div>
diff --git a/ui/src/app/core-ui/topics/topics.component.html b/ui/src/app/core-ui/topics/topics.component.html
new file mode 100644
index 0000000000..73c5be895c
--- /dev/null
+++ b/ui/src/app/core-ui/topics/topics.component.html
@@ -0,0 +1,213 @@
+<!--
+  ~ 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" fxLayout="column">
+        <div fxLayout="row" fxFlex="100">
+            <div fxLayout="column" fxFlex>
+                <h4>{{ pipelineElement?.name }}</h4>
+                <small>{{ pipelineElement?.description }}</small>
+            </div>
+            <div class="element-id" fxLayoutAlign="end start">
+                <span>ID</span>&nbsp;
+                <b>{{
+                    isDataStream
+                        ? pipelineElement?.elementId
+                        : pipelineElement?.appId
+                }}</b>
+            </div>
+        </div>
+
+        <mat-tab-group
+            color="accent"
+            [selectedIndex]="selectedTabIndex"
+            (selectedIndexChange)="selectedTabIndex = $event"
+        >
+            <mat-tab *ngFor="let tab of tabs" [label]="tab"></mat-tab>
+        </mat-tab-group>
+
+        <div *ngIf="selectedTabIndex === 0">
+            <ng-container *ngIf="isSpDataStream()">
+                <table
+                    mat-table
+                    [dataSource]="
+                        pipelineElement?.eventGrounding?.transportProtocols
+                    "
+                >
+                    <ng-container matColumnDef="outputTopics">
+                        <th mat-header-cell *matHeaderCellDef>
+                            <strong>Output Topics</strong>
+                        </th>
+                        <td mat-cell *matCellDef="let element">
+                            <div
+                                fxLayout="row"
+                                fxLayoutAlign="space-between center"
+                            >
+                                <span>{{
+                                    element?.topicDefinition?.actualTopicName
+                                }}</span>
+                                <button
+                                    mat-icon-button
+                                    [cdkCopyToClipboard]="
+                                        element.topicDefinition.actualTopicName
+                                    "
+                                    matTooltip="Copy"
+                                >
+                                    <mat-icon>content_copy</mat-icon>
+                                </button>
+                            </div>
+                        </td>
+                    </ng-container>
+                    <tr mat-header-row *matHeaderRowDef="['outputTopics']"></tr>
+                    <tr
+                        mat-row
+                        *matRowDef="let row; columns: ['outputTopics']"
+                    ></tr>
+                </table>
+            </ng-container>
+
+            <ng-container *ngIf="isDataProcessorInvocation()">
+                <table mat-table [dataSource]="pipelineElement?.inputStreams">
+                    <ng-container matColumnDef="inputTopics">
+                        <th mat-header-cell *matHeaderCellDef>
+                            <strong>Input Topics</strong>
+                        </th>
+                        <td mat-cell *matCellDef="let element">
+                            <div
+                                fxLayout="row"
+                                fxLayoutAlign="space-between center"
+                            >
+                                <span>{{
+                                    element?.eventGrounding
+                                        ?.transportProtocols?.[0]
+                                        ?.topicDefinition?.actualTopicName
+                                }}</span>
+                                <button
+                                    mat-icon-button
+                                    [cdkCopyToClipboard]="
+                                        element?.eventGrounding
+                                            ?.transportProtocols?.[0]
+                                            ?.topicDefinition?.actualTopicName
+                                    "
+                                    matTooltip="Copy"
+                                >
+                                    <mat-icon>content_copy</mat-icon>
+                                </button>
+                            </div>
+                        </td>
+                    </ng-container>
+                    <tr mat-header-row *matHeaderRowDef="['inputTopics']"></tr>
+                    <tr
+                        mat-row
+                        *matRowDef="let row; columns: ['inputTopics']"
+                    ></tr>
+                </table>
+
+                <table
+                    mat-table
+                    [dataSource]="
+                        pipelineElement?.outputStream?.eventGrounding
+                            ?.transportProtocols
+                    "
+                >
+                    <ng-container matColumnDef="outputTopics">
+                        <th mat-header-cell *matHeaderCellDef>
+                            <strong>Output Topics</strong>
+                        </th>
+                        <td mat-cell *matCellDef="let element">
+                            <div
+                                fxLayout="row"
+                                fxLayoutAlign="space-between center"
+                            >
+                                <span>{{
+                                    element?.topicDefinition?.actualTopicName
+                                }}</span>
+                                <button
+                                    mat-icon-button
+                                    [cdkCopyToClipboard]="
+                                        element?.topicDefinition
+                                            ?.actualTopicName
+                                    "
+                                    matTooltip="Copy"
+                                >
+                                    <mat-icon>content_copy</mat-icon>
+                                </button>
+                            </div>
+                        </td>
+                    </ng-container>
+                    <tr mat-header-row *matHeaderRowDef="['outputTopics']"></tr>
+                    <tr
+                        mat-row
+                        *matRowDef="let row; columns: ['outputTopics']"
+                    ></tr>
+                </table>
+            </ng-container>
+
+            <ng-container *ngIf="isDataSinkInvocation()">
+                <table mat-table [dataSource]="pipelineElement?.inputStreams">
+                    <ng-container matColumnDef="inputTopics">
+                        <th mat-header-cell *matHeaderCellDef>
+                            <strong>Input Topics</strong>
+                        </th>
+                        <td mat-cell *matCellDef="let element">
+                            <div
+                                fxLayout="row"
+                                fxLayoutAlign="space-between center"
+                            >
+                                <span>{{
+                                    element?.eventGrounding
+                                        ?.transportProtocols?.[0]
+                                        ?.topicDefinition?.actualTopicName
+                                }}</span>
+                                <button
+                                    mat-icon-button
+                                    [cdkCopyToClipboard]="
+                                        element?.eventGrounding
+                                            ?.transportProtocols?.[0]
+                                            ?.topicDefinition?.actualTopicName
+                                    "
+                                    matTooltip="Copy"
+                                >
+                                    <mat-icon>content_copy</mat-icon>
+                                </button>
+                            </div>
+                        </td>
+                    </ng-container>
+                    <tr mat-header-row *matHeaderRowDef="['inputTopics']"></tr>
+                    <tr
+                        mat-row
+                        *matRowDef="let row; columns: ['inputTopics']"
+                    ></tr>
+                </table>
+            </ng-container>
+        </div>
+    </div>
+
+    <mat-divider></mat-divider>
+
+    <div class="sp-dialog-actions actions-align-right">
+        <button
+            mat-button
+            mat-raised-button
+            class="mat-basic"
+            (click)="close()"
+        >
+            Close
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/core-ui/topics/topics.component.scss b/ui/src/app/core-ui/topics/topics.component.scss
new file mode 100644
index 0000000000..c077f68f35
--- /dev/null
+++ b/ui/src/app/core-ui/topics/topics.component.scss
@@ -0,0 +1,29 @@
+/*
+ * 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-id {
+    border-radius: 5px;
+    margin-right: 10px;
+    margin-top: 5px;
+    margin-bottom: 5px;
+    font-size: small;
+    display: inline-block;
+    padding: 5px;
+}
diff --git a/ui/src/app/core-ui/topics/topics.component.ts b/ui/src/app/core-ui/topics/topics.component.ts
new file mode 100644
index 0000000000..2ce28d6dc7
--- /dev/null
+++ b/ui/src/app/core-ui/topics/topics.component.ts
@@ -0,0 +1,77 @@
+/*
+ * 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 {
+    DataProcessorInvocation,
+    DataSinkInvocation,
+    SpDataStream,
+} from '@streampipes/platform-services';
+import { DialogRef } from '@streampipes/shared-ui';
+import { PipelineElementUnion } from '../../editor/model/editor.model';
+
+@Component({
+    selector: 'sp-pipeline-element-topics',
+    templateUrl: './topics.component.html',
+    styleUrls: ['./topics.component.scss'],
+})
+export class TopicsComponent implements OnInit {
+    selectedTabIndex = 0;
+
+    availableTabs = ['Topics', 'Code'];
+    tabs: string[] = [];
+
+    @Input()
+    pipelineElement: PipelineElementUnion;
+    isDataStream: boolean;
+
+    constructor(private dialogRef: DialogRef<TopicsComponent>) {}
+
+    ngOnInit() {
+        if (
+            this.pipelineElement instanceof SpDataStream ||
+            this.pipelineElement instanceof DataProcessorInvocation ||
+            this.pipelineElement instanceof DataSinkInvocation
+        ) {
+            this.tabs = this.availableTabs;
+        } else {
+            this.tabs = [this.availableTabs[1]];
+            this.selectedTabIndex = 1;
+        }
+    }
+
+    isSpDataStream(): boolean {
+        return this.pipelineElement instanceof SpDataStream;
+    }
+
+    isDataProcessorInvocation(): boolean {
+        return this.pipelineElement instanceof DataProcessorInvocation;
+    }
+
+    isDataSinkInvocation(): boolean {
+        return this.pipelineElement instanceof DataSinkInvocation;
+    }
+
+    close() {
+        setTimeout(() => {
+            this.dialogRef.close();
+        });
+    }
+
+    protected readonly SpDataStream = SpDataStream;
+}
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html
index ee4b95d400..bb5c92e63b 100644
--- a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html
@@ -84,15 +84,12 @@
         "
         (dateRangeEmitter)="updateDateRangeEmitter.emit($event)"
         [timeSettings]="timeSettings"
+        [liveSettings]="dashboard.dashboardLiveSettings"
+        (intervalSettingsChangedEmitter)="
+            intervalSettingsChangedEmitter.emit($event)
+        "
     >
     </sp-time-range-selector>
-
-    <sp-data-explorer-refresh-interval-settings-component
-        [dashboard]="dashboard"
-        (intervalSettingsChangedEmitter)="intervalSettingsChangedEmitter.emit()"
-    >
-    </sp-data-explorer-refresh-interval-settings-component>
-
     <button
         mat-icon-button
         [matMenuTriggerFor]="optMenu"
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
index 7c24498680..4653e10366 100644
--- a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
@@ -17,7 +17,11 @@
  */
 
 import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { Dashboard, TimeSettings } from '@streampipes/platform-services';
+import {
+    Dashboard,
+    DashboardLiveSettings,
+    TimeSettings,
+} from '@streampipes/platform-services';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-toolbar',
@@ -62,6 +66,5 @@ export class DataExplorerDashboardToolbarComponent {
     updateDateRangeEmitter: EventEmitter<TimeSettings> = new EventEmitter();
 
     @Output()
-    intervalSettingsChangedEmitter: EventEmitter<void> =
-        new EventEmitter<void>();
+    intervalSettingsChangedEmitter = new EventEmitter<DashboardLiveSettings>();
 }
diff --git a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html
index 437e4004b4..c84b3330f2 100644
--- a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html
+++ b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html
@@ -34,7 +34,7 @@
             (deleteDashboardEmitter)="deleteDashboard()"
             (triggerEditModeEmitter)="triggerEditMode()"
             (updateDateRangeEmitter)="updateDateRange($event)"
-            (intervalSettingsChangedEmitter)="modifyRefreshInterval()"
+            (intervalSettingsChangedEmitter)="modifyRefreshInterval($event)"
         >
         </sp-data-explorer-dashboard-toolbar>
     </div>
diff --git a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
index 7a28ff025d..59fe7200f0 100644
--- a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
+++ b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
@@ -22,13 +22,13 @@ import { DataExplorerDashboardGridComponent } from '../widget-view/grid-view/dat
 import {
     ClientDashboardItem,
     Dashboard,
+    DashboardLiveSettings,
     DataExplorerWidgetModel,
     DataLakeMeasure,
     DataViewDataExplorerService,
-    TimeSelectionId,
+    TimeSelectionConstants,
     TimeSettings,
 } from '@streampipes/platform-services';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import {
@@ -48,6 +48,7 @@ import { SpDataExplorerRoutes } from '../../data-explorer.routes';
 import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
 import { DataExplorerDetectChangesService } from '../../services/data-explorer-detect-changes.service';
 import { SupportsUnsavedChangeDialog } from '../../models/dataview-dashboard.model';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-panel',
@@ -224,6 +225,7 @@ export class DataExplorerDashboardPanelComponent
                     this.timeSelectionService.getDefaultTimeSettings();
             } else {
                 this.timeSelectionService.updateTimeSettings(
+                    this.timeSelectionService.defaultQuickTimeSelections,
                     this.dashboard.dashboardTimeSettings,
                     new Date(),
                 );
@@ -233,7 +235,7 @@ export class DataExplorerDashboardPanelComponent
                     ? this.overrideTime(+startTime, +endTime)
                     : this.dashboard.dashboardTimeSettings;
             this.dashboardLoaded = true;
-            this.modifyRefreshInterval();
+            this.modifyRefreshInterval(this.dashboard.dashboardLiveSettings);
         });
     }
 
@@ -242,7 +244,7 @@ export class DataExplorerDashboardPanelComponent
             startTime,
             endTime,
             dynamicSelection: -1,
-            timeSelectionId: TimeSelectionId.CUSTOM,
+            timeSelectionId: TimeSelectionConstants.CUSTOM,
         };
     }
 
@@ -285,7 +287,8 @@ export class DataExplorerDashboardPanelComponent
         }
     }
 
-    modifyRefreshInterval(): void {
+    modifyRefreshInterval(liveSettings: DashboardLiveSettings): void {
+        this.dashboard.dashboardLiveSettings = liveSettings;
         this.refreshSubscription?.unsubscribe();
         if (this.dashboard.dashboardLiveSettings.refreshModeActive) {
             this.createQuerySubscription();
@@ -301,6 +304,7 @@ export class DataExplorerDashboardPanelComponent
             .pipe(
                 switchMap(() => {
                     this.timeSelectionService.updateTimeSettings(
+                        this.timeSelectionService.defaultQuickTimeSelections,
                         this.timeSettings,
                         new Date(),
                     );
diff --git a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
index 202946c582..f78329f924 100644
--- a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
@@ -30,7 +30,6 @@ import {
     RouterStateSnapshot,
 } from '@angular/router';
 import { ConfirmDialogComponent } from '@streampipes/shared-ui';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
 import { DataExplorerDashboardService } from '../../services/data-explorer-dashboard.service';
 import { DataExplorerDetectChangesService } from '../../services/data-explorer-detect-changes.service';
@@ -38,6 +37,7 @@ import { SupportsUnsavedChangeDialog } from '../../models/dataview-dashboard.mod
 import { Observable, of } from 'rxjs';
 import { MatDialog } from '@angular/material/dialog';
 import { map } from 'rxjs/operators';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Component({
     selector: 'sp-data-explorer-data-view',
@@ -90,6 +90,7 @@ export class DataExplorerDataViewComponent
                 this.timeSettings = this.makeDefaultTimeSettings();
             } else {
                 this.timeSelectionService.updateTimeSettings(
+                    this.timeSelectionService.defaultQuickTimeSelections,
                     this.dataView.timeSettings as TimeSettings,
                     new Date(),
                 );
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
index ea476a9846..54e23fe4f9 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
@@ -126,7 +126,10 @@
                 </button>
                 <mat-menu #optMenu="matMenu" class="large-menu">
                     <sp-time-selector-menu
+                        *ngIf="quickSelections"
                         [timeSettings]="clonedTimeSettings"
+                        [quickSelections]="quickSelections"
+                        [labels]="labels"
                         (timeSettingsEmitter)="modifyWidgetTimeSettings($event)"
                         class="w-100"
                     >
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
index 21e5170c0e..f9e4ea6ec1 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
@@ -34,6 +34,7 @@ import {
     DashboardItem,
     DataExplorerWidgetModel,
     DataLakeMeasure,
+    QuickTimeSelection,
     SpLogMessage,
     TimeSettings,
 } from '@streampipes/platform-services';
@@ -47,8 +48,9 @@ import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import { CurrentUserService } from '@streampipes/shared-ui';
 import { BaseWidgetData } from '../../models/dataview-dashboard.model';
 import { DataExplorerDashboardService } from '../../services/data-explorer-dashboard.service';
-import { TimeSelectionService } from '../../services/time-selection.service';
 import { MatMenuTrigger } from '@angular/material/menu';
+import { TimeSelectionService } from '@streampipes/shared-ui';
+import { TimeSelectorLabel } from 'projects/streampipes/shared-ui/src/lib/components/time-selector/time-selector.model';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-widget',
@@ -104,6 +106,8 @@ export class DataExplorerDashboardWidgetComponent
     timerActive = false;
     loadingTime = 0;
 
+    quickSelections: QuickTimeSelection[];
+    labels: TimeSelectorLabel;
     clonedTimeSettings: TimeSettings;
     timeSettingsModified: boolean = false;
 
@@ -137,6 +141,9 @@ export class DataExplorerDashboardWidgetComponent
     }
 
     ngOnInit(): void {
+        this.quickSelections =
+            this.timeSelectionService.defaultQuickTimeSelections;
+        this.labels = this.timeSelectionService.defaultLabels;
         this.authSubscription = this.currentUserService.user$.subscribe(
             user => {
                 this.hasDataExplorerWritePrivileges = this.authService.hasRole(
@@ -162,7 +169,7 @@ export class DataExplorerDashboardWidgetComponent
             endTime: this.timeSettings.endTime,
             timeSelectionId: this.timeSettings.timeSelectionId,
         };
-        if (this.dashboardItem.timeSettings !== undefined) {
+        if (this.dashboardItem?.timeSettings !== undefined) {
             this.timeSettingsModified = true;
         }
     }
@@ -225,7 +232,10 @@ export class DataExplorerDashboardWidgetComponent
     getTimeSettings(): TimeSettings {
         if (this.globalTimeEnabled) {
             return this.timeSettings;
-        } else if (this.dashboardItem.timeSettings !== undefined) {
+        } else if (
+            this.dashboardItem.timeSettings !== undefined &&
+            this.dashboardItem.timeSettings !== null
+        ) {
             return this.dashboardItem.timeSettings as TimeSettings;
         } else {
             return this.configuredWidget.timeSettings as TimeSettings;
diff --git a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
index 5df627e9e7..3d5c8b5d17 100644
--- a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
@@ -45,10 +45,10 @@ import {
 } from '../../../models/dataview-dashboard.model';
 import { Observable, Subject, Subscription, zip } from 'rxjs';
 import { DataExplorerFieldProviderService } from '../../../services/data-explorer-field-provider-service';
-import { TimeSelectionService } from '../../../services/time-selection.service';
 import { catchError, switchMap } from 'rxjs/operators';
 import { DataExplorerWidgetRegistry } from '../../../registry/data-explorer-widget-registry';
 import { SpFieldUpdateService } from '../../../services/field-update.service';
+import { TimeSelectionService } from '@streampipes/shared-ui';
 
 @Directive()
 export abstract class BaseDataExplorerWidgetDirective<
@@ -205,6 +205,8 @@ export abstract class BaseDataExplorerWidgetDirective<
                             this.timeSettings = widgetTimeSettings.timeSettings;
                         } else {
                             this.timeSelectionService.updateTimeSettings(
+                                this.timeSelectionService
+                                    .defaultQuickTimeSelections,
                                 this.timeSettings,
                                 new Date(),
                             );
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index c3070b45b5..32991008ed 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -23,11 +23,6 @@ import { FlexLayoutModule } from '@ngbracket/ngx-layout';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { MatChipsModule } from '@angular/material/chips';
 import { MatNativeDateModule } from '@angular/material/core';
-import {
-    DefaultMatCalendarRangeStrategy,
-    MatDatepickerModule,
-    MatRangeDateSelectionModel,
-} from '@angular/material/datepicker';
 import { MatGridListModule } from '@angular/material/grid-list';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 import { MatSliderModule } from '@angular/material/slider';
@@ -43,7 +38,6 @@ import { CoreUiModule } from '../core-ui/core-ui.module';
 import { DataExplorerDashboardGridComponent } from './components/widget-view/grid-view/data-explorer-dashboard-grid.component';
 import { DataExplorerOverviewComponent } from './components/overview/data-explorer-overview.component';
 import { DataExplorerDashboardPanelComponent } from './components/dashboard/data-explorer-dashboard-panel.component';
-import { TimeRangeSelectorComponent } from './components/time-selector/time-range-selector.component';
 import { DataExplorerDashboardWidgetComponent } from './components/widget/data-explorer-dashboard-widget.component';
 import { ImageWidgetComponent } from './components/widgets/image/image-widget.component';
 import { TrafficLightWidgetComponent } from './components/widgets/traffic-light/traffic-light-widget.component';
@@ -129,9 +123,6 @@ import { DataExplorerDataViewSelectionComponent } from './components/dashboard/d
 import { DataExplorerDashboardWidgetSelectionPanelComponent } from './components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component';
 import { DataExplorerDataViewPreviewComponent } from './components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component';
 import { DataExplorerDashboardToolbarComponent } from './components/dashboard/dashboard-toolbar/dashboard-toolbar.component';
-import { TimeRangeSelectorMenuComponent } from './components/time-selector/time-selector-menu/time-selector-menu.component';
-import { CustomTimeRangeSelectionComponent } from './components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
-import { DataExplorerRefreshIntervalSettingsComponent } from './components/dashboard/dashboard-toolbar/refresh-interval-settings/refresh-interval-settings.component';
 import { OrderSelectionPanelComponent } from './components/data-view/data-view-designer-panel/data-settings/order-selection-panel/order-selection-panel.component';
 import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/gauge-widget-config.component';
 
@@ -174,7 +165,6 @@ import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/ga
         MatProgressSpinnerModule,
         ReactiveFormsModule,
         CoreUiModule,
-        MatDatepickerModule,
         MatNativeDateModule,
         MatSliderModule,
         MatSlideToggleModule,
@@ -215,7 +205,6 @@ import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/ga
     ],
     declarations: [
         AggregateConfigurationComponent,
-        CustomTimeRangeSelectionComponent,
         DataExplorerDashboardGridComponent,
         DataExplorerOverviewComponent,
         DataExplorerDashboardPanelComponent,
@@ -227,7 +216,6 @@ import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/ga
         DataExplorerDataViewSelectionComponent,
         DataExplorerDesignerPanelComponent,
         DataExplorerEditDashboardDialogComponent,
-        DataExplorerRefreshIntervalSettingsComponent,
         DataExplorerWidgetAppearanceSettingsComponent,
         DataExplorerWidgetDataSettingsComponent,
         DataExplorerDataViewComponent,
@@ -259,8 +247,6 @@ import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/ga
         MapWidgetComponent,
         HeatmapWidgetConfigComponent,
         ImageViewerComponent,
-        TimeRangeSelectorComponent,
-        TimeRangeSelectorMenuComponent,
         DataExplorerVisualisationSettingsComponent,
         GroupSelectionPanelComponent,
         DataExplorerVisualisationSettingsComponent,
@@ -283,7 +269,6 @@ import { GaugeWidgetConfigComponent } from './components/widgets/gauge/config/ga
         SpTimeSeriesAppearanceConfigComponent,
         SpDataZoomConfigComponent,
     ],
-    providers: [DefaultMatCalendarRangeStrategy, MatRangeDateSelectionModel],
     exports: [],
 })
 export class DataExplorerModule {
diff --git a/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts b/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
index 241d3315c9..bf3631205d 100644
--- a/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
+++ b/ui/src/app/data-explorer/services/data-explorer-detect-changes.service.ts
@@ -51,7 +51,7 @@ export class DataExplorerDetectChangesService {
         originalTimeSettings: TimeSettings,
         currentTimeSettings: TimeSettings,
     ): boolean {
-        if (originalTimeSettings.timeSelectionId == 0) {
+        if (originalTimeSettings.timeSelectionId === 'custom') {
             return this.hasCustomTimeSettingsChanged(
                 originalTimeSettings,
                 currentTimeSettings,
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.html b/ui/src/app/editor/components/pipeline/pipeline.component.html
index 20b984a570..8b77b5b017 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.html
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.html
@@ -26,6 +26,7 @@
     *ngFor="
         let pipelineElementConfig of rawPipelineModel | enabledPipelineElement
     "
+    style="position: relative"
 >
     <sp-dropped-pipeline-element
         [allElements]="allElements"
@@ -41,4 +42,15 @@
         (deleteEmitter)="handleDeleteOption($event)"
     >
     </sp-dropped-pipeline-element>
+    <div class="topics-button customize-button" *ngIf="readonly">
+        <button
+            class="topics-icon-button"
+            mat-icon-button
+            matTooltip="View Topics"
+            [matTooltipPosition]="'above'"
+            (click)="openTopicsDialog(pipelineElementConfig)"
+        >
+            <i class="material-icons topics-icon-size">code</i>
+        </button>
+    </div>
 </div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.scss b/ui/src/app/editor/components/pipeline/pipeline.component.scss
new file mode 100644
index 0000000000..4d3c139be2
--- /dev/null
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.scss
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+
+.topics-button {
+    cursor: pointer;
+    width: 30px;
+    height: 30px;
+    border-radius: 20%;
+    box-shadow: 0 0 3px var(--color-accent);
+    background-color: var(--color-accent);
+    color: rgba(255, 255, 255, 0.75);
+    position: absolute;
+    left: 35%;
+    top: 75%;
+    z-index: 50;
+    margin-top: 5px;
+}
+
+.topics-icon-button {
+    width: 100%;
+    height: 100%;
+    padding: 0;
+}
+
+.topics-icon-size {
+    font-size: 16px;
+    color: white;
+}
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts b/ui/src/app/editor/components/pipeline/pipeline.component.ts
index 71843f0692..7ff4bc3007 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts
@@ -73,6 +73,7 @@ import { IdGeneratorService } from '../../../core-services/id-generator/id-gener
 @Component({
     selector: 'sp-pipeline',
     templateUrl: './pipeline.component.html',
+    styleUrls: ['./pipeline.component.scss'],
 })
 export class PipelineComponent implements OnInit, OnDestroy {
     @Input()
@@ -81,6 +82,9 @@ export class PipelineComponent implements OnInit, OnDestroy {
     @Input()
     rawPipelineModel: PipelineElementConfig[];
 
+    @Input()
+    pipelineElement: PipelineElementConfig;
+
     @Input()
     allElements: PipelineElementUnion[];
 
@@ -586,4 +590,8 @@ export class PipelineComponent implements OnInit, OnDestroy {
                     );
             });
     }
+
+    openTopicsDialog(pipelineElementConfig: PipelineElementConfig) {
+        this.editorService.openTopicsDialog(pipelineElementConfig);
+    }
 }
diff --git a/ui/src/app/editor/dialog/save-pipeline/save-pipeline-settings/save-pipeline-settings.component.html b/ui/src/app/editor/dialog/save-pipeline/save-pipeline-settings/save-pipeline-settings.component.html
index 18f221cbfc..482d98e358 100644
--- a/ui/src/app/editor/dialog/save-pipeline/save-pipeline-settings/save-pipeline-settings.component.html
+++ b/ui/src/app/editor/dialog/save-pipeline/save-pipeline-settings/save-pipeline-settings.component.html
@@ -95,6 +95,7 @@
                 >Show pipeline configuration as code</mat-expansion-panel-header
             >
             <sp-configuration-code-panel
+                *ngIf="compactPipeline"
                 [configuration]="compactPipeline"
                 maxHeight="none"
             >
diff --git a/ui/src/app/editor/services/editor.service.ts b/ui/src/app/editor/services/editor.service.ts
index 45ba82218d..0e0f19954b 100644
--- a/ui/src/app/editor/services/editor.service.ts
+++ b/ui/src/app/editor/services/editor.service.ts
@@ -40,6 +40,7 @@ import { DialogService, PanelType } from '@streampipes/shared-ui';
 import { map } from 'rxjs/operators';
 import { NGX_LOADING_BAR_IGNORED } from '@ngx-loading-bar/http-client';
 import { HelpComponent } from '../../core-ui/help/help.component';
+import { TopicsComponent } from 'src/app/core-ui/topics/topics.component';
 
 @Injectable({ providedIn: 'root' })
 export class EditorService {
@@ -175,6 +176,17 @@ export class EditorService {
         });
     }
 
+    openTopicsDialog(pipelineElementConfig: PipelineElementConfig) {
+        this.dialogService.open(TopicsComponent, {
+            panelType: PanelType.STANDARD_PANEL,
+            title: 'View Topics of ' + pipelineElementConfig.payload.name,
+            width: '70vw',
+            data: {
+                pipelineElement: pipelineElementConfig.payload,
+            },
+        });
+    }
+
     initiatePipelinePreview(
         pipeline: Pipeline,
     ): Observable<PipelinePreviewModel> {
diff --git a/ui/src/app/pipeline-details/dialogs/pipeline-code/pipeline-code-dialog.component.html b/ui/src/app/pipeline-details/dialogs/pipeline-code/pipeline-code-dialog.component.html
index 2b89fa567e..9e17a966ea 100644
--- a/ui/src/app/pipeline-details/dialogs/pipeline-code/pipeline-code-dialog.component.html
+++ b/ui/src/app/pipeline-details/dialogs/pipeline-code/pipeline-code-dialog.component.html
@@ -20,6 +20,7 @@
     <div class="sp-dialog-content">
         <div fxFlex="100" fxLayout="column" class="p-10">
             <sp-configuration-code-panel
+                *ngIf="compactPipeline"
                 [configuration]="compactPipeline"
                 maxHeight="none"
             >
diff --git a/ui/src/app/pipeline-details/pipeline-details.module.ts b/ui/src/app/pipeline-details/pipeline-details.module.ts
index f05009a578..6eb5f6fb11 100644
--- a/ui/src/app/pipeline-details/pipeline-details.module.ts
+++ b/ui/src/app/pipeline-details/pipeline-details.module.ts
@@ -22,6 +22,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { MatTabsModule } from '@angular/material/tabs';
 import { MatButtonModule } from '@angular/material/button';
 import { CommonModule } from '@angular/common';
+import { ClipboardModule } from '@angular/cdk/clipboard';
 import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
 import { PipelinePreviewComponent } from './components/preview/pipeline-preview.component';
 import { EditorModule } from '../editor/editor.module';
@@ -62,6 +63,7 @@ import { PipelineCodeDialogComponent } from './dialogs/pipeline-code/pipeline-co
         MatExpansionModule,
         MatSlideToggleModule,
         MatDivider,
+        ClipboardModule,
     ],
     declarations: [
         PipelineActionsComponent,


Test patch:
diff --git a/.github/workflows/go-client-e2e-test.yml b/.github/workflows/go-client-e2e-test.yml
index 4adec93e16..a2c261e7e9 100644
--- a/.github/workflows/go-client-e2e-test.yml
+++ b/.github/workflows/go-client-e2e-test.yml
@@ -29,7 +29,7 @@ jobs:
         uses: docker/setup-buildx-action@v1
 
       - name: Cache Docker layers
-        uses: actions/cache@v2
+        uses: actions/cache@v4
         with:
           path: /tmp/.buildx-cache
           key: ${{ runner.os }}-buildx-${{ github.sha }}
@@ -37,7 +37,7 @@ jobs:
             ${{ runner.os }}-buildx-
 
       - name: Set up Go 1.21
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v5
         with:
           go-version: '1.21'
 
diff --git a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/AdapterMasterManagementTest.java b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/AdapterMasterManagementTest.java
index 6d920fb751..e1e18324ce 100644
--- a/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/AdapterMasterManagementTest.java
+++ b/streampipes-connect-management/src/test/java/org/apache/streampipes/connect/management/management/AdapterMasterManagementTest.java
@@ -36,12 +36,12 @@ import static org.mockito.Mockito.when;
 public class AdapterMasterManagementTest {
 
   @Test
-  public void getAdapterFailNull() {
-    AdapterInstanceStorageImpl adapterStorage = mock(AdapterInstanceStorageImpl.class);
-    AdapterResourceManager resourceManager = mock(AdapterResourceManager.class);
+  public void getAdapter_FailNull() {
+    var adapterStorage = mock(AdapterInstanceStorageImpl.class);
+    var resourceManager = mock(AdapterResourceManager.class);
     when(adapterStorage.findAll()).thenReturn(null);
 
-    AdapterMasterManagement adapterMasterManagement =
+    var adapterMasterManagement =
         new AdapterMasterManagement(
             adapterStorage,
             resourceManager,
@@ -53,13 +53,13 @@ public class AdapterMasterManagementTest {
   }
 
   @Test
-  public void getAdapterFail() {
-    List<AdapterDescription> adapterDescriptions = List.of(new AdapterDescription());
-    AdapterInstanceStorageImpl adapterStorage = mock(AdapterInstanceStorageImpl.class);
-    AdapterResourceManager resourceManager = mock(AdapterResourceManager.class);
+  public void getAdapter_Fail() {
+    var adapterDescriptions = List.of(new AdapterDescription());
+    var adapterStorage = mock(AdapterInstanceStorageImpl.class);
+    var resourceManager = mock(AdapterResourceManager.class);
     when(adapterStorage.findAll()).thenReturn(adapterDescriptions);
 
-    AdapterMasterManagement adapterMasterManagement =
+    var adapterMasterManagement =
         new AdapterMasterManagement(
             adapterStorage,
             resourceManager,
@@ -71,10 +71,10 @@ public class AdapterMasterManagementTest {
   }
 
   @Test
-  public void getAllAdaptersSuccess() throws AdapterException {
-    List<AdapterDescription> adapterDescriptions = List.of(new AdapterDescription());
-    AdapterInstanceStorageImpl adapterStorage = mock(AdapterInstanceStorageImpl.class);
-    AdapterResourceManager resourceManager = mock(AdapterResourceManager.class);
+  public void getAllAdapters_Success() throws AdapterException {
+    var adapterDescriptions = List.of(new AdapterDescription());
+    var adapterStorage = mock(AdapterInstanceStorageImpl.class);
+    var resourceManager = mock(AdapterResourceManager.class);
     when(adapterStorage.findAll()).thenReturn(adapterDescriptions);
 
     AdapterMasterManagement adapterMasterManagement =
@@ -91,12 +91,12 @@ public class AdapterMasterManagementTest {
   }
 
   @Test
-  public void getAllAdaptersFail() {
-    AdapterInstanceStorageImpl adapterStorage = mock(AdapterInstanceStorageImpl.class);
-    AdapterResourceManager resourceManager = mock(AdapterResourceManager.class);
+  public void getAllAdapters_Fail() {
+    var adapterStorage = mock(AdapterInstanceStorageImpl.class);
+    var resourceManager = mock(AdapterResourceManager.class);
     when(adapterStorage.findAll()).thenReturn(null);
 
-    AdapterMasterManagement adapterMasterManagement =
+    var adapterMasterManagement =
         new AdapterMasterManagement(
             adapterStorage,
             resourceManager,
diff --git a/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessorTest.java b/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessorTest.java
new file mode 100644
index 0000000000..fb2a1d5666
--- /dev/null
+++ b/streampipes-extensions/streampipes-processors-enricher-jvm/src/test/java/org/apache/streampipes/processors/enricher/jvm/processor/math/MathOpProcessorTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.processors.enricher.jvm.processor.math;
+
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+
+public class MathOpProcessorTest{
+  private MathOpProcessor processor;
+
+  @BeforeEach
+  public void setup(){
+    processor = new MathOpProcessor();
+  }
+
+  @Test
+  public void detectAdditionOperator(){
+    TestConfiguration leftOperandConfiguration = TestConfiguration.builder()
+            .configWithDefaultPrefix(MathOpProcessor.LEFT_OPERAND, "leftOperand")
+            .configWithDefaultPrefix(MathOpProcessor.RIGHT_OPERAND, "rightOperand")
+            .config(MathOpProcessor.OPERATION, "+").build();
+
+    List<Map<String, Object>> inputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d));
+    List<Map<String, Object>> outputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d, "calculationResult", 10.0d));
+    ProcessingElementTestExecutor testExecutor = new ProcessingElementTestExecutor(
+            processor, leftOperandConfiguration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
+
+  @Test
+  public void detectSubtractionOperator(){
+    TestConfiguration leftOperandConfiguration = TestConfiguration.builder()
+            .configWithDefaultPrefix(MathOpProcessor.LEFT_OPERAND, "leftOperand")
+            .configWithDefaultPrefix(MathOpProcessor.RIGHT_OPERAND, "rightOperand")
+            .config(MathOpProcessor.OPERATION, "-").build();
+
+    List<Map<String, Object>> inputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d));
+    List<Map<String, Object>> outputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d, "calculationResult", 0.0d));
+    ProcessingElementTestExecutor testExecutor = new ProcessingElementTestExecutor(
+            processor, leftOperandConfiguration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
+
+  @Test
+  public void detectMultiplicationOperator(){
+    TestConfiguration leftOperandConfiguration = TestConfiguration.builder()
+            .configWithDefaultPrefix(MathOpProcessor.LEFT_OPERAND, "leftOperand")
+            .configWithDefaultPrefix(MathOpProcessor.RIGHT_OPERAND, "rightOperand")
+            .config(MathOpProcessor.OPERATION, "*").build();
+
+    List<Map<String, Object>> inputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d));
+    List<Map<String, Object>> outputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d, "calculationResult", 25.0d));
+    ProcessingElementTestExecutor testExecutor = new ProcessingElementTestExecutor(
+            processor, leftOperandConfiguration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
+
+  @Test
+  public void detectDivisionOperator(){
+    TestConfiguration leftOperandConfiguration = TestConfiguration.builder()
+            .configWithDefaultPrefix(MathOpProcessor.LEFT_OPERAND, "leftOperand")
+            .configWithDefaultPrefix(MathOpProcessor.RIGHT_OPERAND, "rightOperand")
+            .config(MathOpProcessor.OPERATION, "/").build();
+
+    List<Map<String, Object>> inputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d));
+    List<Map<String, Object>> outputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d, "calculationResult", 1.0d));
+    ProcessingElementTestExecutor testExecutor = new ProcessingElementTestExecutor(
+            processor, leftOperandConfiguration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
+
+  @Test
+  public void detectModulusOperator(){
+    TestConfiguration leftOperandConfiguration = TestConfiguration.builder()
+            .configWithDefaultPrefix(MathOpProcessor.LEFT_OPERAND, "leftOperand")
+            .configWithDefaultPrefix(MathOpProcessor.RIGHT_OPERAND, "rightOperand")
+            .config(MathOpProcessor.OPERATION, "%").build();
+
+    List<Map<String, Object>> inputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d));
+    List<Map<String, Object>> outputEvents = List.of(
+            Map.of("leftOperand", 5.0d, "rightOperand", 5.0d, "calculationResult", 0.0d));
+    ProcessingElementTestExecutor testExecutor = new ProcessingElementTestExecutor(
+            processor, leftOperandConfiguration);
+
+    testExecutor.run(inputEvents, outputEvents);
+  }
+}
\ No newline at end of file
diff --git a/streampipes-resource-management/src/test/java/org/apache/streampipes/resource/management/AdapterResourceManagerTest.java b/streampipes-resource-management/src/test/java/org/apache/streampipes/resource/management/AdapterResourceManagerTest.java
index d815855490..d4616713da 100644
--- a/streampipes-resource-management/src/test/java/org/apache/streampipes/resource/management/AdapterResourceManagerTest.java
+++ b/streampipes-resource-management/src/test/java/org/apache/streampipes/resource/management/AdapterResourceManagerTest.java
@@ -18,25 +18,59 @@
 
 package org.apache.streampipes.resource.management;
 
+import org.apache.streampipes.commons.exceptions.connect.AdapterException;
+import org.apache.streampipes.model.Tuple2;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.storage.api.IAdapterStorage;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class AdapterResourceManagerTest {
 
+  private IAdapterStorage storage;
+  private AdapterResourceManager adapterResourceManager;
+
+  @BeforeEach
+  void setUp() {
+    storage = mock(IAdapterStorage.class);
+    adapterResourceManager = new AdapterResourceManager(storage);
+  }
+
   @Test
-  public void encryptAndUpdateValidateDescriptionStored() {
+  public void encryptAndUpdate_ValidateDescriptionStored() throws AdapterException {
 
-    IAdapterStorage storage = mock(IAdapterStorage.class);
-    AdapterResourceManager adapterResourceManager = new AdapterResourceManager(storage);
     adapterResourceManager.encryptAndUpdate(new AdapterDescription());
 
     verify(storage, times(1)).updateElement(any());
   }
+
+  @Test
+  void encryptAndCreate_ReturnsIdOnSuccess() throws AdapterException {
+    var id = "adapterId";
+
+    when(storage.persist(any())).thenReturn(new Tuple2<>(true, id));
+    var result = adapterResourceManager.encryptAndCreate(new AdapterDescription());
+
+    verify(storage, times(1)).persist(any());
+    assertEquals(id, result);
+  }
+
+  @Test
+  void encryptAndCreate_ThrowsAdapterExceptionOnConflict() {
+
+    doThrow(new org.lightcouch.DocumentConflictException("Conflict")).when(storage).persist(any());
+
+    assertThrows(AdapterException.class, () -> adapterResourceManager.encryptAndCreate(new AdapterDescription()));
+  }
+
 }
diff --git a/ui/cypress/fixtures/connect/compact/compactTest.csv b/ui/cypress/fixtures/connect/compact/compactTest.csv
new file mode 100644
index 0000000000..6cf117f7c1
--- /dev/null
+++ b/ui/cypress/fixtures/connect/compact/compactTest.csv
@@ -0,0 +1,2 @@
+timestamp;value;temperature
+1000;1.0;0.1
diff --git a/ui/cypress/support/utils/ProcessingElementTestUtils.ts b/ui/cypress/support/utils/ProcessingElementTestUtils.ts
index f2607a112b..6340635b48 100644
--- a/ui/cypress/support/utils/ProcessingElementTestUtils.ts
+++ b/ui/cypress/support/utils/ProcessingElementTestUtils.ts
@@ -18,7 +18,7 @@
 
 import { FileManagementUtils } from './FileManagementUtils';
 import { ConnectUtils } from './connect/ConnectUtils';
-import { PipelineUtils } from './PipelineUtils';
+import { PipelineUtils } from './pipeline/PipelineUtils';
 import { DataLakeUtils } from './datalake/DataLakeUtils';
 import { PipelineBuilder } from '../builder/PipelineBuilder';
 import { PipelineElementBuilder } from '../builder/PipelineElementBuilder';
diff --git a/ui/cypress/tests/connect/compact/addCompactAdapter.spec.ts b/ui/cypress/tests/connect/compact/addCompactAdapter.spec.ts
new file mode 100644
index 0000000000..57d2466c15
--- /dev/null
+++ b/ui/cypress/tests/connect/compact/addCompactAdapter.spec.ts
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
+import { CompactAdapterUtils } from '../../../support/utils/connect/CompactAdapterUtils';
+import { PipelineUtils } from '../../../support/utils/pipeline/PipelineUtils';
+import { FileManagementUtils } from '../../../support/utils/FileManagementUtils';
+
+describe('Add Compact Adapters', () => {
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+    });
+
+    it('Add an adapter via the compact API. Do not start', () => {
+        const compactAdapter =
+            CompactAdapterUtils.getMachineDataSimulator().build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
+            ConnectUtils.validateAdapterIsStopped();
+
+            PipelineUtils.checkAmountOfPipelinesPipeline(0);
+        });
+    });
+
+    it('Add an adapter via the compact API. Start Adapter', () => {
+        const compactAdapter = CompactAdapterUtils.getMachineDataSimulator()
+            .setStart()
+            .build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
+            ConnectUtils.validateAdapterIsRunning();
+
+            PipelineUtils.checkAmountOfPipelinesPipeline(0);
+        });
+    });
+
+    it('Add an adapter via the compact API. Start Adapter and start persist pipeline', () => {
+        const compactAdapter = CompactAdapterUtils.getMachineDataSimulator()
+            .setStart()
+            .setPersist()
+            .build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
+            ConnectUtils.validateAdapterIsRunning();
+
+            PipelineUtils.checkAmountOfPipelinesPipeline(1);
+        });
+    });
+
+    it('Add an adapter via the compact API via yml API.', () => {
+        cy.readFile(
+            'cypress/fixtures/connect/compact/machineDataSimulator.yml',
+        ).then(ymlDescription => {
+            CompactAdapterUtils.storeCompactYmlAdapter(ymlDescription).then(
+                () => {
+                    ConnectUtils.validateAdapterIsStopped();
+                },
+            );
+        });
+    });
+
+    it('Ensure correct error code when adapter with the same id already exists', () => {
+        const compactAdapter = CompactAdapterUtils.getMachineDataSimulator()
+            .setStart()
+            .setPersist()
+            .build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(
+            response => {
+                expect(response.status).to.equal(200);
+                ConnectUtils.checkAmountOfAdapters(1);
+
+                // Store the same adapter a second time and validate that resource returns status of conflict
+                CompactAdapterUtils.storeCompactAdapter(
+                    compactAdapter,
+                    false,
+                ).then(response => {
+                    expect(response.status).to.equal(409);
+
+                    ConnectUtils.checkAmountOfAdapters(1);
+                });
+            },
+        );
+    });
+
+    it('Add file stream adapter via the compact API. Start Adapter with Pipeline', () => {
+        FileManagementUtils.addFile('connect/compact/compactTest.csv');
+
+        cy.readFile('cypress/fixtures/connect/compact/fileReplay.yml').then(
+            ymlDescription => {
+                CompactAdapterUtils.storeCompactYmlAdapter(ymlDescription).then(
+                    () => {
+                        ConnectUtils.validateAdapterIsRunning();
+                        PipelineUtils.checkAmountOfPipelinesPipeline(1);
+                    },
+                );
+            },
+        );
+    });
+});
diff --git a/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts b/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts
new file mode 100644
index 0000000000..4af2f359e2
--- /dev/null
+++ b/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts
@@ -0,0 +1,73 @@
+/*
+ *  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 { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
+import { CompactAdapterUtils } from '../../../support/utils/connect/CompactAdapterUtils';
+import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+
+describe('Add Compact Adapters', () => {
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+    });
+
+    it('Add an adapter and rename a property', () => {
+        const newPropertyName = 'temperature_renamed';
+        const compactAdapter = CompactAdapterUtils.getMachineDataSimulator()
+            .withRename('temperature', newPropertyName)
+            .setStart()
+            .build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
+            const runtimeNames = [
+                'density',
+                'mass_flow',
+                'sensor_fault_flags',
+                'sensorId',
+                newPropertyName,
+                'timestamp',
+                'volume_flow',
+            ];
+
+            ConnectUtils.validateEventSchema(runtimeNames);
+        });
+    });
+
+    it('Add an adapter and change measurement unit', () => {
+        const compactAdapter = CompactAdapterUtils.getMachineDataSimulator()
+            .withMeasurementUnit(
+                'temperature',
+                'http://qudt.org/vocab/unit#DegreeFahrenheit',
+            )
+            .setStart()
+            .build();
+
+        CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
+            ConnectUtils.goToConnect();
+            ConnectBtns.detailsAdapter().click();
+
+            // This assertion works because the original value is below 100
+            // with the transformation the value is above 100
+            ConnectUtils.getLivePreviewValue('temperature')
+                .invoke('text')
+                .then(text => {
+                    const value = parseFloat(text.trim());
+                    expect(value).to.be.greaterThan(100);
+                });
+        });
+    });
+});
diff --git a/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts b/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts
new file mode 100644
index 0000000000..798d8a8caf
--- /dev/null
+++ b/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts
@@ -0,0 +1,55 @@
+/*
+ * 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 { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
+import { AdapterBuilder } from '../../../support/builder/AdapterBuilder';
+import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+import { GeneralUtils } from '../../../support/utils/GeneralUtils';
+import { CompactUtils } from '../../../support/utils/CompactUtils';
+
+describe('Test Compact Adapters', () => {
+    beforeEach('Setup Test', () => {
+        cy.initStreamPipesTest();
+    });
+
+    it('Validate that code for existing adapter is displayed correctly', () => {
+        const adapterInput = AdapterBuilder.create('Machine_Data_Simulator')
+            .setName('Machine Data Simulator Test')
+            .addInput('input', 'wait-time-ms', '1000')
+            .build();
+
+        ConnectUtils.addAdapter(adapterInput);
+
+        // Validate code editor in start dialog
+        ConnectBtns.showCodeCheckbox().parent().click();
+        validateCodeEditor();
+
+        ConnectUtils.startAdapter(adapterInput);
+
+        // Validate code editor in adapter details
+        ConnectBtns.detailsAdapter().click();
+        GeneralUtils.tab('Code');
+        validateCodeEditor();
+    });
+
+    const validateCodeEditor = () => {
+        CompactUtils.ymlConfiguration().should('be.visible');
+        cy.contains('span', 'JSON').click();
+        CompactUtils.jsonConfiguration().should('be.visible');
+    };
+});
diff --git a/ui/cypress/tests/connect/deleteAdapterWithMultipleUsers.smoke.spec.ts b/ui/cypress/tests/connect/deleteAdapterWithMultipleUsers.smoke.spec.ts
index 29c854cb23..a11332ac9e 100644
--- a/ui/cypress/tests/connect/deleteAdapterWithMultipleUsers.smoke.spec.ts
+++ b/ui/cypress/tests/connect/deleteAdapterWithMultipleUsers.smoke.spec.ts
@@ -20,7 +20,7 @@ import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { UserUtils } from '../../support/utils/UserUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 
 const adapterName = 'simulator';
 
diff --git a/ui/cypress/tests/connect/editAdapter.smoke.spec.ts b/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
index 214e8433c8..a1d20139eb 100644
--- a/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
+++ b/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
@@ -57,6 +57,8 @@ describe('Test Edit Adapter', () => {
 
         cy.dataCy('sp-adapter-name').clear().type(newAdapterName);
 
+        // This wait is required to ensure that there is no couch db update conflict
+        cy.wait(1000);
         ConnectBtns.storeEditAdapter().click();
 
         cy.dataCy('sp-connect-adapter-success-added', {
diff --git a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
index c30f355474..c3f14b7a29 100644
--- a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
+++ b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
@@ -18,7 +18,7 @@
 
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
 import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 import { AdapterBuilder } from '../../support/builder/AdapterBuilder';
diff --git a/ui/cypress/tests/connect/persistInDataLake.smoke.spec.ts b/ui/cypress/tests/connect/persistInDataLake.smoke.spec.ts
index 39c672b6a7..939bf44312 100644
--- a/ui/cypress/tests/connect/persistInDataLake.smoke.spec.ts
+++ b/ui/cypress/tests/connect/persistInDataLake.smoke.spec.ts
@@ -17,7 +17,7 @@
  */
 
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { FileManagementUtils } from '../../support/utils/FileManagementUtils';
 import { AdapterBuilder } from '../../support/builder/AdapterBuilder';
 import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
diff --git a/ui/cypress/tests/datalake/configuration.smoke.spec.ts b/ui/cypress/tests/datalake/configuration.smoke.spec.ts
index 3b5532e154..1b095ab07e 100644
--- a/ui/cypress/tests/datalake/configuration.smoke.spec.ts
+++ b/ui/cypress/tests/datalake/configuration.smoke.spec.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { DataLakeUtils } from '../../support/utils/datalake/DataLakeUtils';
 
 describe('Test Truncate data in datalake', () => {
diff --git a/ui/cypress/tests/experimental/restartStreamPipes/restartStreamPipes1.ts b/ui/cypress/tests/experimental/restartStreamPipes/restartStreamPipes1.ts
index 3f098de23a..d8eafe8bc1 100644
--- a/ui/cypress/tests/experimental/restartStreamPipes/restartStreamPipes1.ts
+++ b/ui/cypress/tests/experimental/restartStreamPipes/restartStreamPipes1.ts
@@ -17,7 +17,7 @@
  */
 
 import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../../support/builder/PipelineBuilder';
 import { DashboardUtils } from '../../../support/utils/DashboardUtils';
diff --git a/ui/cypress/tests/experimental/testJvmArchetype/testJvmArchetype.ts b/ui/cypress/tests/experimental/testJvmArchetype/testJvmArchetype.ts
index 2a41d84eec..c15490d2e4 100644
--- a/ui/cypress/tests/experimental/testJvmArchetype/testJvmArchetype.ts
+++ b/ui/cypress/tests/experimental/testJvmArchetype/testJvmArchetype.ts
@@ -17,7 +17,7 @@
  */
 
 import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../../support/builder/PipelineBuilder';
 import { DashboardUtils } from '../../../support/utils/DashboardUtils';
diff --git a/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts b/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
index 1de708d27f..010f7695f9 100644
--- a/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
+++ b/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
@@ -17,7 +17,7 @@
  */
 
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 
diff --git a/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts b/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
index b2e69bd0b4..5de2359906 100644
--- a/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
+++ b/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
@@ -17,7 +17,7 @@
  */
 
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 
diff --git a/ui/cypress/tests/pipelineElement/PipelineElementDocumentation.spec.ts b/ui/cypress/tests/pipelineElement/PipelineElementDocumentation.spec.ts
index 726ed1c5e2..4387a2e5e6 100644
--- a/ui/cypress/tests/pipelineElement/PipelineElementDocumentation.spec.ts
+++ b/ui/cypress/tests/pipelineElement/PipelineElementDocumentation.spec.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 
 describe('Validate that the markdown documentation for pipeline elements works', () => {
     beforeEach('Setup Test', () => {
diff --git a/ui/cypress/tests/pipelineElementConfigurationTemplate/pipelineElementConfigurationTemplate.ts b/ui/cypress/tests/pipelineElementConfigurationTemplate/pipelineElementConfigurationTemplate.ts
index 2b9fff9442..16ea5c3543 100644
--- a/ui/cypress/tests/pipelineElementConfigurationTemplate/pipelineElementConfigurationTemplate.ts
+++ b/ui/cypress/tests/pipelineElementConfigurationTemplate/pipelineElementConfigurationTemplate.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
diff --git a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
index 2f4de9e7bf..03d7159568 100644
--- a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
+++ b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
@@ -20,7 +20,7 @@ import { UserBuilder } from '../../support/builder/UserBuilder';
 import { UserRole } from '../../../src/app/_enums/user-role.enum';
 import { UserUtils } from '../../support/utils/UserUtils';
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';
 
diff --git a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
index a992334de8..94d83418ff 100644
--- a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
@@ -20,7 +20,7 @@ import { UserBuilder } from '../../support/builder/UserBuilder';
 import { UserRole } from '../../../src/app/_enums/user-role.enum';
 import { UserUtils } from '../../support/utils/UserUtils';
 import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
-import { PipelineUtils } from '../../support/utils/PipelineUtils';
+import { PipelineUtils } from '../../support/utils/pipeline/PipelineUtils';
 import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder';
 import { PipelineBuilder } from '../../support/builder/PipelineBuilder';