This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch 
3292-show-adapter-and-pipeline-configuration-in-ui
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit 8a5d4ec587f77234e5357b56bc351c03d26bc4f8
Author: Dominik Riemer <[email protected]>
AuthorDate: Tue Oct 8 22:33:08 2024 +0200

    feat(#3292): Add code tab to adapter view
---
 .../generator/AdapterEnrichmentRuleGenerator.java  |   4 +-
 .../compact/generator/CompactAdapterGenerator.java | 123 ++++++++++++
 .../management/CompactAdapterManagement.java       |  17 ++
 .../connect/adapter/compact/CompactAdapter.java    |   3 +
 .../adapter/compact/CompactEventProperty.java      |   3 +
 .../manager/template/CompactConfigGenerator.java   | 211 +++++++++++++++++++++
 .../template/PipelineElementTemplateVisitor.java   |  33 +---
 .../rest/impl/connect/AdapterResource.java         |  58 ++++--
 .../rest/impl/connect/CompactAdapterResource.java  |   5 +-
 .../src/lib/apis/adapter.service.ts                |  10 +
 .../src/lib/model/gen/streampipes-model.ts         | 176 +++++++++--------
 .../adapter-code-panel.component.html              |  36 ++++
 .../adapter-code-panel.component.scss              |  21 +-
 .../adapter-code-panel.component.ts}               |  48 +++--
 .../adapter-options-panel.component.html           |  22 +--
 .../start-adapter-configuration.component.html     |  15 ++
 .../start-adapter-configuration.component.ts       |   1 +
 .../abstract-adapter-details.directive.ts          |   2 +
 .../adapter-details-code.component.html            |  38 ++++
 .../adapter-details-code.component.ts              |  17 ++
 .../adapter-details/adapter-details-tabs.ts        |   5 +
 ui/src/app/connect/connect.module.ts               |  10 +
 .../app/connect/filter/yaml-pretty-print.pipe.ts   |  17 +-
 23 files changed, 701 insertions(+), 174 deletions(-)

diff --git 
a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/AdapterEnrichmentRuleGenerator.java
 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/AdapterEnrichmentRuleGenerator.java
