streampipes-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t..@apache.org
Subject [incubator-streampipes] 01/01: [STREAMPIPES-22] manual merge from old repo
Date Wed, 18 Dec 2019 17:53:43 GMT
This is an automated email from the ASF dual-hosted git repository.

tex pushed a commit to branch feature_CollectionProperty
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit d11ba496774055cab35b266a5fa1d70214d46657
Author: tex <tex@fzi.de>
AuthorDate: Wed Dec 18 18:53:15 2019 +0100

    [STREAMPIPES-22] manual merge from old repo
---
 .../connect/adapter/sdk/ParameterExtractor.java    |  83 +++-
 .../model/staticproperty/AnyStaticProperty.java    |  10 +-
 .../staticproperty/CollectionStaticProperty.java   |   5 +
 .../model/staticproperty/OneOfStaticProperty.java  |   9 +
 .../RuntimeResolvableAnyStaticProperty.java        |   5 +
 .../RuntimeResolvableOneOfStaticProperty.java      |   4 +
 .../staticproperty/SelectionStaticProperty.java    |  16 +
 .../model/staticproperty/StaticPropertyGroup.java  |  13 +
 .../apache/streampipes/sdk/StaticProperties.java   |  37 ++
 ...AbstractConfigurablePipelineElementBuilder.java |  13 +
 .../apache/streampipes/vocabulary/StreamPipes.java |   4 +
 ui/src/app/connect/connect.module.ts               | 378 ++++++++--------
 .../data-marketplace/data-marketplace.service.ts   | 483 +++++++++++----------
 .../app/connect/model/CollectionStaticProperty.ts  |  40 ++
 ui/src/app/connect/model/GroupStaticProperty.ts    |   4 +
 .../app/connect/model/SelectionStaticProperty.ts   |  86 ++--
 .../static-alternatives.component.css              |   2 +-
 .../static-alternatives.component.html             |  12 +-
 .../static-any-input.component.html                |  66 ++-
 .../static-collection.component.html               |  68 +++
 .../static-collection.component.ts                 |  78 ++++
 .../static-file-input.component.html               |  10 +-
 .../static-free-input.component.html               |   5 +-
 .../static-group/static-group.component.css        |   4 +
 .../static-group/static-group.component.html       |  18 +-
 .../static-mapping-nary.component.css              |   4 +
 .../static-mapping-nary.component.html             |  12 +-
 .../static-mapping-unary.component.html            |  10 +-
 .../static-number-input.component.html             |   1 -
 .../static-one-of-input.component.css              |   3 +
 .../static-one-of-input.component.html             |  46 +-
 .../static-property-util.service.ts                | 126 +++++-
 .../static-property.component.html                 |   5 +
 ...atic-runtime-resolvable-any-input.component.css |   3 +
 ...tic-runtime-resolvable-any-input.component.html |  29 +-
 ...ic-runtime-resolvable-oneof-input.component.css |  16 +
 ...c-runtime-resolvable-oneof-input.component.html |  56 ++-
 .../static-secret-input.component.css              |   5 -
 .../static-secret-input.component.html             |  15 +-
 .../static-text-input.component.css                |   5 -
 .../static-text-input.component.html               |   1 -
 .../static-url-input.component.css                 |   6 -
 .../static-url-input.component.html                |   1 -
 43 files changed, 1202 insertions(+), 595 deletions(-)

diff --git a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/sdk/ParameterExtractor.java b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/sdk/ParameterExtractor.java
index 5e70e1f..75f1fb8 100644
--- a/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/sdk/ParameterExtractor.java
+++ b/streampipes-connect/src/main/java/org/apache/streampipes/connect/adapter/sdk/ParameterExtractor.java
@@ -48,25 +48,32 @@ public class ParameterExtractor {
     }
 
     public String selectedSingleValueInternalName(String internalName) {
-        return ((SelectionStaticProperty) getStaticPropertyByName(internalName))
-                .getOptions()
-                .stream()
-                .filter(Option::isSelected)
-                .findFirst()
-                .get()
-                .getInternalName();
+        return selectedSingleValueInternalName(((SelectionStaticProperty) getStaticPropertyByName(internalName)));
+    }
+
+    private String selectedSingleValueInternalName(SelectionStaticProperty sp) {
+        return  sp.getOptions()
+                    .stream()
+                    .filter(Option::isSelected)
+                    .findFirst()
+                    .get()
+                    .getInternalName();
     }
 
 
     public List<String> selectedMultiValues(String internalName) {
-        return ((SelectionStaticProperty) getStaticPropertyByName(internalName))
-                .getOptions()
-                .stream()
-                .filter(Option::isSelected)
-                .map(Option::getName)
-                .collect(Collectors.toList());
+        return selectedMultiValues((SelectionStaticProperty) getStaticPropertyByName(internalName));
+    }
+
+    public List<String> selectedMultiValues(SelectionStaticProperty sp) {
+        return sp.getOptions()
+                    .stream()
+                    .filter(Option::isSelected)
+                    .map(Option::getName)
+                    .collect(Collectors.toList());
     }
 
+
     public String selectedSingleValueOption(String internalName) {
         return selectedMultiValues(internalName).get(0);
     }
@@ -79,4 +86,54 @@ public class ParameterExtractor {
         }
         return null;
     }
+
+    // Collection
+
+    public List<String> collectionSingleValue(String internalName) {
+        return ((CollectionStaticProperty) getStaticPropertyByName(internalName))
+                .getMembers()
+                .stream()
+                .map(sp -> ((FreeTextStaticProperty) sp).getValue())
+                .collect(Collectors.toList());
+    }
+
+    public <V> List<V> collectionSingleValue(String internalName, Class<V> targetClass) {
+        return ((CollectionStaticProperty) getStaticPropertyByName(internalName))
+                .getMembers()
+                .stream()
+                .map(sp -> typeParser.parse(((FreeTextStaticProperty) sp).getValue(), targetClass))
+                .collect(Collectors.toList());
+    }
+
+    public List<String> collectionSelectedSingleValueInternalName(String internalName) {
+        return ((CollectionStaticProperty) getStaticPropertyByName(internalName))
+                .getMembers()
+                .stream()
+                .map(sp -> selectedSingleValueInternalName(((SelectionStaticProperty) sp)))
+                .collect(Collectors.toList());
+
+    }
+
+    public List<List<String>> collectionSelectedMultiValues(String internalName) {
+        return ((CollectionStaticProperty) getStaticPropertyByName(internalName))
+                .getMembers()
+                .stream()
+                .map(sp -> selectedMultiValues(((SelectionStaticProperty) sp)))
+                .collect(Collectors.toList());
+    }
+
+    public List<String> collectionSelectedSingleValueOption(String internalName) {
+        return collectionSelectedMultiValues(internalName)
+                .stream()
+                .map(list -> list.get(0))
+                .collect(Collectors.toList());
+    }
+
+    public List<ParameterExtractor> collectionGroup(String internalName) {
+        return  ((CollectionStaticProperty) getStaticPropertyByName(internalName))
+                                                .getMembers()
+                                                .stream()
+                                                .map(sp -> new ParameterExtractor(((StaticPropertyGroup) sp).getStaticProperties()))
+                                                .collect(Collectors.toList());
+    }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/AnyStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/AnyStaticProperty.java
index ce8a707..b997f0e 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/AnyStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/AnyStaticProperty.java
@@ -42,13 +42,21 @@ public class AnyStaticProperty extends SelectionStaticProperty {
   }
 
   public AnyStaticProperty(StaticPropertyType staticPropertyType, String internalName,
-                             String label, String description) {
+                           String label, String description) {
     super(staticPropertyType, internalName, label, description);
   }
 
+  public AnyStaticProperty(StaticPropertyType staticPropertyType, String internalName, String label, String
+          description, boolean horizontalRendering) {
+    super(staticPropertyType, internalName, label, description, horizontalRendering);
+  }
+
   public AnyStaticProperty(String internalName, String label, String description) {
     super(StaticPropertyType.AnyStaticProperty, internalName, label, description);
   }
 
+  public AnyStaticProperty(String internalName, String label, String description, boolean horizontalRendering) {
+    super(StaticPropertyType.AnyStaticProperty, internalName, label, description, horizontalRendering);
+  }
 
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CollectionStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CollectionStaticProperty.java
index 9d30b5c..3174a42 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CollectionStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/CollectionStaticProperty.java
@@ -62,6 +62,11 @@ public class CollectionStaticProperty extends StaticProperty {
     this.memberType = memberType;
   }
 