index 5abb7a99ce..9c19b30791 100644
--- 
a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/AdapterEnrichmentRuleGenerator.java
+++ 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/AdapterEnrichmentRuleGenerator.java
@@ -25,6 +25,8 @@ import org.apache.streampipes.sdk.helpers.EpProperties;
 
 public class AdapterEnrichmentRuleGenerator implements AdapterModelGenerator {
 
+  public static final String TIMESTAMP_FIELD = "timestamp";
+
   @Override
   public void apply(AdapterDescription adapterDescription,
                     CompactAdapter compactAdapter) throws Exception {
@@ -33,7 +35,7 @@ public class AdapterEnrichmentRuleGenerator implements 
AdapterModelGenerator {
         var timestampRule = new 
AddTimestampRuleDescription(compactAdapter.enrich().timestamp());
         adapterDescription.getRules().add(timestampRule);
         adapterDescription.getEventSchema().addEventProperty(
-            EpProperties.timestampProperty("timestamp")
+            EpProperties.timestampProperty(TIMESTAMP_FIELD)
         );
       }
     }
diff --git 
a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/CompactAdapterGenerator.java
 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/CompactAdapterGenerator.java
new file mode 100644
index 0000000000..6857d0c4ef
--- /dev/null
+++ 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/compact/generator/CompactAdapterGenerator.java
@@ -0,0 +1,123 @@
+/*
+ * 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.connect.management.compact.generator;
+
+import 
org.apache.streampipes.connect.shared.preprocessing.convert.ToOriginalSchemaConverter;
+import org.apache.streampipes.manager.template.CompactConfigGenerator;
+import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import 
org.apache.streampipes.model.connect.adapter.compact.CompactEventProperty;
+import org.apache.streampipes.model.connect.adapter.compact.CreateOptions;
+import org.apache.streampipes.model.connect.adapter.compact.EnrichmentConfig;
+import 
org.apache.streampipes.model.connect.adapter.compact.TransformationConfig;
+import 
org.apache.streampipes.model.connect.rules.TransformationRuleDescription;
+import org.apache.streampipes.model.connect.rules.schema.RenameRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.AddTimestampRuleDescription;
+import 
org.apache.streampipes.model.connect.rules.value.UnitTransformRuleDescription;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CompactAdapterGenerator {
+
+  private final AdapterDescription adapterDescription;
+
+  public CompactAdapterGenerator(AdapterDescription adapterDescription) {
+    this.adapterDescription = adapterDescription;
+  }
+
+  public List<Map<String, Object>> getConfig() {
+    var configs = new ArrayList<Map<String, Object>>();
+    adapterDescription.getConfig().forEach(c -> {
+      configs.add(new CompactConfigGenerator(c).toTemplateValue());
+    });
+    return configs;
+  }
+
+  public Map<String, CompactEventProperty> getSchema() {
+    var map = new HashMap<String, CompactEventProperty>();
+    var originalProperties = new ToOriginalSchemaConverter(
+        adapterDescription.getEventSchema().getEventProperties()
+    ).getTransformedProperties();
+    originalProperties
+        .forEach(ep -> map.put(ep.getRuntimeName(), new CompactEventProperty(
+            ep.getLabel(),
+            ep.getDescription(),
+            ep.getPropertyScope(),
+            ep.getSemanticType()
+        )));
+    return map;
+  }
+
+  public EnrichmentConfig getEnrichmentConfig() {
+    if (hasTimestampEnrichmentRule()) {
+      return new 
EnrichmentConfig(AdapterEnrichmentRuleGenerator.TIMESTAMP_FIELD);
+    } else {
+      return null;
+    }
+  }
+
+  public TransformationConfig getTransformationConfig() {
+    var renameRules = new HashMap<String, String>();
+    var unitTransformRules = new HashMap<String, String>();
+    if (hasTransformationRule()) {
+      if (hasRule(RenameRuleDescription.class)) {
+        var rules = getRules(RenameRuleDescription.class);
+        rules.forEach(rule -> {
+          renameRules.put(rule.getOldRuntimeKey(), rule.getNewRuntimeKey());
+        });
+      } else if (hasRule(UnitTransformRuleDescription.class)) {
+        var rules = getRules(UnitTransformRuleDescription.class);
+        rules.forEach(rule -> {
+          unitTransformRules.put(rule.getRuntimeKey(), 
rule.getToUnitRessourceURL());
+        });
+      }
+    }
+    return new TransformationConfig(renameRules, unitTransformRules);
+  }
+
+  public CreateOptions getCreateOptions() {
+    return new CreateOptions(
+        true,
+        true
+    );
+  }
+
+  private boolean hasTimestampEnrichmentRule() {
+    return hasRule(AddTimestampRuleDescription.class);
+  }
+
+  private boolean hasTransformationRule() {
+    return adapterDescription.getRules().stream()
+        .anyMatch(r -> hasRule(RenameRuleDescription.class) || 
hasRule(UnitTransformRuleDescription.class));
+  }
+
+  private boolean hasRule(Class<? extends TransformationRuleDescription> rule) 
{
+    return adapterDescription.getRules().stream().anyMatch(r -> 
r.getClass().equals(rule));
+  }
+
+  private <T extends TransformationRuleDescription> List<T> getRules(Class<T> 
rule) {
+    return adapterDescription.getRules()
+        .stream()
+        .filter(rule::isInstance)
+        .map(rule::cast)
+        .toList();
+  }
+}
diff --git 
a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/CompactAdapterManagement.java
 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/CompactAdapterManagement.java
index a973a22d85..12db048447 100644
--- 
a/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/CompactAdapterManagement.java
+++ 
b/streampipes-connect-management/src/main/java/org/apache/streampipes/connect/management/management/CompactAdapterManagement.java
@@ -19,6 +19,7 @@
 package org.apache.streampipes.connect.management.management;
 
 import 
org.apache.streampipes.connect.management.compact.generator.AdapterModelGenerator;
+import 
org.apache.streampipes.connect.management.compact.generator.CompactAdapterGenerator;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.connect.adapter.compact.CompactAdapter;
 import org.apache.streampipes.storage.api.IAdapterStorage;
@@ -45,6 +46,22 @@ public class CompactAdapterManagement {
     return adapterDescription;
   }
 
+  public CompactAdapter convertToCompactAdapter(AdapterDescription 
adapterDescription) throws Exception {
+    var generator = new CompactAdapterGenerator(adapterDescription);
+
+    return new CompactAdapter(
+        adapterDescription.getElementId(),
+        adapterDescription.getName(),
+        adapterDescription.getDescription(),
+        adapterDescription.getAppId(),
+        generator.getConfig(),
+        generator.getSchema(),
+        generator.getEnrichmentConfig(),
+        generator.getTransformationConfig(),
+        generator.getCreateOptions()
+    );
+  }
+
   public AdapterDescription convertToAdapterDescription(CompactAdapter 
compactAdapter,
                                                         AdapterDescription 
existingAdapter) throws Exception {
     var adapterDescription = convertToAdapterDescription(compactAdapter);
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactAdapter.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactAdapter.java
index d8a0a93f29..1129736376 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactAdapter.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactAdapter.java
@@ -36,9 +36,12 @@
 
 package org.apache.streampipes.model.connect.adapter.compact;
 
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
 import java.util.List;
 import java.util.Map;
 
+@TsModel
 public record CompactAdapter(
     String id,
     String name,
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
index c0cdd7e6af..479b42b0dc 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
@@ -18,6 +18,9 @@
 
 package org.apache.streampipes.model.connect.adapter.compact;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public record CompactEventProperty(
     String label,
     String description,
diff --git 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/CompactConfigGenerator.java
 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/CompactConfigGenerator.java
new file mode 100644
index 0000000000..3ec54266b7
--- /dev/null
+++ 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/CompactConfigGenerator.java
@@ -0,0 +1,211 @@
+/*
+ * 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.template;
+
+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.FileStaticProperty;
+import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
+import org.apache.streampipes.model.staticproperty.MappingPropertyNary;
+import org.apache.streampipes.model.staticproperty.MappingPropertyUnary;
+import org.apache.streampipes.model.staticproperty.MatchingStaticProperty;
+import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
+import org.apache.streampipes.model.staticproperty.Option;
+import 
org.apache.streampipes.model.staticproperty.RuntimeResolvableGroupStaticProperty;
+import 
org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty;
+import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
+import org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty;
+import org.apache.streampipes.model.staticproperty.StaticProperty;
+import org.apache.streampipes.model.staticproperty.StaticPropertyAlternative;
+import org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives;
+import org.apache.streampipes.model.staticproperty.StaticPropertyGroup;
+import org.apache.streampipes.model.staticproperty.StaticPropertyVisitor;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CompactConfigGenerator implements StaticPropertyVisitor {
+
+  private final Map<String, Object> config;
+  private final StaticProperty staticProperty;
+
+  public CompactConfigGenerator(StaticProperty staticProperty) {
+    this.config = new HashMap<>();
+    this.staticProperty = staticProperty;
+  }
+
+  public Map<String, Object> toTemplateValue() {
+    staticProperty.accept(this);
+    return config;
+  }
+
+  @Override
+  public void visit(AnyStaticProperty property) {
+    addConfig(
+        property,
+        
property.getOptions().stream().filter(Option::isSelected).map(Option::getName).toList()
+    );
+  }
+
+  @Override
+  public void visit(CodeInputStaticProperty codeInputStaticProperty) {
+    addConfig(
+        codeInputStaticProperty,
+        codeInputStaticProperty.getValue()
+    );
+  }
+
+  @Override
+  public void visit(CollectionStaticProperty collectionStaticProperty) {
+    config.put(
+        collectionStaticProperty.getInternalName(),
+        addListEntry(collectionStaticProperty.getMembers())
+    );
+  }
+
+  @Override
+  public void visit(ColorPickerStaticProperty colorPickerStaticProperty) {
+    addConfig(
+        colorPickerStaticProperty,
+        colorPickerStaticProperty.getSelectedColor()
+    );
+  }
+
+  @Override
+  public void visit(FileStaticProperty fileStaticProperty) {
+    addConfig(
+        fileStaticProperty,
+        fileStaticProperty.getLocationPath()
+    );
+  }
+
+  @Override
+  public void visit(FreeTextStaticProperty freeTextStaticProperty) {
+    addConfig(
+        freeTextStaticProperty,
+        freeTextStaticProperty.getValue()
+    );
+  }
+
+  @Override
+  public void visit(MappingPropertyNary mappingPropertyNary) {
+    addConfig(
+        mappingPropertyNary,
+        mappingPropertyNary.getSelectedProperties()
+    );
+  }
+
+  @Override
+  public void visit(MappingPropertyUnary mappingPropertyUnary) {
+    addConfig(
+        mappingPropertyUnary,
+        mappingPropertyUnary.getSelectedProperty()
+    );
+  }
+
+  @Override
+  public void visit(MatchingStaticProperty matchingStaticProperty) {
+    // not supported
+  }
+
+  @Override
+  public void visit(OneOfStaticProperty oneOfStaticProperty) {
+    addConfig(
+        oneOfStaticProperty,
+        
oneOfStaticProperty.getOptions().stream().filter(Option::isSelected).findFirst().map(Option::getName)
+    );
+  }
+
+  @Override
+  public void visit(SecretStaticProperty secretStaticProperty) {
+    config.put(secretStaticProperty.getInternalName(), 
secretStaticProperty.getValue());
+    config.put("encrypted", secretStaticProperty.getEncrypted());
+  }
+
+  @Override
+  public void visit(StaticPropertyAlternative staticPropertyAlternative) {
+
+  }
+
+  @Override
+  public void visit(StaticPropertyAlternatives staticPropertyAlternatives) {
+    var selectedAlternativeOpt = staticPropertyAlternatives.getAlternatives()
+        .stream()
+        .filter(StaticPropertyAlternative::getSelected)
+        .findFirst();
+    if (selectedAlternativeOpt.isPresent()) {
+      var selectedAlternative = selectedAlternativeOpt.get();
+      config.put(staticPropertyAlternatives.getInternalName(), 
selectedAlternative.getInternalName());
+      if (selectedAlternative.getStaticProperty() != null) {
+        var alternative = new 
CompactConfigGenerator(selectedAlternative.getStaticProperty()).toTemplateValue();
+        config.putAll(alternative);
+      }
+    }
+  }
+
+  @Override
+  public void visit(StaticPropertyGroup staticPropertyGroup) {
+    config.putAll(addNestedEntry(staticPropertyGroup.getStaticProperties()));
+  }
+
+  @Override
+  public void visit(SlideToggleStaticProperty slideToggleStaticProperty) {
+    addConfig(
+        slideToggleStaticProperty,
+        slideToggleStaticProperty.isSelected()
+    );
+  }
+
+  @Override
+  public void visit(RuntimeResolvableTreeInputStaticProperty 
treeInputStaticProperty) {
+    addConfig(
+        treeInputStaticProperty,
+        treeInputStaticProperty.getSelectedNodesInternalNames()
+    );
+  }
+
+  @Override
+  public void visit(RuntimeResolvableGroupStaticProperty groupStaticProperty) {
+
+  }
+
+  private void addConfig(StaticProperty staticProperty, Object value) {
+    config.put(staticProperty.getInternalName(), value);
+  }
+
+  public List<Map<String, Object>> addListEntry(List<StaticProperty> 
staticProperties) {
+    return staticProperties.stream()
+        .map(sp -> new CompactConfigGenerator(sp).toTemplateValue())
+        .toList();
+  }
+
+  public Map<String, Object> addNestedEntry(List<StaticProperty> 
staticProperties) {
+    Map<String, Object> entry = new HashMap<>();
+
+    staticProperties.forEach(sp -> {
+      Map<String, Object> groupEntries = new 
CompactConfigGenerator(sp).toTemplateValue();
+      entry.putAll(groupEntries);
+    });
+
+    return entry;
+  }
+}
diff --git 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
index 11ec281927..fbcd30907a 100644
--- 
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
+++ 
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
@@ -27,7 +27,9 @@ import 
org.apache.streampipes.model.staticproperty.MappingPropertyNary;
 import org.apache.streampipes.model.staticproperty.MappingPropertyUnary;
 import org.apache.streampipes.model.staticproperty.MatchingStaticProperty;
 import org.apache.streampipes.model.staticproperty.OneOfStaticProperty;
+import org.apache.streampipes.model.staticproperty.Option;
 import 
org.apache.streampipes.model.staticproperty.RuntimeResolvableGroupStaticProperty;
+import 
org.apache.streampipes.model.staticproperty.RuntimeResolvableOneOfStaticProperty;
 import 
org.apache.streampipes.model.staticproperty.RuntimeResolvableTreeInputStaticProperty;
 import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
 import org.apache.streampipes.model.staticproperty.SlideToggleStaticProperty;
@@ -132,6 +134,10 @@ public class PipelineElementTemplateVisitor implements 
StaticPropertyVisitor {
       String value = getConfigValueAsString(oneOfStaticProperty);
       oneOfStaticProperty.getOptions().forEach(option ->
           option.setSelected(option.getName().equals(value)));
+      if (oneOfStaticProperty instanceof RuntimeResolvableOneOfStaticProperty
+          && oneOfStaticProperty.getOptions().isEmpty()) {
+        oneOfStaticProperty.setOptions(List.of(new Option(value, true)));
+      }
     }
   }
 
@@ -204,7 +210,7 @@ public class PipelineElementTemplateVisitor implements 
StaticPropertyVisitor {
 
   @Override
   public void visit(RuntimeResolvableGroupStaticProperty groupStaticProperty) {
-    // TODO not yet supported
+    // TODO
   }
 
 
@@ -289,29 +295,4 @@ public class PipelineElementTemplateVisitor implements 
StaticPropertyVisitor {
     }
     throw new IllegalArgumentException("Key '" + key + "' not found");
   }
-
-
-//  private String getAsString(StaticProperty sp) {
-//    return configs.get(sp.getInternalName()).toString();
-//  }
-//
-//  private boolean getAsBoolean(StaticProperty sp) {
-//    return 
Boolean.parseBoolean(configs.get(sp.getInternalName()).toString());
-//  }
-//
-//  private Map<String, Object> getAsMap(StaticProperty sp) {
-//    return (Map<String, Object>) configs.get(sp.getInternalName());
-//  }
-//
-//  private Map<String, Object> getAsMap(StaticProperty sp, String subkey) {
-//    return (Map<String, Object>) getAsMap(sp).get(subkey);
-//  }
-//
-//  private Map<String, Object> getAsMap(Map<String, Object> map, String key) {
-//    return (Map<String, Object>) map.get(key);
-//  }
-//
-//  private List<Map<String, Object>> getAsList(StaticProperty sp, String key) 
{
-//    return (List<Map<String, Object>>) getAsMap(sp).get(key);
-//  }
 }
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 0961a8c5c4..3ca4465d29 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
@@ -22,11 +22,13 @@ import 
org.apache.streampipes.commons.exceptions.connect.AdapterException;
 import org.apache.streampipes.commons.prometheus.adapter.AdapterMetricsManager;
 import 
org.apache.streampipes.connect.management.management.AdapterMasterManagement;
 import 
org.apache.streampipes.connect.management.management.AdapterUpdateManagement;
+import 
org.apache.streampipes.connect.management.management.CompactAdapterManagement;
 import org.apache.streampipes.manager.pipeline.PipelineManager;
 import org.apache.streampipes.model.client.user.DefaultRole;
 import org.apache.streampipes.model.client.user.Permission;
 import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.connect.adapter.PipelineUpdateInfo;
+import org.apache.streampipes.model.connect.adapter.compact.CompactAdapter;
 import org.apache.streampipes.model.message.Message;
 import org.apache.streampipes.model.message.Notifications;
 import org.apache.streampipes.model.monitoring.SpLogMessage;
@@ -34,6 +36,7 @@ import org.apache.streampipes.model.util.ElementIdGenerator;
 import org.apache.streampipes.resource.management.PermissionResourceManager;
 import org.apache.streampipes.resource.management.SpResourceManager;
 import org.apache.streampipes.rest.security.AuthConstants;
+import org.apache.streampipes.rest.shared.constants.SpMediaType;
 import org.apache.streampipes.storage.api.IPipelineStorage;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 
@@ -66,7 +69,7 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
   public AdapterResource() {
     super(() -> new AdapterMasterManagement(
         StorageDispatcher.INSTANCE.getNoSqlStore()
-                                  .getAdapterInstanceStorage(),
+            .getAdapterInstanceStorage(),
         new SpResourceManager().manageAdapters(),
         new SpResourceManager().manageDataStreams(),
         AdapterMetricsManager.INSTANCE.getAdapterMetrics()
@@ -93,6 +96,16 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
     return ok(Notifications.success(adapterId));
   }
 
+  @PostMapping(path = "compact", consumes = 
{MediaType.APPLICATION_JSON_VALUE}, produces = {
+      MediaType.APPLICATION_JSON_VALUE,
+      SpMediaType.YAML,
+      SpMediaType.YML
+  })
+  @PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
+  public ResponseEntity<?> convertToCompactAdapter(@RequestBody 
AdapterDescription adapterDescription) throws Exception {
+    return ok(new 
CompactAdapterManagement(List.of()).convertToCompactAdapter(adapterDescription));
+  }
+
   @PutMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = 
MediaType.APPLICATION_JSON_VALUE)
   @PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
   public ResponseEntity<? extends Message> updateAdapter(@RequestBody 
AdapterDescription adapterDescription) {
@@ -108,7 +121,7 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
   }
 
   @PutMapping(path = "pipeline-migration-preflight", consumes = 
MediaType.APPLICATION_JSON_VALUE,
-              produces = MediaType.APPLICATION_JSON_VALUE)
+      produces = MediaType.APPLICATION_JSON_VALUE)
   @PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
   public ResponseEntity<List<PipelineUpdateInfo>> 
performPipelineMigrationPreflight(
       @RequestBody AdapterDescription adapterDescription
@@ -119,17 +132,26 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
     return ok(migrations);
   }
 
-  @GetMapping(path = "/{id}", produces = { MediaType.APPLICATION_JSON_VALUE, 
"application/yaml" })
+  @GetMapping(path = "/{id}", produces = {MediaType.APPLICATION_JSON_VALUE, 
SpMediaType.YAML, SpMediaType.YML})
   @PreAuthorize(AuthConstants.HAS_READ_ADAPTER_PRIVILEGE)
-  public ResponseEntity<?> getAdapter(@PathVariable("id") String adapterId) {
+  public ResponseEntity<?> getAdapter(@PathVariable("id") String adapterId,
+                                      @RequestParam(value = "output",
+                                          defaultValue = "full",
+                                          required = false) String outputMode) 
{
 
     try {
       AdapterDescription adapterDescription = getAdapterDescription(adapterId);
-
-      return ok(adapterDescription);
+      if (outputMode.equalsIgnoreCase("compact")) {
+        return ok(toCompactAdapterDescription(adapterDescription));
+      } else {
+        return ok(adapterDescription);
+      }
     } catch (AdapterException e) {
       LOG.error("Error while getting adapter with id {}", adapterId, e);
       return fail();
+    } catch (Exception e) {
+      LOG.error("Error while transforming adapter {}", adapterId, e);
+      return fail();
     }
   }
 
@@ -164,7 +186,7 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
                                          boolean deleteAssociatedPipelines) {
     List<String> pipelinesUsingAdapter = getPipelinesUsingAdapter(elementId);
     IPipelineStorage pipelineStorageAPI = 
StorageDispatcher.INSTANCE.getNoSqlStore()
-                                                                    
.getPipelineStorageAPI();
+        .getPipelineStorageAPI();
 
     if (pipelinesUsingAdapter.isEmpty()) {
       try {
@@ -178,11 +200,11 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
       List<String> namesOfPipelinesUsingAdapter = pipelinesUsingAdapter
           .stream()
           .map(pipelineId -> pipelineStorageAPI.getElementById(
-                                                   pipelineId)
-                                               .getName())
+                  pipelineId)
+              .getName())
           .collect(Collectors.toList());
       return ResponseEntity.status(HttpStatus.SC_CONFLICT)
-                           .body(String.join(", ", 
namesOfPipelinesUsingAdapter));
+          .body(String.join(", ", namesOfPipelinesUsingAdapter));
     } else {
       PermissionResourceManager permissionResourceManager = new 
PermissionResourceManager();
       // find out the names of pipelines that have an owner and the owner is 
not the current user
@@ -204,16 +226,16 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
           }
           managementService.deleteAdapter(elementId);
           return ok(Notifications.success("Adapter with id: " + elementId
-                                              + " and all pipelines using the 
adapter are deleted."));
+              + " and all pipelines using the adapter are deleted."));
         } catch (Exception e) {
           LOG.error("Error while deleting adapter with id "
-                        + elementId + " and all pipelines using the adapter", 
e);
+              + elementId + " and all pipelines using the adapter", e);
           return ok(Notifications.error(e.getMessage()));
         }
       } else {
         // otherwise, hint the user the names of pipelines using the adapter 
but not owned by the user
         return ResponseEntity.status(HttpStatus.SC_CONFLICT)
-                             .body(String.join(", ", 
namesOfPipelinesNotOwnedByUser));
+            .body(String.join(", ", namesOfPipelinesNotOwnedByUser));
       }
     }
   }
@@ -226,7 +248,7 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
     } catch (AdapterException e) {
       LOG.error("Error while getting all adapters", e);
       return ResponseEntity.status(500)
-                           .build();
+          .build();
     }
   }
 
@@ -234,10 +256,14 @@ public class AdapterResource extends 
AbstractAdapterResource<AdapterMasterManage
     return managementService.getAdapter(adapterId);
   }
 
+  private CompactAdapter toCompactAdapterDescription(AdapterDescription 
adapterDescription) throws Exception {
+    return new 
CompactAdapterManagement(List.of()).convertToCompactAdapter(adapterDescription);
+  }
+
   private List<String> getPipelinesUsingAdapter(String adapterId) {
     return StorageDispatcher.INSTANCE.getNoSqlStore()
-                                     .getPipelineStorageAPI()
-                                     .getPipelinesUsingAdapter(adapterId);
+        .getPipelineStorageAPI()
+        .getPipelinesUsingAdapter(adapterId);
   }
 
 }
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 97dbb7912a..88424c2256 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
@@ -31,6 +31,7 @@ import 
org.apache.streampipes.model.connect.adapter.compact.CompactAdapter;
 import org.apache.streampipes.model.message.Notifications;
 import org.apache.streampipes.resource.management.SpResourceManager;
 import org.apache.streampipes.rest.security.AuthConstants;
+import org.apache.streampipes.rest.shared.constants.SpMediaType;
 import org.apache.streampipes.rest.shared.exception.BadRequestException;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 
@@ -69,8 +70,8 @@ public class CompactAdapterResource extends 
AbstractAdapterResource<AdapterMaste
   @PostMapping(
       consumes = {
           MediaType.APPLICATION_JSON_VALUE,
-          "application/yaml",
-          "application/yml"
+          SpMediaType.YML,
+          SpMediaType.YAML
       }
   )
   @PreAuthorize(AuthConstants.HAS_WRITE_ADAPTER_PRIVILEGE)
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts 
b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
index a18160a427..ff32b390f4 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
@@ -24,6 +24,7 @@ import { Observable } from 'rxjs';
 import { PlatformServicesCommons } from './commons.service';
 import {
     AdapterDescription,
+    CompactAdapter,
     Message,
     PipelineUpdateInfo,
 } from '../model/gen/streampipes-model';
@@ -55,6 +56,15 @@ export class AdapterService {
             );
     }
 
+    convertToCompactAdapter(
+        adapterDescription: AdapterDescription,
+    ): Observable<CompactAdapter> {
+        return this.http.post<CompactAdapter>(
+            this.connectPath + `/master/adapters/compact`,
+            adapterDescription,
+        );
+    }
+
     requestAdapterDescriptions(path: string): Observable<AdapterDescription[]> 
{
         return this.http.get(this.connectPath + path).pipe(
             map(response => {
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 235a32498e..8840666969 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,11 +20,10 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-10-02 
14:54:56.
+// Generated using typescript-generator version 3.2.1263 on 2024-10-08 
10:25:48.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
-        | 'org.apache.streampipes.model.template.PipelineTemplateDescription'
         | 'org.apache.streampipes.model.SpDataStream'
         | 'org.apache.streampipes.model.base.VersionedNamedStreamPipesEntity'
         | 'org.apache.streampipes.model.connect.adapter.AdapterDescription'
@@ -644,28 +643,6 @@ export class AssetExportConfiguration {
     }
 }
 
-export class BoundPipelineElement {
-    connectedTo: BoundPipelineElement[];
-    pipelineElementTemplate: InvocableStreamPipesEntity;
-
-    static fromData(
-        data: BoundPipelineElement,
-        target?: BoundPipelineElement,
-    ): BoundPipelineElement {
-        if (!data) {
-            return data;
-        }
-        const instance = target || new BoundPipelineElement();
-        instance.connectedTo = __getCopyArrayFn(BoundPipelineElement.fromData)(
-            data.connectedTo,
-        );
-        instance.pipelineElementTemplate = InvocableStreamPipesEntity.fromData(
-            data.pipelineElementTemplate,
-        );
-        return instance;
-    }
-}
-
 export class CanvasPosition {
     x: number;
     y: number;
@@ -773,6 +750,64 @@ export class ColorPickerStaticProperty extends 
StaticProperty {
     }
 }
 
+export class CompactAdapter {
+    appId: string;
+    configuration: { [index: string]: any }[];
+    createOptions: CreateOptions;
+    description: string;
+    enrich: EnrichmentConfig;
+    id: string;
+    name: string;
+    schema: { [index: string]: CompactEventProperty };
+    transform: TransformationConfig;
+
+    static fromData(
+        data: CompactAdapter,
+        target?: CompactAdapter,
+    ): CompactAdapter {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new CompactAdapter();
+        instance.appId = data.appId;
+        instance.configuration = __getCopyArrayFn(
+            __getCopyObjectFn(__identity<any>()),
+        )(data.configuration);
+        instance.createOptions = CreateOptions.fromData(data.createOptions);
+        instance.description = data.description;
+        instance.enrich = EnrichmentConfig.fromData(data.enrich);
+        instance.id = data.id;
+        instance.name = data.name;
+        instance.schema = __getCopyObjectFn(CompactEventProperty.fromData)(
+            data.schema,
+        );
+        instance.transform = TransformationConfig.fromData(data.transform);
+        return instance;
+    }
+}
+
+export class CompactEventProperty {
+    description: string;
+    label: string;
+    propertyScope: string;
+    semanticType: string;
+
+    static fromData(
+        data: CompactEventProperty,
+        target?: CompactEventProperty,
+    ): CompactEventProperty {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new CompactEventProperty();
+        instance.description = data.description;
+        instance.label = data.label;
+        instance.propertyScope = data.propertyScope;
+        instance.semanticType = data.semanticType;
+        return instance;
+    }
+}
+
 export class CompactPipeline {
     createOptions: CreateOptions;
     description: string;
@@ -1478,6 +1513,22 @@ export interface EndpointSelectable {
     selectedEndpointUrl: string;
 }
 
+export class EnrichmentConfig {
+    timestamp: string;
+
+    static fromData(
+        data: EnrichmentConfig,
+        target?: EnrichmentConfig,
+    ): EnrichmentConfig {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new EnrichmentConfig();
+        instance.timestamp = data.timestamp;
+        return instance;
+    }
+}
+
 export class ValueSpecification {
     '@class':
         | 'org.apache.streampipes.model.schema.QuantitativeValue'
@@ -3024,32 +3075,6 @@ export class PipelineStatusMessage {
     }
 }
 
-export class PipelineTemplateDescription extends NamedStreamPipesEntity {
-    '@class': 
'org.apache.streampipes.model.template.PipelineTemplateDescription';
-    'boundTo': BoundPipelineElement[];
-    'pipelineTemplateDescription': string;
-    'pipelineTemplateId': string;
-    'pipelineTemplateName': string;
-
-    static 'fromData'(
-        data: PipelineTemplateDescription,
-        target?: PipelineTemplateDescription,
-    ): PipelineTemplateDescription {
-        if (!data) {
-            return data;
-        }
-        const instance = target || new PipelineTemplateDescription();
-        super.fromData(data, instance);
-        instance.boundTo = __getCopyArrayFn(BoundPipelineElement.fromData)(
-            data.boundTo,
-        );
-        instance.pipelineTemplateDescription = 
data.pipelineTemplateDescription;
-        instance.pipelineTemplateId = data.pipelineTemplateId;
-        instance.pipelineTemplateName = data.pipelineTemplateName;
-        return instance;
-    }
-}
-
 export class PipelineTemplateGenerationRequest {
     pipelineDescription: string;
     pipelineName: string;
@@ -3074,37 +3099,6 @@ export class PipelineTemplateGenerationRequest {
     }
 }
 
-export class PipelineTemplateInvocation {
-    '@class': 
'org.apache.streampipes.model.template.PipelineTemplateInvocation';
-    'dataStreamId': string;
-    'kviName': string;
-    'pipelineTemplateDescription': PipelineTemplateDescription;
-    'pipelineTemplateId': string;
-    'staticProperties': StaticPropertyUnion[];
-
-    static 'fromData'(
-        data: PipelineTemplateInvocation,
-        target?: PipelineTemplateInvocation,
-    ): PipelineTemplateInvocation {
-        if (!data) {
-            return data;
-        }
-        const instance = target || new PipelineTemplateInvocation();
-        instance['@class'] = data['@class'];
-        instance.dataStreamId = data.dataStreamId;
-        instance.kviName = data.kviName;
-        instance.pipelineTemplateDescription =
-            PipelineTemplateDescription.fromData(
-                data.pipelineTemplateDescription,
-            );
-        instance.pipelineTemplateId = data.pipelineTemplateId;
-        instance.staticProperties = __getCopyArrayFn(
-            StaticProperty.fromDataUnion,
-        )(data.staticProperties);
-        return instance;
-    }
-}
-
 export class PipelineUpdateInfo {
     canAutoMigrate: boolean;
     migrationInfo: string;
@@ -3960,6 +3954,26 @@ export class TransformOutputStrategy extends 
OutputStrategy {
     }
 }
 
+export class TransformationConfig {
+    measurementUnit: { [index: string]: string };
+    rename: { [index: string]: string };
+
+    static fromData(
+        data: TransformationConfig,
+        target?: TransformationConfig,
+    ): TransformationConfig {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new TransformationConfig();
+        instance.measurementUnit = __getCopyObjectFn(__identity<string>())(
+            data.measurementUnit,
+        );
+        instance.rename = __getCopyObjectFn(__identity<string>())(data.rename);
+        return instance;
+    }
+}
+
 export class TreeInputNode {
     children: TreeInputNode[];
     dataNode: boolean;
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
new file mode 100644
index 0000000000..52b5d4e5f4
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.html
@@ -0,0 +1,36 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" *ngIf="compactAdapter" class="mt-10">
+    <mat-tab-group color="accent" [mat-stretch-tabs]="false">
+        <mat-tab label="YAML">
+            <pre
+                [innerHTML]="compactAdapter | yamlpretty"
+                class="preview-text"
+                [ngStyle]="{ maxHeight: maxHeight }"
+            ></pre>
+        </mat-tab>
+        <mat-tab label="JSON">
+            <pre
+                [innerHTML]="compactAdapter | jsonpretty"
+                class="preview-text"
+                [ngStyle]="{ maxHeight: maxHeight }"
+            ></pre>
+        </mat-tab>
+    </mat-tab-group>
+</div>
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
 
b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.scss
similarity index 76%
copy from 
streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
copy to 
ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.scss
index c0cdd7e6af..c02ba8acc6 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
+++ 
b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
@@ -16,12 +16,15 @@
  *
  */
 
-package org.apache.streampipes.model.connect.adapter.compact;
-
-public record CompactEventProperty(
-    String label,
-    String description,
-    String propertyScope,
-    String semanticType
-) {
+.preview-text {
+    background-color: black;
+    font:
+        9pt Inconsolata,
+        monospace;
+    text-shadow: 0 0 5px #c8c8c8;
+    color: white;
+    padding: 10px;
+    max-width: 100%;
+    overflow-y: scroll;
+    white-space: pre-wrap;
 }
diff --git 
a/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts 
b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.ts
similarity index 50%
copy from ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts
copy to 
ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.ts
index c4633a0fb4..5c742add6f 100644
--- a/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts
+++ 
b/ui/src/app/connect/components/adapter-code-panel/adapter-code-panel.component.ts
@@ -16,26 +16,34 @@
  *
  */
 
-import { SpNavigationItem } from '@streampipes/shared-ui';
+import { Component, Input, OnInit } from '@angular/core';
+import {
+    AdapterDescription,
+    AdapterService,
+    CompactAdapter,
+} from '@streampipes/platform-services';
 
-export class SpAdapterDetailsTabs {
-    public getTabs(elementId: string): SpNavigationItem[] {
-        return [
-            {
-                itemId: 'data',
-                itemTitle: 'Data',
-                itemLink: ['connect', 'details', elementId, 'data'],
-            },
-            {
-                itemId: 'metrics',
-                itemTitle: 'Metrics',
-                itemLink: ['connect', 'details', elementId, 'metrics'],
-            },
-            {
-                itemId: 'logs',
-                itemTitle: 'Logs',
-                itemLink: ['connect', 'details', elementId, 'logs'],
-            },
-        ];
+@Component({
+    selector: 'sp-adapter-code-panel',
+    templateUrl: './adapter-code-panel.component.html',
+    styleUrls: ['./adapter-code-panel.component.scss'],
+})
+export class AdapterCodePanelComponent implements OnInit {
+    @Input()
+    adapterDescription: AdapterDescription;
+
+    @Input()
+    maxHeight = '300px';
+
+    compactAdapter: CompactAdapter;
+
+    constructor(private adapterService: AdapterService) {}
+
+    ngOnInit(): void {
+        this.adapterService
+            .convertToCompactAdapter(this.adapterDescription)
+            .subscribe(res => {
+                this.compactAdapter = res;
+            });
     }
 }
diff --git 
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
 
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
index 2bcfd840d1..b3afa5c944 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
+++ 
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component.html
@@ -18,17 +18,16 @@
 
 <div fxFlex="100" fxLayout="column" class="options-panel">
     <div fxLayout="row" fxFlex="100" fxLayoutAlign="start center">
-        <div class="mr-15" fxLayoutAlign="start center">
-            <mat-icon class="icon">{{ optionIcon }}</mat-icon>
-        </div>
         <div fxFlex fxLayout="column" fxLayoutAlign="center start">
             <div
                 fxFlex="100"
-                class="title"
+                class="title w-100"
                 fxLayout="row"
-                fxLayoutAlign="start center"
+                fxLayoutAlign="start start"
+                fxLayoutGap="15px"
             >
-                <div fxLayoutAlign="start center" class="mr-15">
+                <div class="mr-15" fxLayoutAlign="start center">
+                    <mat-icon class="icon mr-15">{{ optionIcon }}</mat-icon>
                     <mat-checkbox
                         (change)="optionSelectedEmitter.emit($event.checked)"
                         [checked]="isChecked"
@@ -37,15 +36,14 @@
                     >
                     </mat-checkbox>
                 </div>
-                <div fxFlex fxLayout="column">
+                <div fxFlex fxLayout="column" class="w-100">
                     <div>{{ optionTitle }}</div>
-                    <mat-hint class="description">{{
-                        optionDescription
-                    }}</mat-hint>
+                    <mat-hint class="description"
+                        >{{ optionDescription }}
+                    </mat-hint>
+                    <ng-content class="w-100 mt-10"></ng-content>
                 </div>
             </div>
-
-            <ng-content></ng-content>
         </div>
     </div>
 </div>
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 66cbbed55f..f7ff5b8c7b 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
@@ -145,6 +145,21 @@
                 </mat-select>
             </mat-form-field>
         </sp-adapter-options-panel>
+
+        <sp-adapter-options-panel
+            optionTitle="Show code"
+            optionDescription="Show code to programmatically deploy this 
adapter over the API"
+            optionIcon="code"
+            (optionSelectedEmitter)="showCode = $event"
+        >
+            @if (showCode) {
+                <sp-adapter-code-panel
+                    [adapterDescription]="adapterDescription"
+                    class="w-100"
+                >
+                </sp-adapter-code-panel>
+            }
+        </sp-adapter-options-panel>
     </div>
 
     <div fxLayoutAlign="end" style="margin-top: 10px">
diff --git 
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
index e6b97f915a..e8fc266424 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
+++ 
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
@@ -89,6 +89,7 @@ export class StartAdapterConfigurationComponent implements 
OnInit {
     dataLakeTimestampField: string;
 
     startAdapterNow = true;
+    showCode = false;
 
     constructor(
         private dialogService: DialogService,
diff --git 
a/ui/src/app/connect/components/adapter-details/abstract-adapter-details.directive.ts
 
b/ui/src/app/connect/components/adapter-details/abstract-adapter-details.directive.ts
index 394274eb12..1298c1dea9 100644
--- 
a/ui/src/app/connect/components/adapter-details/abstract-adapter-details.directive.ts
+++ 
b/ui/src/app/connect/components/adapter-details/abstract-adapter-details.directive.ts
@@ -28,7 +28,9 @@ import {
     SpBreadcrumbService,
 } from '@streampipes/shared-ui';
 import { SpAdapterDetailsTabs } from './adapter-details-tabs';
+import { Directive } from '@angular/core';
 
+@Directive()
 export abstract class SpAbstractAdapterDetailsDirective {
     currentAdapterId: string;
     tabs: SpNavigationItem[] = [];
diff --git 
a/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.html
 
b/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.html
new file mode 100644
index 0000000000..6a93d34e7f
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.html
@@ -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.
+  ~
+  -->
+
+<sp-basic-nav-tabs
+    [spNavigationItems]="tabs"
+    [activeLink]="'code'"
+    [showBackLink]="true"
+    [backLinkTarget]="['connect']"
+>
+    <div fxLayout="column">
+        @if (adapter) {
+            <div fxLayout="column">
+                <sp-basic-header-title-component
+                    [title]="adapter.name + ' - Data'"
+                ></sp-basic-header-title-component>
+                <sp-adapter-code-panel
+                    [adapterDescription]="adapter"
+                    maxHeight="none"
+                ></sp-adapter-code-panel>
+            </div>
+        }
+    </div>
+</sp-basic-nav-tabs>
diff --git 
a/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.ts
 
b/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.ts
new file mode 100644
index 0000000000..07dfacae09
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-details/adapter-details-code/adapter-details-code.component.ts
@@ -0,0 +1,17 @@
+import { Component, OnInit } from '@angular/core';
+import { SpAbstractAdapterDetailsDirective } from 
'../abstract-adapter-details.directive';
+
+@Component({
+    selector: 'sp-adapter-details-code',
+    templateUrl: './adapter-details-code.component.html',
+})
+export class AdapterDetailsCodeComponent
+    extends SpAbstractAdapterDetailsDirective
+    implements OnInit
+{
+    ngOnInit() {
+        super.onInit();
+    }
+
+    onAdapterLoaded(): void {}
+}
diff --git 
a/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts 
b/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts
index c4633a0fb4..8d3bf34714 100644
--- a/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts
+++ b/ui/src/app/connect/components/adapter-details/adapter-details-tabs.ts
@@ -36,6 +36,11 @@ export class SpAdapterDetailsTabs {
                 itemTitle: 'Logs',
                 itemLink: ['connect', 'details', elementId, 'logs'],
             },
+            {
+                itemId: 'code',
+                itemTitle: 'Code',
+                itemLink: ['connect', 'details', elementId, 'code'],
+            },
         ];
     }
 }
diff --git a/ui/src/app/connect/connect.module.ts 
b/ui/src/app/connect/connect.module.ts
index 0d0e598a31..5d2e8b4756 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -104,6 +104,9 @@ import { AdapterStatusLightComponent } from 
'./components/existing-adapters/adap
 import { SpAdapterDeploymentSettingsComponent } from 
'./components/adapter-configuration/adapter-settings/adapter-deployment-settings/adapter-deployment-settings.component';
 import { SpAdapterDocumentationDialogComponent } from 
'./dialog/adapter-documentation/adapter-documentation-dialog.component';
 import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapter-details-data/adapter-details-data.component';
+import { AdapterCodePanelComponent } from 
'./components/adapter-code-panel/adapter-code-panel.component';
+import { YamlPrettyPrintPipe } from './filter/yaml-pretty-print.pipe';
+import { AdapterDetailsCodeComponent } from 
'./components/adapter-details/adapter-details-code/adapter-details-code.component';
 
 @NgModule({
     imports: [
@@ -184,6 +187,10 @@ import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapte
                                 path: 'logs',
                                 component: SpAdapterDetailsLogsComponent,
                             },
+                            {
+                                path: 'code',
+                                component: AdapterDetailsCodeComponent,
+                            },
                         ],
                     },
                 ],
@@ -193,9 +200,11 @@ import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapte
     ],
     exports: [ErrorMessageComponent],
     declarations: [
+        AdapterCodePanelComponent,
         AdapterConfigurationHeaderComponent,
         AdapterConfigurationComponent,
         AdapterDescriptionComponent,
+        AdapterDetailsCodeComponent,
         AdapterDetailsDataComponent,
         AdapterStartedDialog,
         AdapterStatusLightComponent,
@@ -214,6 +223,7 @@ import { AdapterDetailsDataComponent } from 
'./components/adapter-details/adapte
         ExistingAdaptersComponent,
         AdapterFilterPipe,
         JsonPrettyPrintPipe,
+        YamlPrettyPrintPipe,
         AdapterConfigurationComponent,
         TimestampPipe,
         EditCorrectionValueComponent,
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
 b/ui/src/app/connect/filter/yaml-pretty-print.pipe.ts
similarity index 69%
copy from 
streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
copy to ui/src/app/connect/filter/yaml-pretty-print.pipe.ts
index c0cdd7e6af..88f8b4b459 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/compact/CompactEventProperty.java
+++ b/ui/src/app/connect/filter/yaml-pretty-print.pipe.ts
@@ -16,12 +16,15 @@
  *
  */
 
-package org.apache.streampipes.model.connect.adapter.compact;
+import { Injectable, Pipe, PipeTransform } from '@angular/core';
+import { parse, stringify } from 'yaml';
 
-public record CompactEventProperty(
-    String label,
-    String description,
-    String propertyScope,
-    String semanticType
-) {
+@Pipe({
+    name: 'yamlpretty',
+})
+@Injectable({ providedIn: 'root' })
+export class YamlPrettyPrintPipe implements PipeTransform {
+    transform(obj: any) {
+        return stringify(obj).replace(/ /g, '&nbsp;').replace(/\n/g, '<br/>');
+    }
 }

Reply via email to