+  public CollectionStaticProperty(String internalName, String label, String description, StaticProperty propertyTemplate) {
+    super(StaticPropertyType.CollectionStaticProperty, internalName, label, description);
+    this.staticPropertyTemplate = propertyTemplate;
+  }
+
   public CollectionStaticProperty(CollectionStaticProperty other) {
     super(other);
     this.members = new Cloner().staticProperties(other.getMembers());
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/OneOfStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/OneOfStaticProperty.java
index 90e4865..dc30073 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/OneOfStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/OneOfStaticProperty.java
@@ -42,6 +42,11 @@ public class OneOfStaticProperty extends SelectionStaticProperty {
     super(staticPropertyType, internalName, label, description);
   }
 
+  public OneOfStaticProperty(StaticPropertyType staticPropertyType, String internalName,
+                             String label, String description, boolean horizontalRendering) {
+    super(staticPropertyType, internalName, label, description, horizontalRendering);
+  }
+
   public OneOfStaticProperty(OneOfStaticProperty other) {
     super(other);
   }
@@ -50,5 +55,9 @@ public class OneOfStaticProperty extends SelectionStaticProperty {
     super(StaticPropertyType.OneOfStaticProperty, internalName, label, description);
   }
 
+  public OneOfStaticProperty(String internalName, String label, String description, boolean horizontalRendering) {
+    super(StaticPropertyType.OneOfStaticProperty, internalName, label, description, horizontalRendering);
+  }
+
 
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableAnyStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableAnyStaticProperty.java
index d7fa958..c4dee18 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableAnyStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableAnyStaticProperty.java
@@ -50,6 +50,11 @@ public class RuntimeResolvableAnyStaticProperty extends AnyStaticProperty {
     super(StaticPropertyType.RuntimeResolvableAnyStaticProperty, internalName, label, description);
   }
 
+  public RuntimeResolvableAnyStaticProperty(String internalName, String label, String description, boolean horizontalRendering) {
+    super(StaticPropertyType.RuntimeResolvableAnyStaticProperty, internalName, label, description, horizontalRendering);
+  }
+
+
   public List<String> getDependsOn() {
     return dependsOn;
   }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableOneOfStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableOneOfStaticProperty.java
index 15a30de..0ab3804 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableOneOfStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/RuntimeResolvableOneOfStaticProperty.java
@@ -50,6 +50,10 @@ public class RuntimeResolvableOneOfStaticProperty extends OneOfStaticProperty {
     super(StaticPropertyType.RuntimeResolvableOneOfStaticProperty, internalName, label, description);
   }
 
+  public RuntimeResolvableOneOfStaticProperty(String internalName, String label, String description, boolean horizontalRendering) {
+    super(StaticPropertyType.RuntimeResolvableOneOfStaticProperty, internalName, label, description, horizontalRendering);
+  }
+
   public List<String> getDependsOn() {
     return dependsOn;
   }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/SelectionStaticProperty.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/SelectionStaticProperty.java
index 3b6816f..79d466f 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/SelectionStaticProperty.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/SelectionStaticProperty.java
@@ -41,6 +41,10 @@ public abstract class SelectionStaticProperty extends StaticProperty {
   @RdfProperty(StreamPipes.HAS_OPTION)
   private List<Option> options;
 
+  @RdfProperty(StreamPipes.IS_HORIZONTAL_RENDERING)
+  private boolean horizontalRendering;
+
+
   public SelectionStaticProperty(StaticPropertyType staticPropertyType) {
     super(staticPropertyType);
     this.options = new ArrayList<>();
@@ -49,6 +53,7 @@ public abstract class SelectionStaticProperty extends StaticProperty {
   public SelectionStaticProperty(SelectionStaticProperty other) {
     super(other);
     this.options = new Cloner().options(other.getOptions());
+    this.horizontalRendering = other.horizontalRendering;
   }
 
   public SelectionStaticProperty(StaticPropertyType staticPropertyType, String internalName, String label, String
@@ -57,6 +62,13 @@ public abstract class SelectionStaticProperty extends StaticProperty {
     this.options = new ArrayList<>();
   }
 
+  public SelectionStaticProperty(StaticPropertyType staticPropertyType, String internalName, String label, String
+          description, boolean horizontalRendering) {
+    super(staticPropertyType, internalName, label, description);
+    this.options = new ArrayList<>();
+    this.horizontalRendering = horizontalRendering;
+  }
+
   public List<Option> getOptions() {
     return options;
   }
@@ -69,4 +81,8 @@ public abstract class SelectionStaticProperty extends StaticProperty {
   {
     return options.add(option);
   }
+
+  public void setHorizontalRendering(boolean horizontalRendering) {
+    this.horizontalRendering = horizontalRendering;
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyGroup.java b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyGroup.java
index 23dc627..8d567b0 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyGroup.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/staticproperty/StaticPropertyGroup.java
@@ -41,6 +41,9 @@ public class StaticPropertyGroup extends StaticProperty {
   @RdfProperty(StreamPipes.SHOW_LABEL)
   private Boolean showLabel;
 
+  @RdfProperty(StreamPipes.IS_HORIZONTAL_RENDERING)
+  private boolean horizontalRendering;
+
   public StaticPropertyGroup() {
     super(StaticPropertyType.StaticPropertyGroup);
   }
@@ -49,12 +52,18 @@ public class StaticPropertyGroup extends StaticProperty {
     super(other);
     this.staticProperties = new Cloner().staticProperties(other.getStaticProperties());
     this.showLabel = other.showLabel;
+    this.horizontalRendering = other.horizontalRendering;
   }
 
   public StaticPropertyGroup(String internalName, String label, String description) {
     super(StaticPropertyType.StaticPropertyGroup, internalName, label, description);
   }
 
+  public StaticPropertyGroup(String internalName, String label, String description, boolean horizontalRendering) {
+    super(StaticPropertyType.StaticPropertyGroup, internalName, label, description);
+    this.horizontalRendering = horizontalRendering;
+  }
+
   public StaticPropertyGroup(String internalName, String label, String description, List<StaticProperty> staticProperties) {
     this(internalName, label, description);
     this.staticProperties = staticProperties;
@@ -67,4 +76,8 @@ public class StaticPropertyGroup extends StaticProperty {
   public void setStaticProperties(List<StaticProperty> staticProperties) {
     this.staticProperties = staticProperties;
   }
+
+  public void setHorizontalRendering(boolean horizontalRendering) {
+    this.horizontalRendering = horizontalRendering;
+  }
 }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
index 652edc9..78ac517 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/StaticProperties.java
@@ -28,6 +28,9 @@ import org.apache.streampipes.model.staticproperty.SecretStaticProperty;
 import org.apache.streampipes.model.staticproperty.StaticProperty;
 import org.apache.streampipes.model.staticproperty.StaticPropertyGroup;
 import org.apache.streampipes.model.staticproperty.SupportedProperty;
+import org.apache.streampipes.model.staticproperty.CollectionStaticProperty;
+import org.apache.streampipes.model.staticproperty.SelectionStaticProperty;
+import org.apache.streampipes.model.staticproperty.StaticPropertyAlternatives;
 import org.apache.streampipes.sdk.helpers.Label;
 import org.apache.streampipes.sdk.utils.Datatypes;
 
@@ -114,4 +117,38 @@ public class StaticProperties {
     return new SecretStaticProperty(label.getInternalId(),
             label.getLabel(), label.getDescription());
   }
+
+  public static CollectionStaticProperty collection(Label label, StaticProperty... sp) {
+    for (StaticProperty staticProperty : sp) {
+      setHorizontalRendering(staticProperty);
+    }
+
+    if (sp.length > 0) {
+      StaticPropertyGroup group = StaticProperties.group(label);
+      group.setHorizontalRendering(true);
+
+      return new CollectionStaticProperty(label.getInternalId(), label.getLabel(),
+              label.getDescription(), group);
+    } else {
+      return new CollectionStaticProperty(label.getInternalId(), label.getLabel(),
+              label.getDescription(), sp[0]);
+    }
+  }
+
+  private static StaticProperty setHorizontalRendering(StaticProperty sp) {
+     if (sp instanceof StaticPropertyGroup) {
+      ((StaticPropertyGroup) sp).setHorizontalRendering(true);
+      ((StaticPropertyGroup) sp).getStaticProperties().stream()
+              .forEach(property -> setHorizontalRendering(property));
+    } else if (sp instanceof SelectionStaticProperty) {
+      ((SelectionStaticProperty) sp).setHorizontalRendering(true);
+    } else if (sp instanceof StaticPropertyAlternatives) {
+      ((StaticPropertyAlternatives) sp).getAlternatives().stream()
+              .forEach(property -> setHorizontalRendering(property.getStaticProperty()));
+
+    }
+
+    return sp;
+  }
+
 }
diff --git a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
index 74b9f4a..b71e9a3 100644
--- a/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
+++ b/streampipes-sdk/src/main/java/org/apache/streampipes/sdk/builder/AbstractConfigurablePipelineElementBuilder.java
@@ -668,6 +668,19 @@ public abstract class AbstractConfigurablePipelineElementBuilder<BU extends
     return me();
   }
 
+  /**
+   * Defines a collection of configuration parameters of the specified staticProperties.
+   * The developer can fill the staticProperties multiply times.
+   * @param label The {@link org.apache.streampipes.sdk.helpers.Label} that describes why this parameter is needed in a
+   *    *              user-friendly manner.
+   * @param staticProperties A list of {@link org.apache.streampipes.model.staticproperty} elements.
+   * @return this
+   */
+  public BU requiredCollection(Label label, StaticProperty... staticProperties) {
+    this.staticProperties.add(StaticProperties.collection(label, staticProperties));
+    return me();
+  }
+
   private FreeTextStaticProperty prepareFreeTextStaticProperty(String internalId, String label, String description, String type) {
     return new FreeTextStaticProperty(internalId,
             label,
diff --git a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
index 5e1e76a..db8c6db 100644
--- a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
+++ b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
@@ -352,4 +352,8 @@ public class StreamPipes {
 
   public static final String SECRET_STATIC_PROPERTY = NS + "SecretStaticProperty";
   public static final String IS_ENCRYPTED = NS + "isEncrypted";
+
+  // UI Rendering
+
+  public static final String IS_HORIZONTAL_RENDERING = NS + "isHorizontalRendering";
 }
diff --git a/ui/src/app/connect/connect.module.ts b/ui/src/app/connect/connect.module.ts
index fe9d12e..d530df5 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -1,188 +1,190 @@
-/*
- * 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 { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { FlexLayoutModule } from '@angular/flex-layout';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import {
-    MatFormFieldModule,
-    MatGridListModule,
-} from '@angular/material';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { BrowserModule } from '@angular/platform-browser';
-
-import { ConnectComponent } from './connect.component';
-import { NewAdapterComponent } from './new-adapter/new-adapter.component';
-
-import { FormatFormComponent } from './format-form/format-form.component';
-import { SelectProtocolComponent } from './select-protocol-component/select-protocol.component';
-
-import { EventPropertyPrimitiveComponent } from './schema-editor/event-property-primitive/event-property-primitive.component';
-import { EventPropertyComponent } from './schema-editor/event-property/event-property.component';
-import { EventSchemaComponent } from './schema-editor/event-schema/event-schema.component';
-
-import { StaticPropertyComponent } from './static-properties/static-property.component';
-
-import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
-
-import { RestService } from './rest.service';
-
-import { MatInputModule } from '@angular/material';
-import { DragulaModule } from 'ng2-dragula';
-import { AdapterStartedDialog } from './new-adapter/component/adapter-started-dialog.component';
-import { DataTypesService } from './schema-editor/data-type.service';
-import { StaticFreeInputComponent } from './static-properties/static-free-input/static-free-input.component';
-import { StaticNumberInputComponent } from './static-properties/static-number-input/static-number-input.component';
-import { StaticPropertyUtilService } from './static-properties/static-property-util.service';
-import { StaticTextInputComponent } from './static-properties/static-text-input/static-text-input.component';
-import { StaticUrlInputComponent } from './static-properties/static-url-input/static-url-input.component';
-import { TransformationRuleService } from './transformation-rule.service';
-import { StaticSecretInputComponent } from "./static-properties/static-secret-input/static-secret-input.component";
-
-import { ProtocolComponent } from './protocol-component/protocol.component';
-
-import { ShepherdService } from '../services/tour/shepherd.service';
-import { ConnectService } from './connect.service';
-import { AdapterDescriptionComponent } from './data-marketplace/adapter-description/adapter-description.component';
-import { DataMarketplaceComponent } from './data-marketplace/data-marketplace.component';
-import { DataMarketplaceService } from './data-marketplace/data-marketplace.service';
-import { FormatComponent } from './format-component/format.component';
-import { FormatListComponent } from './format-list-component/format-list.component';
-import { ProtocolListComponent } from './protocol-list-component/protocol-list.component';
-import { UnitProviderService } from './schema-editor/unit-provider.service';
-import { SelectStaticPropertiesComponent } from './select-static-properties-component/select-static-properties.component';
-import { StaticAnyInput } from './static-properties/static-any-input/static-any-input.component';
-import { StaticOneOfInputComponent } from './static-properties/static-one-of-input/static-one-of-input.component';
-import { IconService } from './new-adapter/icon.service';
-import { StaticFileInputComponent } from './static-properties/static-file-input/static-file-input.component';
-import { StaticFileRestService } from './static-properties/static-file-input/static-file-rest.service';
-import { FileManagementComponent } from './file-management/file-management.component';
-import { FileRestService } from './file-management/service/filerest.service';
-import { StaticRuntimeResolvableAnyInputComponent } from "./static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component";
-import { StaticRuntimeResolvableOneOfInputComponent } from "./static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component";
-import { StaticGroupComponent } from './static-properties/static-group/static-group.component';
-import { StaticAlternativesComponent } from './static-properties/static-alternatives/static-alternatives.component';
-
-
-import { FilterPipe } from '../connect/data-marketplace/filter.pipe';
-import { AdapterExportDialog } from './data-marketplace/adapter-export/adapter-export-dialog.component';
-import { AdapterUploadDialog } from './data-marketplace/adapter-upload/adapter-upload-dialog.component';
-import { EventPropertyListComponent } from './schema-editor/event-property-list/event-property-list.component';
-import { StaticMappingNaryComponent } from './static-properties/static-mapping-nary/static-mapping-nary.component';
-import { StaticMappingUnaryComponent } from './static-properties/static-mapping-unary/static-mapping-unary.component';
-import { TimestampPipe } from './filter/timestamp.pipe';
-import { PlatformServicesModule } from '../platform-services/platform.module';
-
-import { TreeModule } from 'angular-tree-component';
-import { EventSchemaPreviewComponent } from './schema-editor/event-schema-preview/event-schema-preview.component';
-import {EventPropertyRowComponent} from "./schema-editor/event-property-row/event-property-row.component";
-
-
-@NgModule({
-    imports: [
-        BrowserModule,
-        FormsModule,
-        ReactiveFormsModule,
-        CommonModule,
-        FlexLayoutModule,
-        MatGridListModule,
-        CustomMaterialModule,
-        DragulaModule,
-        MatProgressSpinnerModule,
-        MatInputModule,
-        MatFormFieldModule,
-        PlatformServicesModule,
-        TreeModule.forRoot(),
-    ],
-    exports: [
-        StaticPropertyComponent,
-        SelectStaticPropertiesComponent
-    ],
-    declarations: [
-        NewAdapterComponent,
-        SelectProtocolComponent,
-        FormatFormComponent,
-        EventSchemaComponent,
-        EventPropertyPrimitiveComponent,
-        EventPropertyComponent,
-        EventPropertyRowComponent,
-        EventPropertyListComponent,
-        StaticPropertyComponent,
-        AdapterStartedDialog,
-        AdapterExportDialog,
-        AdapterUploadDialog,
-        StaticNumberInputComponent,
-        StaticUrlInputComponent,
-        StaticTextInputComponent,
-        StaticFreeInputComponent,
-        StaticSecretInputComponent,
-        StaticFileInputComponent,
-        StaticMappingNaryComponent,
-        StaticMappingUnaryComponent,
-        TimestampPipe,
-        StaticAnyInput,
-        ProtocolComponent,
-        ProtocolListComponent,
-        FormatListComponent,
-        FormatComponent,
-        DataMarketplaceComponent,
-        AdapterDescriptionComponent,
-        ConnectComponent,
-        SelectStaticPropertiesComponent,
-        StaticOneOfInputComponent,
-        StaticRuntimeResolvableAnyInputComponent,
-        StaticRuntimeResolvableOneOfInputComponent,
-        FileManagementComponent,
-        FilterPipe,
-        EventSchemaPreviewComponent,
-        StaticGroupComponent,
-        StaticAlternativesComponent,
-    ],
-    providers: [
-        RestService,
-        ConnectService,
-        DataTypesService,
-        TransformationRuleService,
-        StaticPropertyUtilService,
-        DataMarketplaceService,
-        IconService,
-        ShepherdService,
-        UnitProviderService,
-        TimestampPipe,
-        FileRestService,
-        StaticFileRestService,
-        {
-            provide: '$state',
-            useFactory: ($injector: any) => $injector.get('$state'),
-            deps: ['$injector'],
-        },
-        {
-            provide: '$timeout',
-            useFactory: ($injector: any) => $injector.get('$timeout'),
-            deps: ['$injector'],
-        },
-        {
-            provide: 'TourProviderService',
-            useFactory: ($injector: any) => $injector.get('TourProviderService'),
-            deps: ['$injector'],
-        },
-    ],
-    entryComponents: [ConnectComponent, AdapterStartedDialog, AdapterExportDialog, AdapterUploadDialog, EventPropertyComponent],
-})
-export class ConnectModule { }
+/*
+ * 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 { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import {
+    MatFormFieldModule,
+    MatGridListModule,
+} from '@angular/material';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { BrowserModule } from '@angular/platform-browser';
+
+import { ConnectComponent } from './connect.component';
+import { NewAdapterComponent } from './new-adapter/new-adapter.component';
+
+import { FormatFormComponent } from './format-form/format-form.component';
+import { SelectProtocolComponent } from './select-protocol-component/select-protocol.component';
+
+import { EventPropertyPrimitiveComponent } from './schema-editor/event-property-primitive/event-property-primitive.component';
+import { EventPropertyComponent } from './schema-editor/event-property/event-property.component';
+import { EventSchemaComponent } from './schema-editor/event-schema/event-schema.component';
+
+import { StaticPropertyComponent } from './static-properties/static-property.component';
+
+import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
+
+import { RestService } from './rest.service';
+
+import { MatInputModule } from '@angular/material';
+import { DragulaModule } from 'ng2-dragula';
+import { AdapterStartedDialog } from './new-adapter/component/adapter-started-dialog.component';
+import { DataTypesService } from './schema-editor/data-type.service';
+import { StaticFreeInputComponent } from './static-properties/static-free-input/static-free-input.component';
+import { StaticNumberInputComponent } from './static-properties/static-number-input/static-number-input.component';
+import { StaticPropertyUtilService } from './static-properties/static-property-util.service';
+import { StaticTextInputComponent } from './static-properties/static-text-input/static-text-input.component';
+import { StaticUrlInputComponent } from './static-properties/static-url-input/static-url-input.component';
+import { TransformationRuleService } from './transformation-rule.service';
+import { StaticSecretInputComponent } from "./static-properties/static-secret-input/static-secret-input.component";
+
+import { ProtocolComponent } from './protocol-component/protocol.component';
+
+import { ShepherdService } from '../services/tour/shepherd.service';
+import { ConnectService } from './connect.service';
+import { AdapterDescriptionComponent } from './data-marketplace/adapter-description/adapter-description.component';
+import { DataMarketplaceComponent } from './data-marketplace/data-marketplace.component';
+import { DataMarketplaceService } from './data-marketplace/data-marketplace.service';
+import { FormatComponent } from './format-component/format.component';
+import { FormatListComponent } from './format-list-component/format-list.component';
+import { ProtocolListComponent } from './protocol-list-component/protocol-list.component';
+import { UnitProviderService } from './schema-editor/unit-provider.service';
+import { SelectStaticPropertiesComponent } from './select-static-properties-component/select-static-properties.component';
+import { StaticAnyInput } from './static-properties/static-any-input/static-any-input.component';
+import { StaticOneOfInputComponent } from './static-properties/static-one-of-input/static-one-of-input.component';
+import { IconService } from './new-adapter/icon.service';
+import { StaticFileInputComponent } from './static-properties/static-file-input/static-file-input.component';
+import { StaticFileRestService } from './static-properties/static-file-input/static-file-rest.service';
+import { FileManagementComponent } from './file-management/file-management.component';
+import { FileRestService } from './file-management/service/filerest.service';
+import { StaticRuntimeResolvableAnyInputComponent } from "./static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component";
+import { StaticRuntimeResolvableOneOfInputComponent } from "./static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component";
+import { StaticGroupComponent } from './static-properties/static-group/static-group.component';
+import { StaticAlternativesComponent } from './static-properties/static-alternatives/static-alternatives.component';
+import {StaticCollectionComponent} from './static-properties/static-collection/static-collection.component';
+
+
+import { FilterPipe } from '../connect/data-marketplace/filter.pipe';
+import { AdapterExportDialog } from './data-marketplace/adapter-export/adapter-export-dialog.component';
+import { AdapterUploadDialog } from './data-marketplace/adapter-upload/adapter-upload-dialog.component';
+import { EventPropertyListComponent } from './schema-editor/event-property-list/event-property-list.component';
+import { StaticMappingNaryComponent } from './static-properties/static-mapping-nary/static-mapping-nary.component';
+import { StaticMappingUnaryComponent } from './static-properties/static-mapping-unary/static-mapping-unary.component';
+import { TimestampPipe } from './filter/timestamp.pipe';
+import { PlatformServicesModule } from '../platform-services/platform.module';
+
+import { TreeModule } from 'angular-tree-component';
+import { EventSchemaPreviewComponent } from './schema-editor/event-schema-preview/event-schema-preview.component';
+import {EventPropertyRowComponent} from "./schema-editor/event-property-row/event-property-row.component";
+
+
+@NgModule({
+    imports: [
+        BrowserModule,
+        FormsModule,
+        ReactiveFormsModule,
+        CommonModule,
+        FlexLayoutModule,
+        MatGridListModule,
+        CustomMaterialModule,
+        DragulaModule,
+        MatProgressSpinnerModule,
+        MatInputModule,
+        MatFormFieldModule,
+        PlatformServicesModule,
+        TreeModule.forRoot(),
+    ],
+    exports: [
+        StaticPropertyComponent,
+        SelectStaticPropertiesComponent
+    ],
+    declarations: [
+        NewAdapterComponent,
+        SelectProtocolComponent,
+        FormatFormComponent,
+        EventSchemaComponent,
+        EventPropertyPrimitiveComponent,
+        EventPropertyComponent,
+        EventPropertyRowComponent,
+        EventPropertyListComponent,
+        StaticPropertyComponent,
+        AdapterStartedDialog,
+        AdapterExportDialog,
+        AdapterUploadDialog,
+        StaticNumberInputComponent,
+        StaticUrlInputComponent,
+        StaticTextInputComponent,
+        StaticFreeInputComponent,
+        StaticSecretInputComponent,
+        StaticFileInputComponent,
+        StaticMappingNaryComponent,
+        StaticMappingUnaryComponent,
+        TimestampPipe,
+        StaticAnyInput,
+        ProtocolComponent,
+        ProtocolListComponent,
+        FormatListComponent,
+        FormatComponent,
+        DataMarketplaceComponent,
+        AdapterDescriptionComponent,
+        ConnectComponent,
+        SelectStaticPropertiesComponent,
+        StaticOneOfInputComponent,
+        StaticRuntimeResolvableAnyInputComponent,
+        StaticRuntimeResolvableOneOfInputComponent,
+        FileManagementComponent,
+        FilterPipe,
+        EventSchemaPreviewComponent,
+        StaticGroupComponent,
+        StaticAlternativesComponent,
+        StaticCollectionComponent,
+    ],
+    providers: [
+        RestService,
+        ConnectService,
+        DataTypesService,
+        TransformationRuleService,
+        StaticPropertyUtilService,
+        DataMarketplaceService,
+        IconService,
+        ShepherdService,
+        UnitProviderService,
+        TimestampPipe,
+        FileRestService,
+        StaticFileRestService,
+        {
+            provide: '$state',
+            useFactory: ($injector: any) => $injector.get('$state'),
+            deps: ['$injector'],
+        },
+        {
+            provide: '$timeout',
+            useFactory: ($injector: any) => $injector.get('$timeout'),
+            deps: ['$injector'],
+        },
+        {
+            provide: 'TourProviderService',
+            useFactory: ($injector: any) => $injector.get('TourProviderService'),
+            deps: ['$injector'],
+        },
+    ],
+    entryComponents: [ConnectComponent, AdapterStartedDialog, AdapterExportDialog, AdapterUploadDialog, EventPropertyComponent],
+})
+export class ConnectModule { }
diff --git a/ui/src/app/connect/data-marketplace/data-marketplace.service.ts b/ui/src/app/connect/data-marketplace/data-marketplace.service.ts
index aba692c..c88b30e 100644
--- a/ui/src/app/connect/data-marketplace/data-marketplace.service.ts
+++ b/ui/src/app/connect/data-marketplace/data-marketplace.service.ts
@@ -1,239 +1,244 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import { Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
-
-
-import { TsonLd } from '../../platform-services/tsonld';
-import { AuthStatusService } from '../../services/auth-status.service';
-import { AdapterDescriptionList } from '../model/connect/AdapterDescriptionList';
-import { AdapterDescription } from '../model/connect/AdapterDescription';
-import { AdapterSetDescription } from '../model/connect/AdapterSetDescription';
-import { GenericAdapterSetDescription } from '../model/connect/GenericAdapterSetDescription';
-import { SpecificAdapterSetDescription } from '../model/connect/SpecificAdapterSetDescription';
-import { AdapterStreamDescription } from '../model/connect/AdapterStreamDescription';
-import { GenericAdapterStreamDescription } from '../model/connect/GenericAdapterStreamDescription';
-import { SpecificAdapterStreamDescription } from '../model/connect/SpecificAdapterStreamDescription';
-import { FreeTextStaticProperty } from '../model/FreeTextStaticProperty';
-import { ProtocolDescription } from '../model/connect/grounding/ProtocolDescription';
-import { ProtocolDescriptionList } from '../model/connect/grounding/ProtocolDescriptionList';
-import { FormatDescription } from '../model/connect/grounding/FormatDescription';
-import { DataStreamDescription } from '../model/DataStreamDescription';
-import { EventSchema } from '../schema-editor/model/EventSchema';
-import { EventPropertyPrimitive } from '../schema-editor/model/EventPropertyPrimitive';
-import { ConnectService } from '../connect.service';
-import { AnyStaticProperty } from '../model/AnyStaticProperty';
-import { Option } from '../model/Option';
-import { RenameRuleDescription} from '../model/connect/rules/RenameRuleDescription';
-import { DeleteRuleDescription} from '../model/connect/rules/DeleteRuleDescription';
-import { AddNestedRuleDescription} from '../model/connect/rules/AddNestedRuleDescription';
-import { MoveRuleDescription} from '../model/connect/rules/MoveRuleDesctiption';
-import { EventPropertyNested} from '../schema-editor/model/EventPropertyNested';
-import {EventPropertyList} from '../schema-editor/model/EventPropertyList';
-import {UUID} from 'angular2-uuid';
-import {DataSetDescription} from '../model/DataSetDescription';
-import {OneOfStaticProperty} from '../model/OneOfStaticProperty';
-import {UnitTransformRuleDescription} from '../model/connect/rules/UnitTransformRuleDescription';
-import {RemoveDuplicatesRuleDescription} from '../model/connect/rules/RemoveDuplicatesRuleDescription';
-import {AddTimestampRuleDescription} from '../model/connect/rules/AddTimestampRuleDescription';
-import {AddValueTransformationRuleDescription} from '../model/connect/rules/AddValueTransformationRuleDescription';
-import {FileStaticProperty} from '../model/FileStaticProperty';
-import {TimestampTransformationRuleDescription} from '../model/connect/rules/TimestampTransformationRuleDescription';
-import {RestApi} from "../../services/rest-api.service";
-import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
-import {AlternativesStaticProperty} from "../model/AlternativesStaticProperty";
-import {GroupStaticProperty} from "../model/GroupStaticProperty";
-import {StaticProperty} from "../model/StaticProperty";
-
-@Injectable()
-export class DataMarketplaceService {
-  private host = '/streampipes-connect/';
-
-  constructor(
-    private http: HttpClient,
-    private authStatusService: AuthStatusService,
-    private connectService: ConnectService,
-    private restApi: RestApi,
-    private tsonLdSerializer: TsonLdSerializerService
-  ) {}
-
-
-  getAdapterDescriptions(): Observable<AdapterDescription[]> {
-      return this.requestAdapterDescriptions('/master/description/adapters');
-  }
-
-  getAdapters(): Observable<AdapterDescription[]> {
-    return this.requestAdapterDescriptions('/master/adapters');
-  }
-
-  getAdapterTemplates(): Observable<AdapterDescription[]> {
-    return this.requestAdapterDescriptions('/master/adapters/template/all');
-  }
-
-  requestAdapterDescriptions(path: string) : Observable<AdapterDescription[]> {
-    return this.http
-      .get(
-        this.host +
-          'api/v1/' +
-          this.authStatusService.email +
-          path
-      )
-      .pipe(map(response => {
-        if(response['@graph'] === undefined) return [];
-        const res: AdapterDescriptionList = this.tsonLdSerializer.fromJsonLd(
-          response,
-          'sp:AdapterDescriptionList'
-        );
-        res.list.forEach(adapterDescription => {
-          adapterDescription.config.sort((a, b) => a.index - b.index);
-          adapterDescription.config.forEach(sp => {
-            this.sortStaticProperties(sp)
-          });
-        });
-        return res.list;
-      }));
-  }
-
-  deleteAdapter(adapter: AdapterDescription): Observable<Object> {
-    return this.deleteRequest(adapter, '/master/adapters/')
-  }
-
-  deleteAdapterTemplate(adapter: AdapterDescription): Observable<Object> {
-      return this.deleteRequest(adapter, '/master/adapters/template/')
-  }
-
-  getAdapterCategories(): Observable<Object> {
-    return this.http.get(
-        this.baseUrl +
-        '/api/v2' +
-        "/categories/adapter"
-    )
-  }
-
-  private deleteRequest(adapter: AdapterDescription, url: String) {
-    return this.http.delete(
-      this.host +
-        'api/v1/' +
-        this.authStatusService.email +
-        url +
-        adapter.couchDbId
-    );
-  }
-
-  getProtocols(): Observable<ProtocolDescription[]> {
-    return this.http
-      .get(
-        this.host +
-          'api/v1/' +
-          this.authStatusService.email +
-          '/master/description/protocols'
-      )
-      .pipe(map(response => {
-        const res = this.tsonLdSerializer.fromJsonLd(
-          response,
-          'sp:ProtocolDescriptionList'
-        );
-        res.list.forEach(protocolDescription => {
-          protocolDescription.config.sort((a, b) => a.index - b.index);
-          protocolDescription.config.forEach(sp => {
-            this.sortStaticProperties(sp)
-          });
-        });
-        return res.list;
-      }));
-  }
-
-  sortStaticProperties(sp: StaticProperty) {
-    if (sp instanceof AlternativesStaticProperty) {
-      sp.alternatives.sort((a, b) => a.index - b.index);
-      sp.alternatives.forEach(a => {
-        if (a.staticProperty instanceof GroupStaticProperty) {
-          a.staticProperty.staticProperties.sort((a, b) => a.index - b.index);
-        }
-      })
-    } else if (sp instanceof GroupStaticProperty) {
-      sp.staticProperties.sort((a, b) => a.index - b.index);
-    }
-  }
-
-  getGenericAndSpecifigAdapterDescriptions(): Observable<
-    Observable<AdapterDescription[]>
-  > {
-    return this.getAdapterDescriptions().pipe(map(adapterDescriptions => {
-      adapterDescriptions = adapterDescriptions.filter(
-        this.connectService.isSpecificDescription
-      );
-
-      return this.getProtocols().pipe(map(protocols => {
-        for (let protocol of protocols) {
-          let newAdapterDescription: AdapterDescription;
-          if (protocol.id.includes('sp:protocol/set')) {
-            newAdapterDescription = new GenericAdapterSetDescription(
-              'http://streampipes.org/genericadaptersetdescription'
-            );
-          } else if (protocol.id.includes('sp:protocol/stream')) {
-            newAdapterDescription = new GenericAdapterStreamDescription(
-              'http://streampipes.org/genericadapterstreamdescription'
-            );
-          }
-          newAdapterDescription.label = protocol.label;
-          newAdapterDescription.description = protocol.description;
-          newAdapterDescription.iconUrl = protocol.iconUrl;
-          newAdapterDescription.uri = newAdapterDescription.id;
-          newAdapterDescription.category = protocol.category;
-
-          if (
-            newAdapterDescription instanceof GenericAdapterSetDescription ||
-            newAdapterDescription instanceof GenericAdapterStreamDescription
-          ) {
-            newAdapterDescription.protocol = protocol;
-          }
-          adapterDescriptions.push(newAdapterDescription);
-        }
-        return adapterDescriptions;
-      }));
-    }));
-  }
-
-  cloneAdapterDescription(toClone: AdapterDescription): AdapterDescription {
-    var result: AdapterDescription;
-
-      if (this.connectService.isGenericDescription(toClone)) {
-          if (this.connectService.isDataStreamDescription(toClone)) {
-              result = Object.assign(new GenericAdapterStreamDescription(toClone.id), toClone);
-          } else {
-              result = Object.assign(new GenericAdapterSetDescription(toClone.id), toClone);
-          }
-      } else {
-          if (this.connectService.isDataStreamDescription(toClone)) {
-              result = Object.assign(new SpecificAdapterStreamDescription(toClone.id), toClone);
-          } else {
-              result = Object.assign(new SpecificAdapterSetDescription(toClone.id), toClone);
-          }
-      }
-
-    return result;
-  }
-
-  private get baseUrl() {
-    return '/streampipes-backend';
-  }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+
+import { TsonLd } from '../../platform-services/tsonld';
+import { AuthStatusService } from '../../services/auth-status.service';
+import { AdapterDescriptionList } from '../model/connect/AdapterDescriptionList';
+import { AdapterDescription } from '../model/connect/AdapterDescription';
+import { AdapterSetDescription } from '../model/connect/AdapterSetDescription';
+import { GenericAdapterSetDescription } from '../model/connect/GenericAdapterSetDescription';
+import { SpecificAdapterSetDescription } from '../model/connect/SpecificAdapterSetDescription';
+import { AdapterStreamDescription } from '../model/connect/AdapterStreamDescription';
+import { GenericAdapterStreamDescription } from '../model/connect/GenericAdapterStreamDescription';
+import { SpecificAdapterStreamDescription } from '../model/connect/SpecificAdapterStreamDescription';
+import { FreeTextStaticProperty } from '../model/FreeTextStaticProperty';
+import { ProtocolDescription } from '../model/connect/grounding/ProtocolDescription';
+import { ProtocolDescriptionList } from '../model/connect/grounding/ProtocolDescriptionList';
+import { FormatDescription } from '../model/connect/grounding/FormatDescription';
+import { DataStreamDescription } from '../model/DataStreamDescription';
+import { EventSchema } from '../schema-editor/model/EventSchema';
+import { EventPropertyPrimitive } from '../schema-editor/model/EventPropertyPrimitive';
+import { ConnectService } from '../connect.service';
+import { AnyStaticProperty } from '../model/AnyStaticProperty';
+import { Option } from '../model/Option';
+import { RenameRuleDescription} from '../model/connect/rules/RenameRuleDescription';
+import { DeleteRuleDescription} from '../model/connect/rules/DeleteRuleDescription';
+import { AddNestedRuleDescription} from '../model/connect/rules/AddNestedRuleDescription';
+import { MoveRuleDescription} from '../model/connect/rules/MoveRuleDesctiption';
+import { EventPropertyNested} from '../schema-editor/model/EventPropertyNested';
+import {EventPropertyList} from '../schema-editor/model/EventPropertyList';
+import {UUID} from 'angular2-uuid';
+import {DataSetDescription} from '../model/DataSetDescription';
+import {OneOfStaticProperty} from '../model/OneOfStaticProperty';
+import {UnitTransformRuleDescription} from '../model/connect/rules/UnitTransformRuleDescription';
+import {RemoveDuplicatesRuleDescription} from '../model/connect/rules/RemoveDuplicatesRuleDescription';
+import {AddTimestampRuleDescription} from '../model/connect/rules/AddTimestampRuleDescription';
+import {AddValueTransformationRuleDescription} from '../model/connect/rules/AddValueTransformationRuleDescription';
+import {FileStaticProperty} from '../model/FileStaticProperty';
+import {TimestampTransformationRuleDescription} from '../model/connect/rules/TimestampTransformationRuleDescription';
+import {RestApi} from "../../services/rest-api.service";
+import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
+import {AlternativesStaticProperty} from "../model/AlternativesStaticProperty";
+import {GroupStaticProperty} from "../model/GroupStaticProperty";
+import {StaticProperty} from "../model/StaticProperty";
+import { CollectionStaticProperty } from "../model/CollectionStaticProperty";
+
+@Injectable()
+export class DataMarketplaceService {
+  private host = '/streampipes-connect/';
+
+  constructor(
+    private http: HttpClient,
+    private authStatusService: AuthStatusService,
+    private connectService: ConnectService,
+    private restApi: RestApi,
+    private tsonLdSerializer: TsonLdSerializerService
+  ) {}
+
+
+  getAdapterDescriptions(): Observable<AdapterDescription[]> {
+      return this.requestAdapterDescriptions('/master/description/adapters');
+  }
+
+  getAdapters(): Observable<AdapterDescription[]> {
+    return this.requestAdapterDescriptions('/master/adapters');
+  }
+
+  getAdapterTemplates(): Observable<AdapterDescription[]> {
+    return this.requestAdapterDescriptions('/master/adapters/template/all');
+  }
+
+  requestAdapterDescriptions(path: string) : Observable<AdapterDescription[]> {
+    return this.http
+      .get(
+        this.host +
+          'api/v1/' +
+          this.authStatusService.email +
+          path
+      )
+      .pipe(map(response => {
+        if(response['@graph'] === undefined) return [];
+        const res: AdapterDescriptionList = this.tsonLdSerializer.fromJsonLd(
+          response,
+          'sp:AdapterDescriptionList'
+        );
+        res.list.forEach(adapterDescription => {
+          adapterDescription.config.sort((a, b) => a.index - b.index);
+          adapterDescription.config.forEach(sp => {
+            this.sortStaticProperties(sp)
+          });
+        });
+        return res.list;
+      }));
+  }
+
+  deleteAdapter(adapter: AdapterDescription): Observable<Object> {
+    return this.deleteRequest(adapter, '/master/adapters/')
+  }
+
+  deleteAdapterTemplate(adapter: AdapterDescription): Observable<Object> {
+      return this.deleteRequest(adapter, '/master/adapters/template/')
+  }
+
+  getAdapterCategories(): Observable<Object> {
+    return this.http.get(
+        this.baseUrl +
+        '/api/v2' +
+        "/categories/adapter"
+    )
+  }
+
+  private deleteRequest(adapter: AdapterDescription, url: String) {
+    return this.http.delete(
+      this.host +
+        'api/v1/' +
+        this.authStatusService.email +
+        url +
+        adapter.couchDbId
+    );
+  }
+
+  getProtocols(): Observable<ProtocolDescription[]> {
+    return this.http
+      .get(
+        this.host +
+          'api/v1/' +
+          this.authStatusService.email +
+          '/master/description/protocols'
+      )
+      .pipe(map(response => {
+        const res = this.tsonLdSerializer.fromJsonLd(
+          response,
+          'sp:ProtocolDescriptionList'
+        );
+        res.list.forEach(protocolDescription => {
+          protocolDescription.config.sort((a, b) => a.index - b.index);
+          protocolDescription.config.forEach(sp => {
+            this.sortStaticProperties(sp)
+          });
+        });
+        return res.list;
+      }));
+  }
+
+  sortStaticProperties(sp: StaticProperty) {
+    if (sp instanceof AlternativesStaticProperty) {
+      sp.alternatives.sort((a, b) => a.index - b.index);
+      sp.alternatives.forEach(a => {
+        if (a.staticProperty instanceof GroupStaticProperty) {
+          a.staticProperty.staticProperties.sort((a, b) => a.index - b.index);
+        } else if (a.staticProperty instanceof CollectionStaticProperty) {
+          this.sortStaticProperties((<CollectionStaticProperty> a.staticProperty).staticPropertyTemplate)
+        }
+      })
+    } else if (sp instanceof GroupStaticProperty) {
+        sp.staticProperties.sort((a, b) => a.index - b.index);
+    } else if (sp instanceof CollectionStaticProperty) {
+        this.sortStaticProperties((<CollectionStaticProperty> sp).staticPropertyTemplate)
+    }
+  }
+
+  getGenericAndSpecifigAdapterDescriptions(): Observable<
+    Observable<AdapterDescription[]>
+  > {
+    return this.getAdapterDescriptions().pipe(map(adapterDescriptions => {
+      adapterDescriptions = adapterDescriptions.filter(
+        this.connectService.isSpecificDescription
+      );
+
+      return this.getProtocols().pipe(map(protocols => {
+        for (let protocol of protocols) {
+          let newAdapterDescription: AdapterDescription;
+          if (protocol.id.includes('sp:protocol/set')) {
+            newAdapterDescription = new GenericAdapterSetDescription(
+              'http://streampipes.org/genericadaptersetdescription'
+            );
+          } else if (protocol.id.includes('sp:protocol/stream')) {
+            newAdapterDescription = new GenericAdapterStreamDescription(
+              'http://streampipes.org/genericadapterstreamdescription'
+            );
+          }
+          newAdapterDescription.label = protocol.label;
+          newAdapterDescription.description = protocol.description;
+          newAdapterDescription.iconUrl = protocol.iconUrl;
+          newAdapterDescription.uri = newAdapterDescription.id;
+          newAdapterDescription.category = protocol.category;
+
+          if (
+            newAdapterDescription instanceof GenericAdapterSetDescription ||
+            newAdapterDescription instanceof GenericAdapterStreamDescription
+          ) {
+            newAdapterDescription.protocol = protocol;
+          }
+          adapterDescriptions.push(newAdapterDescription);
+        }
+        return adapterDescriptions;
+      }));
+    }));
+  }
+
+  cloneAdapterDescription(toClone: AdapterDescription): AdapterDescription {
+    var result: AdapterDescription;
+
+      if (this.connectService.isGenericDescription(toClone)) {
+          if (this.connectService.isDataStreamDescription(toClone)) {
+              result = Object.assign(new GenericAdapterStreamDescription(toClone.id), toClone);
+          } else {
+              result = Object.assign(new GenericAdapterSetDescription(toClone.id), toClone);
+          }
+      } else {
+          if (this.connectService.isDataStreamDescription(toClone)) {
+              result = Object.assign(new SpecificAdapterStreamDescription(toClone.id), toClone);
+          } else {
+              result = Object.assign(new SpecificAdapterSetDescription(toClone.id), toClone);
+          }
+      }
+
+    return result;
+  }
+
+  private get baseUrl() {
+    return '/streampipes-backend';
+  }
+}
diff --git a/ui/src/app/connect/model/CollectionStaticProperty.ts b/ui/src/app/connect/model/CollectionStaticProperty.ts
new file mode 100644
index 0000000..138e689
--- /dev/null
+++ b/ui/src/app/connect/model/CollectionStaticProperty.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 FZI Forschungszentrum Informatik
+ *
+ * Licensed 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 {RdfsClass} from '../../platform-services/tsonld/RdfsClass';
+import {RdfProperty} from '../../platform-services/tsonld/RdfsProperty';
+import {StaticProperty} from './StaticProperty';
+
+@RdfsClass('sp:CollectionStaticProperty')
+export class CollectionStaticProperty extends StaticProperty {
+
+    @RdfProperty('sp:hasStaticProperty')
+    public staticPropertyTemplate: StaticProperty;
+
+    @RdfProperty('sp:member')
+    public members: StaticProperty [];
+
+    @RdfProperty('sp:memberType')
+    public memberType: String;
+
+    constructor(id: string) {
+        super();
+        this.id = id;
+    }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/connect/model/GroupStaticProperty.ts b/ui/src/app/connect/model/GroupStaticProperty.ts
index ead4d01..2b5562e 100644
--- a/ui/src/app/connect/model/GroupStaticProperty.ts
+++ b/ui/src/app/connect/model/GroupStaticProperty.ts
@@ -29,6 +29,10 @@ export class GroupStaticProperty extends StaticProperty {
     @RdfProperty('sp:showLabel')
     public showLabel: boolean;
 
+    //TODO remove setting true, if serialization is fixed
+    @RdfProperty('sp:horizontalRendering')
+    public horizontalRendering: boolean = true;
+
     constructor(id: string) {
         super();
         this.id = id;
diff --git a/ui/src/app/connect/model/SelectionStaticProperty.ts b/ui/src/app/connect/model/SelectionStaticProperty.ts
index b5585a4..416a67f 100644
--- a/ui/src/app/connect/model/SelectionStaticProperty.ts
+++ b/ui/src/app/connect/model/SelectionStaticProperty.ts
@@ -1,41 +1,45 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import { RdfId } from '../../platform-services/tsonld/RdfId';
-import { RdfProperty } from '../../platform-services/tsonld/RdfsProperty';
-import { RdfsClass } from '../../platform-services/tsonld/RdfsClass';
-import { StaticProperty } from './StaticProperty';
-import { Option } from './Option';
-
-@RdfsClass('sp:SelectionStaticProperty')
-export class SelectionStaticProperty extends StaticProperty {
-
-  @RdfProperty('sp:hasValue')
-  public value: string;
-
-  @RdfProperty('sp:requiredDomainProperty')
-  public requiredDomainProperty: string;
-
-  @RdfProperty('sp:hasOption')
-  public options: Option[] = [];
-
-  constructor(id: string) {
-    super();
-    this.id = id;
-  }
-}
+/*
+ * 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 { RdfId } from '../../platform-services/tsonld/RdfId';
+import { RdfProperty } from '../../platform-services/tsonld/RdfsProperty';
+import { RdfsClass } from '../../platform-services/tsonld/RdfsClass';
+import { StaticProperty } from './StaticProperty';
+import { Option } from './Option';
+
+@RdfsClass('sp:SelectionStaticProperty')
+export class SelectionStaticProperty extends StaticProperty {
+
+  @RdfProperty('sp:hasValue')
+  public value: string;
+
+  @RdfProperty('sp:requiredDomainProperty')
+  public requiredDomainProperty: string;
+
+  @RdfProperty('sp:hasOption')
+  public options: Option[] = [];
+
+  //TODO remove setting true, if serialization is fixed
+  @RdfProperty('sp:horizontalRendering')
+  public horizontalRendering: boolean = true;
+
+  constructor(id: string) {
+    super();
+    this.id = id;
+  }
+}
diff --git a/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.css b/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.css
index 5d29c51..71ba43d 100644
--- a/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.css
+++ b/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.css
@@ -31,7 +31,7 @@ form {
 }
 
 .content {
-    margin-top: 20px;
+    margin-left: 10px;
 }
 
 .radio-group {
diff --git a/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.html b/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.html
index 8ae9a3d..088738c 100644
--- a/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.html
+++ b/ui/src/app/connect/static-properties/static-alternatives/static-alternatives.component.html
@@ -16,12 +16,13 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-        <p>{{staticProperty.label}}: </p>
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+    <div>
+        <p>{{staticProperty.label}}: <br>
+            <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+        </p>
     </div>
     <div fxFlex fxLayout="column" class="content">
-        <div>{{staticProperty.description}}</div>
         <div>
             <mat-radio-group  *ngIf="staticProperty.alternatives.length > 1"
                     class="radio-group" (change)="radioSelectionChange($event)" required>
@@ -47,7 +48,8 @@
                      {{alternative.label}}
                  </div>
 
-                <div class="sp-blue-border" style="padding-top: 0px; padding-bottom: 0px;  padding-left: 10px;">
+                <div class="sp-blue-border" style="padding-top: 0px; padding-bottom: 0px;
+                                                   padding-left: 10px; padding-right: 10px">
                     <app-static-property [adapterId]="adapterId" [eventSchema]="eventSchema"
                                          [staticProperty]="alternative.staticProperty" (validateEmitter)="valueChange($event)"
                                          class="test fullWidth">
diff --git a/ui/src/app/connect/static-properties/static-any-input/static-any-input.component.html b/ui/src/app/connect/static-properties/static-any-input/static-any-input.component.html
index 77ec16e..057bb1d 100644
--- a/ui/src/app/connect/static-properties/static-any-input/static-any-input.component.html
+++ b/ui/src/app/connect/static-properties/static-any-input/static-any-input.component.html
@@ -1,22 +1,46 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div fxLayout="column">
-    <p>{{staticProperty.label}}: </p>
-    <mat-checkbox *ngFor="let option of staticProperty.options" [(ngModel)]="option.selected">{{option.name}}</mat-checkbox>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
+        <div>
+            <p>{{staticProperty.label}}: <br>
+                <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+            </p>
+        </div>
+        <mat-checkbox *ngFor="let option of staticProperty.options" [(ngModel)]="option.selected" style="margin-left: 10px;">
+            {{option.name}}
+        </mat-checkbox>
+
+    </div>
+
+    <div *ngIf="staticProperty.horizontalRendering">
+        <mat-form-field style="width: 100%">
+            <mat-label>{{staticProperty.label}}</mat-label>
+            <mat-select multiple>
+                <mat-option *ngFor="let option of staticProperty.options" [value]="option.id"
+                            (click)="select(option.id)">
+                    <label style="font-weight: normal">
+                        {{option.name}}
+                    </label>
+                </mat-option>
+            </mat-select>
+            <mat-hint>{{staticProperty.description}}</mat-hint>
+        </mat-form-field>
+    </div>
 </div>
\ No newline at end of file
diff --git a/ui/src/app/connect/static-properties/static-collection/static-collection.component.html b/ui/src/app/connect/static-properties/static-collection/static-collection.component.html
new file mode 100644
index 0000000..44c3609
--- /dev/null
+++ b/ui/src/app/connect/static-properties/static-collection/static-collection.component.html
@@ -0,0 +1,68 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+
+    <div>
+        <p>{{staticProperty.label}}: <br>
+            <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+        </p>
+    </div>
+
+    <div fxLayout="row" fxLayoutAlign="space-between center" *ngFor="let property of staticProperty.members; let i = index">
+        <div fxFlex="grow">
+            <app-static-property [adapterId]="adapterId"
+                                 [eventSchema]="eventSchema"
+                                 [staticProperty]="property"
+                                 (validateEmitter)="valueChange($event)">
+            </app-static-property>
+        </div>
+        <div fxFlex="nogrow" style="width: 50px" fxLayout="row" fxLayoutAlign="end center">
+            <button mat-icon-button class="icon-button" (click)="remove(i)">
+                    <mat-icon class="icon">remove</mat-icon>
+            </button>
+        </div>
+    </div>
+
+
+    <div fxLayout="row" fxLayoutAlign="space-between center">
+        <div  fxFlex="grow" style="pointer-events: none; opacity: 0.4;">
+            <app-static-property
+                                [adapterId]="adapterId"
+                                [eventSchema]="eventSchema"
+                                [staticProperty]="staticProperty.staticPropertyTemplate"
+                                (validateEmitter)="valueChange($event)">
+            </app-static-property>
+        </div>
+        <div fxFlex="nogrow" style="width: 50px" fxLayout="row" fxLayoutAlign="end center">
+            <button mat-icon-button class="icon-button" (click)="add()">
+                <mat-icon class="icon">add</mat-icon>
+            </button>
+        </div>
+    </div>
+
+
+</div>
+
+
+
+
+
+
+
+
diff --git a/ui/src/app/connect/static-properties/static-collection/static-collection.component.ts b/ui/src/app/connect/static-properties/static-collection/static-collection.component.ts
new file mode 100644
index 0000000..a447352
--- /dev/null
+++ b/ui/src/app/connect/static-properties/static-collection/static-collection.component.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import {Component, EventEmitter, Input, Output} from '@angular/core';
+import {ConfigurationInfo} from '../../model/message/ConfigurationInfo';
+import {StaticProperty} from '../../model/StaticProperty';
+import {CollectionStaticProperty} from '../../model/CollectionStaticProperty';
+import {EventSchema} from '../../schema-editor/model/EventSchema';
+import {StaticPropertyUtilService} from '../static-property-util.service';
+
+
+@Component({
+    selector: 'app-static-collection',
+    templateUrl: './static-collection.component.html',
+    styleUrls: ['./static-collection.component.css']
+})
+export class StaticCollectionComponent {
+
+    @Input() staticProperty: StaticProperty;
+    @Input() adapterId: string;
+    @Input() eventSchema: EventSchema;
+
+    @Output() inputEmitter: EventEmitter<Boolean> = new EventEmitter<Boolean>();
+    @Output() updateEmitter: EventEmitter<ConfigurationInfo> = new EventEmitter();
+
+
+
+    private hasInput: Boolean;
+
+    constructor(private staticPropertyUtil: StaticPropertyUtilService) {
+
+    }
+
+
+    valueChange(inputValue) {
+        if ((<CollectionStaticProperty> this.staticProperty).members !== undefined) {
+          let property = (<CollectionStaticProperty> this.staticProperty).members.find(member => member.isValid == false);
+          property === undefined ? this.hasInput = true : this.hasInput = false;
+        } else {
+          this.hasInput = false;
+        }
+
+        this.inputEmitter.emit(this.hasInput);
+        this.emitUpdate(this.hasInput);
+    }
+
+    emitUpdate(valid) {
+        this.updateEmitter.emit(new ConfigurationInfo(this.staticProperty.internalName, valid));
+    }
+
+    add() {
+        if (   (<CollectionStaticProperty> (this.staticProperty)).members === undefined) {
+            (<CollectionStaticProperty> (this.staticProperty)).members = [];
+        }
+        let clone = this.staticPropertyUtil.clone((<CollectionStaticProperty> (this.staticProperty)).staticPropertyTemplate);
+        (<CollectionStaticProperty> (this.staticProperty)).members.push(clone)
+    }
+
+    remove(i) {
+        (<CollectionStaticProperty> (this.staticProperty)).members.splice(i,1).slice(0);
+    }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/connect/static-properties/static-file-input/static-file-input.component.html b/ui/src/app/connect/static-properties/static-file-input/static-file-input.component.html
index 56edd07..b8425d5 100644
--- a/ui/src/app/connect/static-properties/static-file-input/static-file-input.component.html
+++ b/ui/src/app/connect/static-properties/static-file-input/static-file-input.component.html
@@ -16,17 +16,11 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-
-    <div fxFlex="20">
-        <p>{{staticProperty.label}}: </p>
-    </div>
+<div id="formWrapper" fxFlex="100" fxLayout="row">
     <div fxFlex fxLayout="row">
         <form fxFlex>
 
-
-
-            <mat-form-field style="width: 75%" (click)="fileInput.click();">
+            <mat-form-field style="width: 95%" (click)="fileInput.click();">
                 <input  matInput placeholder="{{staticProperty.label}}" disabled (value)="fileName">
                 <input #fileInput type="file" style="display:none;"
                        (change)="handleFileInput($event.target.files)">
diff --git a/ui/src/app/connect/static-properties/static-free-input/static-free-input.component.html b/ui/src/app/connect/static-properties/static-free-input/static-free-input.component.html
index 7570185..a6b83a2 100644
--- a/ui/src/app/connect/static-properties/static-free-input/static-free-input.component.html
+++ b/ui/src/app/connect/static-properties/static-free-input/static-free-input.component.html
@@ -16,10 +16,7 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-    <p>{{staticProperty.label}}: </p>
-    </div>
+<div id="formWrapper" fxFlex="100" fxLayout="column">
     <div fxFlex fxLayout="row">
         <form fxFlex [formGroup]="freeTextForm">
             <mat-form-field fxFlex>
diff --git a/ui/src/app/connect/static-properties/static-group/static-group.component.css b/ui/src/app/connect/static-properties/static-group/static-group.component.css
index 519232f..20de946 100644
--- a/ui/src/app/connect/static-properties/static-group/static-group.component.css
+++ b/ui/src/app/connect/static-properties/static-group/static-group.component.css
@@ -19,4 +19,8 @@
 .padding {
     padding-top: 5px;
     padding-bottom: 5px;
+}
+
+.fullWidth {
+    width: 100%;
 }
\ No newline at end of file
diff --git a/ui/src/app/connect/static-properties/static-group/static-group.component.html b/ui/src/app/connect/static-properties/static-group/static-group.component.html
index dbcc25b..161646b 100644
--- a/ui/src/app/connect/static-properties/static-group/static-group.component.html
+++ b/ui/src/app/connect/static-properties/static-group/static-group.component.html
@@ -16,9 +16,23 @@
   ~
   -->
 
-<div *ngFor="let property of staticProperty.staticProperties" class="padding">
-    <app-static-property [adapterId]="adapterId" [staticProperties]="staticProperties" [eventSchema]="eventSchema"
+<div *ngIf="!staticProperty.horizontalRendering" class="padding" fxLayout="column">
+    <app-static-property *ngFor="let property of staticProperty.staticProperties"
+                         [adapterId]="adapterId" [staticProperties]="staticProperties" [eventSchema]="eventSchema"
                          [staticProperty]="property" (validateEmitter)="valueChange($event)" class="test fullWidth">
     </app-static-property>
+</div>
+
+
+<div *ngIf="staticProperty.horizontalRendering"  class="padding" fxLayout="row" fxLayoutAlign="space-between center">
+    <ng-container *ngFor="let property of staticProperty.staticProperties; let i = index">
+        <span *ngIf="i > 0" style="margin-left: 10px;"></span>
+        <app-static-property
+                [adapterId]="adapterId" [staticProperties]="staticProperties" [eventSchema]="eventSchema"
+                [staticProperty]="property" (validateEmitter)="valueChange($event)" class="test fullWidth">
+        </app-static-property>
+    </ng-container>
 
 </div>
+
+
diff --git a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.css b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.css
index 565a1d7..60748fb 100644
--- a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.css
+++ b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.css
@@ -29,3 +29,7 @@ form {
     float: left;
 }
 
+.description {
+    font-size: 10px;
+}
+
diff --git a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.html b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.html
index 1bd43b2..66bb2f6 100644
--- a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.html
+++ b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.html
@@ -16,16 +16,18 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
+<div id="formWrapper" fxFlex="100" fxLayout="column">
     <div fxFlex="20">
-    <p>{{staticProperty.label}}: </p>
+        <p>{{staticProperty.label}}: <br>
+            <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+        </p>
     </div>
     <div fxFlex fxLayout="row">
-        <form fxFlex [formGroup]="freeTextForm">
+        <form fxFlex [formGroup]="freeTextForm" style="padding-left: 10px;">
             <mat-form-field fxFlex>
                 <input fxFlex id="{{ 'input-' + staticProperty.label.toLowerCase() }}" matInput [placeholder]="staticProperty.label" [(ngModel)]="staticPropertyUtil.asFreeTextStaticProperty(staticProperty).value"
-                    formControlName="freeStaticText" (ngModelChange)="valueChange(staticPropertyUtil.asFreeTextStaticProperty(staticProperty).value)"
-                    required>
+                       formControlName="freeStaticText" (ngModelChange)="valueChange(staticPropertyUtil.asFreeTextStaticProperty(staticProperty).value)"
+                       required>
 
                 <mat-error *ngIf="!hasInput">
                     {{errorMessage}}
diff --git a/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.html b/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.html
index 64a04a0..3212128 100644
--- a/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.html
+++ b/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.html
@@ -16,12 +16,14 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-    <p>{{staticProperty.label}}: </p>
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+    <div>
+        <p>{{staticProperty.label}}: <br>
+            <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+        </p>
     </div>
     <div fxFlex fxLayout="row">
-        <form fxFlex [formGroup]="unaryTextForm">
+        <form fxFlex [formGroup]="unaryTextForm" style="padding-left: 10px">
             <mat-form-field class="example-full-width">
                 <!--<mat-form-field class="example-full-width">-->
                 <mat-select [placeholder]="staticProperty.label">
diff --git a/ui/src/app/connect/static-properties/static-number-input/static-number-input.component.html b/ui/src/app/connect/static-properties/static-number-input/static-number-input.component.html
index b2a4f55..be5de95 100644
--- a/ui/src/app/connect/static-properties/static-number-input/static-number-input.component.html
+++ b/ui/src/app/connect/static-properties/static-number-input/static-number-input.component.html
@@ -17,7 +17,6 @@
   -->
 
 <div id="formWrapper">
-    <p>{{staticProperty.label}}: </p>
     <form [formGroup]="freeTextForm">
         <mat-form-field>
             <input class="example-full-width" matInput id="{{ 'input-' + staticProperty.label.toLowerCase() }}" [placeholder]="staticProperty.label" [(ngModel)]="staticPropertyUtil.asFreeTextStaticProperty(staticProperty).value"
diff --git a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.css b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.css
index 0b1dc9e..6835726 100644
--- a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.css
+++ b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.css
@@ -29,3 +29,6 @@
     background-color: rgb(27, 20, 100);
 }
 
+.description {
+    font-size: 10px;
+}
diff --git a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
index 04c42d7..d77c554 100644
--- a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
+++ b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
@@ -16,18 +16,40 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-        <p>{{staticProperty.label}}: </p>
-    </div>
-    <div fxFlex fxLayout="row">
-        <div fxLayout="column">
-            <mat-radio-button *ngFor="let option of staticProperty.options" style="margin-top: -10px"
-                              (click)="select(option.id)" [checked]="option.selected">
-                <label style="font-weight: normal; padding-top: 8px;">
-                    {{option.name}}
-                </label>
-            </mat-radio-button>
+
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
+        <div>
+            <p>{{staticProperty.label}}: <br>
+                <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+            </p>
+        </div>
+        <div fxFlex fxLayout="row">
+            <div fxLayout="column" style="margin-left: 10px">
+                <mat-radio-button *ngFor="let option of staticProperty.options" style="margin-top: -10px"
+                                  (click)="select(option.id)" [checked]="option.selected">
+                    <label style="font-weight: normal">
+                        {{option.name}}
+                    </label>
+                </mat-radio-button>
+            </div>
         </div>
     </div>
+
+    <div *ngIf="staticProperty.horizontalRendering">
+        <mat-form-field style="width: 100%">
+            <mat-label>{{staticProperty.label}}</mat-label>
+            <mat-select>
+                <mat-option *ngFor="let option of staticProperty.options" [value]="option.id"
+                            (click)="select(option.id)">
+                    <label style="font-weight: normal">
+                        {{option.name}}
+                    </label>
+                </mat-option>
+            </mat-select>
+            <mat-hint>{{staticProperty.description}}</mat-hint>
+        </mat-form-field>
+    </div>
+
 </div>
diff --git a/ui/src/app/connect/static-properties/static-property-util.service.ts b/ui/src/app/connect/static-properties/static-property-util.service.ts
index 23473ed..0d09746 100644
--- a/ui/src/app/connect/static-properties/static-property-util.service.ts
+++ b/ui/src/app/connect/static-properties/static-property-util.service.ts
@@ -20,11 +20,131 @@ import { Injectable } from '@angular/core';
 import { StaticProperty } from '../model/StaticProperty';
 import { FreeTextStaticProperty } from '../model/FreeTextStaticProperty';
 import {SecretStaticProperty} from "../model/SecretStaticProperty";
+import {CollectionStaticProperty} from '../model/CollectionStaticProperty';
+import { FileStaticProperty } from "../model/FileStaticProperty";
+import { AnyStaticProperty } from "../model/AnyStaticProperty";
+import { MappingPropertyUnary } from "../model/MappingPropertyUnary";
+import { OneOfStaticProperty } from "../model/OneOfStaticProperty";
+import { MappingPropertyNary } from "../model/MappingPropertyNary";
+import { RuntimeResolvableOneOfStaticProperty } from "../model/RuntimeResolvableOneOfStaticProperty";
+import { RuntimeResolvableAnyStaticProperty } from "../model/RuntimeResolvableAnyStaticProperty";
+import { GroupStaticProperty } from "../model/GroupStaticProperty";
+import { AlternativesStaticProperty } from "../model/AlternativesStaticProperty";
+import { AlternativeStaticProperty } from "../model/AlternativeStaticProperty";
+import { Option } from "../model/Option";
+import { URI } from "../model/URI";
+
+
 @Injectable()
+export class StaticPropertyUtilService{
 
+    public clone(val: StaticProperty) {
+        let clone;
+        let id = 'urn:streampipes.org:spi::' + this.generateID(6);
 
+        if (val instanceof FreeTextStaticProperty) {
+            clone = new FreeTextStaticProperty(id);
+            clone.value = val.value;
+            clone.requiredDomainProperty = val.requiredDomainProperty;
+        }
+        else if (val instanceof FileStaticProperty) {
+            clone = new FileStaticProperty(id);
+            clone.endpointUrl = val.endpointUrl;
+            clone.locationPath = val.locationPath;
+        }
+        else if (val instanceof MappingPropertyUnary) {
+            clone = new MappingPropertyUnary(id);
+            clone.requirementSelector = val.requirementSelector;
+            clone.mapsFromOptions = val.mapsFromOptions;
+            clone.propertyScope = val.propertyScope;
+            clone.selectedProperties = val.selectedProperties;
+        }
+        else if (val instanceof MappingPropertyNary) {
+            clone = new MappingPropertyNary(id);
+            clone.requirementSelector = val.requirementSelector;
+            clone.mapsFromOptions = val.mapsFromOptions;
+            clone.propertyScope = val.propertyScope;
+            clone.selectedProperty = val.selectedProperty;
+        }
+        else if (val instanceof SecretStaticProperty) {
+            clone = new SecretStaticProperty(id);
+            clone.value = val.value;
+            clone.isEncrypted = val.isEncrypted;
+        }
+        else if (val instanceof GroupStaticProperty) {
+            clone = new GroupStaticProperty(id);
+            clone.staticProperties = val.staticProperties.map(elem => this.clone(elem));
+            clone.showLabel = val.showLabel;
+            clone.horizontalRendering = val.horizontalRendering;
+          }
+        else if (val instanceof AlternativesStaticProperty) {
+            clone = new AlternativesStaticProperty(id);
+            clone.alternatives = val.alternatives.map(elem => this.clone(elem));
+        }
+        else if (val instanceof AlternativeStaticProperty) {
+            clone = new AlternativeStaticProperty(id);
+            clone.selected = val.selected;
+            clone.staticProperty = this.clone(val.staticProperty);
+        }
+        else if (val instanceof CollectionStaticProperty) {
+            clone = new CollectionStaticProperty(id);
+            clone.staticPropertyTemplate = this.clone(val.staticPropertyTemplate);
+            clone.members = val.members.map(elem => this.clone(elem));
+            clone.memberType = val.memberType;
+        }
+        else if (val instanceof URI) {
+            clone = new URI(id);
+            clone.tmp = val.tmp
+        }
+        //SelectionStaticProperty
+        else if (val instanceof RuntimeResolvableAnyStaticProperty ||  val instanceof RuntimeResolvableOneOfStaticProperty){
+            val instanceof RuntimeResolvableAnyStaticProperty ? clone = new RuntimeResolvableAnyStaticProperty(id) :
+              clone = new RuntimeResolvableOneOfStaticProperty(id);
+
+            clone.dependsOn = val.dependsOn;
+            clone.value = val.value;
+            clone.requiredDomainProperty = val.requiredDomainProperty;
+            clone.options = val.options.map(option => this.cloneOption(option));
+            clone.horizontalRendering = val.horizontalRendering;
+        }
+        else if (val instanceof AnyStaticProperty || val instanceof OneOfStaticProperty){
+            val instanceof AnyStaticProperty ? clone = new AnyStaticProperty(id) : clone = new OneOfStaticProperty(id);
+
+            clone.value = val.value;
+            clone.requiredDomainProperty = val.requiredDomainProperty;
+            clone.options = val.options.map(option => this.cloneOption(option));
+            clone.horizontalRendering = val.horizontalRendering;
+        }
+        clone = this.copyStaticPropertyProperty(val, clone);
+        return clone;
+    }
+
+    private copyStaticPropertyProperty(src: StaticProperty, dst: StaticProperty): StaticProperty {
+        dst.label = src.label;
+        dst.elementName = src.elementName;
+        dst.description = src.description;
+        dst.internalName = src.internalName;
+        dst.index = src.index;
+        return dst;
+    }
+
+    private cloneOption(val: Option) {
+        let clone = new Option();
+        clone.id = 'urn:streampipes.org:spi::' + this.generateID(6);
+        clone.elementName = val.elementName;
+        clone.name = val.name;
+        clone.internalName = val.internalName;
+        clone.selected = val.selected;
+        return clone;
+    }
+
+    private generateID(length): string {
+        let chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        var result = '';
+        for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
+        return result;
+    }
 
-export class StaticPropertyUtilService{
 
     public asFreeTextStaticProperty(val: StaticProperty): FreeTextStaticProperty {
         return <FreeTextStaticProperty> val;
@@ -33,4 +153,8 @@ export class StaticPropertyUtilService{
     public asSecretStaticProperty(val: StaticProperty): SecretStaticProperty {
         return <SecretStaticProperty> val;
     }
+
+    public asCollectionProperty(val: StaticProperty): CollectionStaticProperty {
+        return <CollectionStaticProperty> val;
+    }
 }
\ No newline at end of file
diff --git a/ui/src/app/connect/static-properties/static-property.component.html b/ui/src/app/connect/static-properties/static-property.component.html
index c8e34e8..c4e276b 100644
--- a/ui/src/app/connect/static-properties/static-property.component.html
+++ b/ui/src/app/connect/static-properties/static-property.component.html
@@ -74,5 +74,10 @@
                   (inputEmitter)="valueChange($event)">
 </app-static-group>
 
+<app-static-collection *ngIf="isCollectionStaticProperty(staticProperty)"
+                       [adapterId]="adapterId" [eventSchema]="eventSchema"
+                       [staticProperty]="staticProperty" class="test fullWidth"
+                       (inputEmitter)="valueChange($event)" (updateEmitter)="emitUpdate($event)">
+</app-static-collection>
 
 
diff --git a/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.css b/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.css
index 58ba04b..440a058 100644
--- a/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.css
+++ b/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.css
@@ -16,3 +16,6 @@
  *
  */
 
+.description {
+    font-size: 10px;
+}
diff --git a/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html b/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
index 35dd129..ea40d59 100644
--- a/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
+++ b/ui/src/app/connect/static-properties/static-runtime-resolvable-any-input/static-runtime-resolvable-any-input.component.html
@@ -16,7 +16,28 @@
   ~
   -->
 
-<div fxLayout="column">
-    <p>{{staticProperty.label}}: </p>
-    <mat-checkbox *ngFor="let option of staticProperty.options" [(ngModel)]="option.selected">{{option.name}}</mat-checkbox>
-</div>
\ No newline at end of file
+
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
+
+        <p>{{staticProperty.label}}: <br>
+            <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+        </p>
+        <mat-checkbox style="padding-left: 10px" *ngFor="let option of staticProperty.options" [(ngModel)]="option.selected">
+            {{option.name}}
+        </mat-checkbox>
+    </div>
+
+    <div *ngIf="staticProperty.horizontalRendering">
+        <mat-form-field style="width: 100%">
+            <mat-label>{{staticProperty.label}}</mat-label>
+            <mat-select multiple [(ngModel)]="option.selected">
+                <mat-option *ngFor="let option of staticProperty.options" [value]="option">
+                    {{option.name}}
+                </mat-option>
+            </mat-select>
+            <mat-hint>{{staticProperty.description}}</mat-hint>
+        </mat-form-field>
+    </div>
+</div>
diff --git a/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.css b/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.css
index 58ba04b..67091f6 100644
--- a/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.css
+++ b/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.css
@@ -16,3 +16,19 @@
  *
  */
 
+::ng-deep .mat-radio-container {
+    margin-top: 10px;
+    margin-bottom: 10px;
+}
+
+::ng-deep .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle {
+    border-color: rgb(27, 20, 100);
+}
+
+::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle {
+    background-color: rgb(27, 20, 100);
+}
+
+.description {
+    font-size: 10px;
+}
\ No newline at end of file
diff --git a/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html b/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
index e9bd96b..ea17ad5 100644
--- a/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
+++ b/ui/src/app/connect/static-properties/static-runtime-resolvable-oneof-input/static-runtime-resolvable-oneof-input.component.html
@@ -16,24 +16,46 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-        <p>{{staticProperty.label}}: </p>
-    </div>
-    <div fxFlex fxLayout="row">
-        <div fxLayout="column" *ngIf="showOptions || staticProperty.options">
-            <mat-radio-button *ngFor="let option of staticProperty.options"
-                              (click)="select(option.id)" [checked]="option.selected">
-                <label style="font-weight: normal; padding-top: 8px;">
-                    {{option.name}}
-                </label>
-            </mat-radio-button>
-        </div>
-        <div fxLayout="column" *ngIf="!showOptions && !staticProperty.options && !loading">
-            (waiting for input)
+<div id="formWrapper" fxFlex="100" fxLayout="column">
+
+    <div *ngIf="!staticProperty.horizontalRendering" fxLayout="column">
+        <div>
+            <p>{{staticProperty.label}}: <br>
+                <mat-hint class="description">{{staticProperty.description}}</mat-hint>
+            </p>
         </div>
-        <div fxLayout="column" *ngIf="loading">
-            <mat-spinner [diameter]="20"></mat-spinner>
+        <div fxFlex fxLayout="row">
+            <div fxLayout="column" *ngIf="showOptions || staticProperty.options" style="margin-left: 10px">
+                <mat-radio-button *ngFor="let option of staticProperty.options"
+                                  (click)="select(option.id)" [checked]="option.selected">
+                    <label style="font-weight: normal">
+                        {{option.name}}
+                    </label>
+                </mat-radio-button>
+            </div>
+            <div fxLayout="column" *ngIf="!showOptions && !staticProperty.options && !loading">
+                (waiting for input)
+            </div>
+            <div fxLayout="column" *ngIf="loading">
+                <mat-spinner [diameter]="20"></mat-spinner>
+            </div>
         </div>
     </div>
+
+    <div *ngIf="staticProperty.horizontalRendering">
+        <mat-form-field style="width: 100%">
+            <mat-label>{{staticProperty.label}}</mat-label>
+            <span matPrefix *ngIf="loading"><mat-spinner style="top:5px" [diameter]="20"></mat-spinner></span>
+            <mat-select>
+                <mat-option *ngFor="let option of staticProperty.options" [value]="option.id"
+                            (click)="select(option.id)">
+                    <label style="font-weight: normal">
+                        {{option.name}}
+                    </label>
+                </mat-option>
+            </mat-select>
+            <mat-hint>{{staticProperty.description}}</mat-hint>
+        </mat-form-field>
+    </div>
+
 </div>
diff --git a/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.css b/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.css
index 565a1d7..634aff7 100644
--- a/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.css
+++ b/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.css
@@ -20,11 +20,6 @@
     height: 60px;
 }
 
-p {
-    width: 100px;
-    float: left;
-    margin: 20px  15px 0 0;
-}
 form {
     float: left;
 }
diff --git a/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.html b/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.html
index b7580a1..fa745ab 100644
--- a/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.html
+++ b/ui/src/app/connect/static-properties/static-secret-input/static-secret-input.component.html
@@ -16,19 +16,14 @@
   ~
   -->
 
-<div id="formWrapper" fxFlex="90" fxLayout="row">
-    <div fxFlex="20">
-        <p>{{staticProperty.label}}: </p>
-    </div>
+<div id="formWrapper" fxFlex="100" fxLayout="column">
     <div fxFlex fxLayout="row">
         <form [formGroup]="secretForm">
-            <mat-form-field fxFlex>
-                <input type="password" fxFlex matInput
-                       formControlName="secretStaticProperty"
-                       id="{{ 'input-' + staticProperty.label.toLowerCase() }}" [placeholder]="staticProperty.label"
-                       [(ngModel)]="staticPropertyUtil.asSecretStaticProperty(staticProperty).value"
-                       (ngModelChange)="valueChange(staticPropertyUtil.asSecretStaticProperty(staticProperty).value)"
+            <mat-form-field fxFlex >
+                <input type="password" fxFlex id="{{ 'input-' + staticProperty.label.toLowerCase() }}" matInput [placeholder]="staticProperty.label" [(ngModel)]="staticPropertyUtil.asSecretStaticProperty(staticProperty).value"
+                       formControlName="secretStaticProperty" (ngModelChange)="valueChange(staticPropertyUtil.asSecretStaticProperty(staticProperty).value)"
                        required (blur)="emitUpdate()">
+                <mat-hint>{{staticProperty.description}}</mat-hint>
 
                 <mat-error *ngIf="!hasInput">
                     {{staticProperty.errorMessage}}
diff --git a/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.css b/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.css
index b352710..9ed6230 100644
--- a/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.css
+++ b/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.css
@@ -20,11 +20,6 @@
     height: 60px;
 }
 
-p {
-    width: 100px;
-    float: left;
-    margin: 20px  15px 0 0;
-}
 form {
     float: left;
 }
diff --git a/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.html b/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.html
index de26c51..dc296c5 100644
--- a/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.html
+++ b/ui/src/app/connect/static-properties/static-text-input/static-text-input.component.html
@@ -17,7 +17,6 @@
   -->
 
 <div id="formWrapper">
-    <p>{{staticProperty.label}}: </p>
     <form [formGroup]="freeTextForm">
 
         <mat-form-field>
diff --git a/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.css b/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.css
index b352710..6277006 100644
--- a/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.css
+++ b/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.css
@@ -19,12 +19,6 @@
 #formWrapper {
     height: 60px;
 }
-
-p {
-    width: 100px;
-    float: left;
-    margin: 20px  15px 0 0;
-}
 form {
     float: left;
 }
diff --git a/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.html b/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.html
index dbba53d..3d296a3 100644
--- a/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.html
+++ b/ui/src/app/connect/static-properties/static-url-input/static-url-input.component.html
@@ -17,7 +17,6 @@
   -->
 
 <div id="formWrapper">
-    <p>{{staticProperty.label}}: </p>
     <form [formGroup]="freeTextForm">
         <mat-form-field>
             <input class="example-full-width" matInput id="{{ 'input-' + staticProperty.label.toLowerCase() }}" [placeholder]="staticProperty.label" [(ngModel)]="staticPropertyUtil.asFreeTextStaticProperty(staticProperty).value"


Mime
View raw message