You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2020/08/05 07:31:21 UTC

[incubator-streampipes] branch STREAMPIPES-145 updated: [STREAMPIPES-190] Migrate pipeline element installation from AngularJS to Angular

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

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


The following commit(s) were added to refs/heads/STREAMPIPES-145 by this push:
     new 716849f  [STREAMPIPES-190] Migrate pipeline element installation from AngularJS to Angular
     new cab0320  Merge branch 'STREAMPIPES-145' of github.com:apache/incubator-streampipes into STREAMPIPES-145
716849f is described below

commit 716849f60c753984dd9351efed934e11326d8f09
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Wed Aug 5 09:30:47 2020 +0200

    [STREAMPIPES-190] Migrate pipeline element installation from AngularJS to Angular
---
 ui/deployment/modules.yml                          |  10 +-
 ui/src/app/add/add.component.html                  |  71 +++++++
 .../app/add/{add.module.ts => add.component.scss}  |  15 +-
 ui/src/app/add/add.component.ts                    | 159 +++++++++++++++
 ui/src/app/add/add.controller.ts                   | 220 ---------------------
 ui/src/app/add/add.html                            | 103 ----------
 ui/src/app/add/add.module.ts                       |  56 +++++-
 .../endpoint-item/endpoint-item.component.html     |  62 ++++++
 .../endpoint-item/endpoint-item.component.scss}    |  19 +-
 .../endpoint-item/endpoint-item.component.ts       |  97 +++++++++
 .../add-endpoint/add-endpoint.component.html       |  62 ++++++
 .../add-endpoint/add-endpoint.component.scss}      |   7 +-
 ...int.controller.ts => add-endpoint.component.ts} | 158 ++++++++-------
 .../dialogs/add-endpoint/add-endpoint.tmpl.html    |  67 -------
 .../endpoint-installation.component.html           |  51 +++++
 .../endpoint-installation.component.scss}          |   7 +-
 .../endpoint-installation.component.ts             | 126 ++++++++++++
 .../endpoint-installation.controller.ts            | 130 ------------
 .../endpoint-installation.tmpl.html                |  60 ------
 ui/src/app/add/endpoint-item.tmpl.html             |  77 --------
 .../add/{add.module.ts => filter/order-by.pipe.ts} |  27 ++-
 .../pipeline-element-type.pipe.ts}                 |  20 +-
 ui/src/app/add/services/add.service.ts             |  49 +++++
 .../apis/pipeline-element-endpoint.service.ts      |  52 +++++
 ui/src/app/platform-services/platform.module.ts    |   2 +
 ui/src/app/services/rest-api.service.ts            |  47 -----
 26 files changed, 928 insertions(+), 826 deletions(-)

diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index 811b149..80f36b5 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -70,11 +70,11 @@ spSensors:
   homeImage: '/assets/img/home/sensors.png'
   admin: False
 spAdd:
-  ng5: False
-  ng1_templateUrl: '../add/add.html'
-  ng5_moduleName: ''
-  ng5_component: ''
-  ng5_componentPath: ''
+  ng5: True
+  ng1_templateUrl: ''
+  ng5_moduleName: 'AddModule'
+  ng5_component: 'AddComponent'
+  ng5_componentPath: '../add/add.component'
   path: './add/add.module'
   link: 'streampipes.add'
   url: '/add'
diff --git a/ui/src/app/add/add.component.html b/ui/src/app/add/add.component.html
new file mode 100644
index 0000000..37983a0
--- /dev/null
+++ b/ui/src/app/add/add.component.html
@@ -0,0 +1,71 @@
+<!--
+  ~ 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" class="page-container">
+    <div fxLayout="row" class="border" style="padding:0px;background-color:#f6f6f6;">
+        <div fxFlex="100" style="line-height:24px;border-bottom:1px solid #ccc">
+            <div fxFlex="100" fxLayout="row">
+                <button mat-button mat-flat-button color="primary" (click)="showManageRdfEndpointsDialog()">Manage Endpoints</button>
+                <div fxFlex fxLayoutAlign="start center" [attr.id]="'peType'">
+                    <mat-tab-group [selectedIndex]="selectedCategoryIndex" (selectedIndexChange)="setSelectedTab($event)">
+                        <mat-tab label="All"></mat-tab>
+                        <mat-tab label="Data Sources"></mat-tab>
+                        <mat-tab label="Data Processors"></mat-tab>
+                        <mat-tab label="Data Sinks"></mat-tab>
+                    </mat-tab-group>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="page-container-padding-inner" *ngIf="endpointItemsLoadingComplete" >
+        <div fxLayoutAlign="start start" fxLayout="column">
+            <div fxFlex="100" fxLayout="row" style="margin-bottom:20px;">
+                <button mat-button mat-raised-button (click)="selectAll(true)" class="mr-10">
+                    <i class="material-icons">done</i>
+                    &nbsp;Select all
+                </button>
+                <button mat-button mat-raised-button (click)="selectAll(false)" class="mr-10">
+                    <i class="material-icons">clear</i>
+                    &nbsp;Select none
+                </button>
+                <button mat-button mat-raised-button color="primary" (click)="installSelected()" class="mr-10">
+                    <i class="material-icons">cloud_download</i>
+                    &nbsp;Install selected
+                </button>
+                <button mat-button mat-raised-button color="primary" (click)="uninstallSelected()">
+                    <i class="material-icons">delete</i>
+                    &nbsp;Uninstall selected
+                </button>
+            </div>
+        </div>
+        <div fxLayout="row wrap">
+            <endpoint-item fxFlex="33"
+                           [itemSelected]="endpointItem.selected"
+                           [item]="endpointItem"
+                           (triggerInstallation)="triggerInstallation($event)"
+                           *ngFor="let endpointItem of endpointItems | pipelineElementTypeFilter: selectedTab | orderBy: 'asc':'name'"
+                           class="p-15"
+                           (click)="toggleSelected(endpointItem)"></endpoint-item>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="row" fxLayoutAlign="center center" *ngIf="!endpointItemsLoadingComplete">
+        <mat-spinner [mode]="'indeterminate'" [diameter]="20"></mat-spinner>
+        <h4>&nbsp;&nbsp;Searching for available pipeline elements, please wait...</h4>
+    </div>
+</div>
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/add.component.scss
similarity index 83%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/add.component.scss
index 7de767a..0baeea4 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/add.component.scss
@@ -16,9 +16,14 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
+.page-container-padding-inner {
+  margin: 20px;
+}
 
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+.p-15 {
+  padding: 15px;
+}
+
+.mr-10 {
+  margin-right: 10px;
+}
\ No newline at end of file
diff --git a/ui/src/app/add/add.component.ts b/ui/src/app/add/add.component.ts
new file mode 100644
index 0000000..5c4659a
--- /dev/null
+++ b/ui/src/app/add/add.component.ts
@@ -0,0 +1,159 @@
+/*
+ * 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 {RestApi} from "../services/rest-api.service";
+import {ChangeDetectorRef, Component, OnInit} from "@angular/core";
+import {AddService} from "./services/add.service";
+import {DialogRef} from "../core-ui/dialog/base-dialog/dialog-ref";
+import {PanelType} from "../core-ui/dialog/base-dialog/base-dialog.model";
+import {DialogService} from "../core-ui/dialog/base-dialog/base-dialog.service";
+import {AddEndpointComponent} from "./dialogs/add-endpoint/add-endpoint.component";
+import {EndpointInstallationComponent} from "./dialogs/endpoint-installation/endpoint-installation.component";
+
+@Component({
+    selector: 'add',
+    templateUrl: './add.component.html',
+    styleUrls: ['./add.component.scss']
+})
+export class AddComponent implements OnInit {
+
+    results: any[];
+    loading: boolean;
+    endpointItems: any[];
+    endpointItemsLoadingComplete: boolean;
+    selectedTab: string;
+    availableTypes: Array<string> = ["all", "source", "sepa", "action"];
+
+    selectedCategoryIndex: number = 0;
+
+    constructor(private RestApi: RestApi,
+                private AddService: AddService,
+                private DialogService: DialogService,
+                private ChangeDetectorRef: ChangeDetectorRef) {
+        this.results = [];
+        this.loading = false;
+        this.endpointItems = [];
+        this.endpointItemsLoadingComplete = false;
+    }
+
+    ngOnInit() {
+        this.getEndpointItems();
+        this.selectedTab = "all";
+    }
+
+    toggleSelected(endpointItem) {
+        endpointItem.selected = !endpointItem.selected;
+    }
+
+    setSelectedTab(index: number) {
+        this.selectedTab = this.availableTypes[index];
+    }
+
+    isSelected(endpointItem) {
+        return endpointItem.selected;
+    }
+
+    selectAll(selected) {
+        this.endpointItems.forEach(item => {
+            if (item.type === this.selectedTab || this.selectedTab == 'all') item.selected = selected;
+        });
+        this.ChangeDetectorRef.detectChanges();
+    }
+
+    getTitle(selectedTab) {
+        if (selectedTab === 'source') {
+            return "Data Sources";
+        } else if (selectedTab === 'sepa') {
+            return "Processing Elements";
+        } else if (selectedTab === 'action') {
+            return "Data Sinks";
+        } else if (selectedTab === 'all') {
+            return "All Pipeline Elements";
+        } else {
+            return "Marketplace";
+        }
+    }
+
+    showManageRdfEndpointsDialog() {
+        let dialogRef: DialogRef<AddEndpointComponent> = this.DialogService.open(AddEndpointComponent, {
+            panelType: PanelType.STANDARD_PANEL,
+            title: "Manage Endpoints",
+            width: "70vw",
+            data: {
+
+            }
+        });
+        dialogRef.afterClosed().subscribe(data => {
+            if (data) {
+                this.getEndpointItems();
+            }
+        })
+    }
+
+    getEndpointItems() {
+        this.endpointItemsLoadingComplete = false;
+        this.AddService.getRdfEndpointItems()
+            .subscribe(endpointItems => {
+                this.endpointItems = endpointItems;
+                this.endpointItemsLoadingComplete = true;
+            });
+    }
+
+    installSelected() {
+        this.installElements(this.getSelectedElements(true), true);
+    }
+
+    uninstallSelected() {
+        this.installElements(this.getSelectedElements(false), false);
+    }
+
+    getSelectedElements(install) {
+        let elementsToInstall = [];
+
+        this.endpointItems.forEach(item => {
+            if (item.type === this.selectedTab || this.selectedTab == 'all') {
+                if (item.installed === !install && item.selected) {
+                    elementsToInstall.push(item);
+                }
+            }
+        });
+
+        return elementsToInstall;
+    }
+
+    triggerInstallation(installationInfo: any) {
+        this.installElements(installationInfo.endpointItems, installationInfo.install);
+    }
+
+    installElements(endpointItems, install) {
+        let dialogRef: DialogRef<EndpointInstallationComponent> = this.DialogService.open(EndpointInstallationComponent, {
+            panelType: PanelType.STANDARD_PANEL,
+            title: "Installation",
+            width: "70vw",
+            data: {
+                "install": install,
+                "endpointItemsToInstall": endpointItems
+            }
+        });
+        dialogRef.afterClosed().subscribe(data => {
+            if (data) {
+                this.getEndpointItems();
+            }
+        })
+    }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/add.controller.ts b/ui/src/app/add/add.controller.ts
deleted file mode 100644
index eb11da1..0000000
--- a/ui/src/app/add/add.controller.ts
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import {AddEndpointController} from './dialogs/add-endpoint/add-endpoint.controller';
-import {EndpointInstallationController} from './dialogs/endpoint-installation/endpoint-installation.controller';
-import * as angular from 'angular';
-import {RestApi} from "../services/rest-api.service";
-
-declare const require: any;
-
-export class AddCtrl {
-
-    RestApi: RestApi;
-    $mdDialog: any;
-    ElementIconText: any;
-    elements: any;
-    results: any;
-    loading: any;
-    endpointItems: any;
-    endpointItemsLoadingComplete: any;
-    selectedTab: any;
-    $templateCache: any;
-    availableTypes: {"source", "sepa", "action"};
-
-    constructor(RestApi, $mdDialog, ElementIconText, $templateCache) {
-        this.RestApi = RestApi;
-        this.$mdDialog = $mdDialog;
-        this.ElementIconText = ElementIconText;
-        this.elements = "";
-        this.results = [];
-        this.loading = false;
-        this.endpointItems = [];
-        this.endpointItemsLoadingComplete = false;
-        this.selectedTab = "MARKETPLACE";
-        this.$templateCache = $templateCache;
-        this.$templateCache.put('endpoint-item.tmpl.html', require('./endpoint-item.tmpl.html'));
-    }
-
-    $onInit() {
-        this.getEndpointItems();
-    }
-
-    iconText(elementName) {
-        return this.ElementIconText.getElementIconText(elementName);
-    }
-
-    setSelectedTab(type) {
-        this.selectedTab = type;
-    }
-
-    isSelected(endpointItem) {
-        return endpointItem.selected;
-    }
-
-    getSelectedBackground(endpointItem) {
-        if (endpointItem.selected) return "#EEEEEE";
-        else return "#FFFFFF";
-    }
-
-    toggleSelected(endpointItem) {
-        endpointItem.selected = !endpointItem.selected;
-    }
-
-    selectAll(selected) {
-        this.endpointItems.forEach(item => {
-            if (item.type === this.selectedTab || this.selectedTab == 'all') item.selected = selected;
-        });
-    }
-
-    getTitle(selectedTab) {
-        if (selectedTab === 'source') {
-            return "Data Sources";
-        } else if (selectedTab === 'sepa') {
-            return "Processing Elements";
-        } else if (selectedTab === 'action') {
-            return "Data Sinks";
-        } else if (selectedTab === 'all') {
-            return "All Pipeline Elements";
-        } else {
-            return "Marketplace";
-        }
-    }
-
-    getItemTitle(selectedTab) {
-        if (selectedTab === 'source') {
-            return "Data Source";
-        } else if (selectedTab === 'sepa') {
-            return "Data Processor";
-        } else {
-            return "Data Sink";
-        }
-    }
-
-    getItemStyle(type) {
-        let baseType = "pe-label ";
-        if (type == 'source') {
-            return baseType + "source-label";
-        } else if (type == 'sepa') {
-            return baseType + "processor-label";
-        } else {
-            return baseType + "sink-label";
-        }
-    }
-    showManageRdfEndpointsDialog() {
-        this.$mdDialog.show({
-            controller: AddEndpointController,
-            controllerAs: 'ctrl',
-            template: require('./dialogs/add-endpoint/add-endpoint.tmpl.html'),
-            parent: angular.element(document.body),
-            clickOutsideToClose: true,
-            locals: {
-                getEndpointItems: () => {
-                    return this.getEndpointItems();
-                }
-            },
-            bindToController: true
-        })
-    }
-
-    getEndpointItems() {
-        this.endpointItemsLoadingComplete = false;
-        this.RestApi.getRdfEndpointItems()
-            .then(msg => {
-                let endpointItems = msg.data;
-                this.endpointItems = endpointItems;
-                this.endpointItemsLoadingComplete = true;
-            });
-    }
-
-    addFromEndpoint(endpointUrl) {
-        this.loading = true;
-        this.RestApi.addBatch(endpointUrl, true)
-            .then(msg => {
-                var data = msg.data;
-                this.loading = false;
-                data.forEach((element, index) => {
-                    this.results[index] = {};
-                    this.results[index].success = element.success;
-                    this.results[index].elementName = element.elementName;
-                    this.results[index].details = [];
-                    element.notifications.forEach(notification => {
-                        let detail = {};
-                        detail['description'] = notification.description;
-                        detail['title'] = notification.title;
-                        this.results[index].details.push(detail);
-                    })
-                });
-            })
-    }
-
-    installSingleElement(endpointItem) {
-        let endpointItems = [];
-        endpointItems.push(endpointItem);
-        this.installElements(endpointItems, true);
-    }
-
-    uninstallSingleElement(endpointItem) {
-        let endpointItems = [];
-        endpointItems.push(endpointItem);
-        this.installElements(endpointItems, false);
-    }
-
-    installSelected() {
-        this.installElements(this.getSelectedElements(true), true);
-    }
-
-    uninstallSelected() {
-        this.installElements(this.getSelectedElements(false), false);
-    }
-
-    getSelectedElements(install) {
-        let elementsToInstall = [];
-
-        this.endpointItems.forEach(item => {
-            if (item.type === this.selectedTab || this.selectedTab == 'all') {
-                if (item.installed === !install && item.selected) {
-                    elementsToInstall.push(item);
-                }
-            }
-        });
-
-        return elementsToInstall;
-    }
-
-    installElements(endpointItems, install) {
-        this.$mdDialog.show({
-            controller: EndpointInstallationController,
-            controllerAs: 'ctrl',
-            template: require('./dialogs/endpoint-installation/endpoint-installation.tmpl.html'),
-            parent: angular.element(document.body),
-            clickOutsideToClose: false,
-            locals: {
-                endpointItems: endpointItems,
-                install: install,
-                getEndpointItems: () => {
-                    return this.getEndpointItems();
-                }
-            },
-            bindToController: true
-        });
-    }
-
-}
-
-AddCtrl.$inject = ['RestApi', '$mdDialog', 'ElementIconText', '$templateCache'];
\ No newline at end of file
diff --git a/ui/src/app/add/add.html b/ui/src/app/add/add.html
deleted file mode 100644
index f238771..0000000
--- a/ui/src/app/add/add.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div flex class="page-container page-container-padding" ng-controller="AddCtrl as ctrl">
-    <div flex="100" layout="row" style="padding:0px;background-color:#f6f6f6">
-        <div flex="none" layout-wrap layout="row" layout-align="start center"
-             style="padding-left:10px;font-size:14px;line-height:24px;border-bottom:1px solid #ccc">
-            <sp-button sp-button-flat ng-click="ctrl.showManageRdfEndpointsDialog()">Manage Endpoints</sp-button>
-        </div>
-        <div layout-fill>
-            <md-tabs md-dynamic-height md-border-bottom>
-                <md-tab label="All" md-on-select="ctrl.setSelectedTab('all')"></md-tab>
-                <md-tab label="Data Sources" md-on-select="ctrl.setSelectedTab('source')"></md-tab>
-                <md-tab label="Data Processors" md-on-select="ctrl.setSelectedTab('sepa')"></md-tab>
-                <md-tab label="Data Sinks" md-on-select="ctrl.setSelectedTab('action')"></md-tab>
-            </md-tabs>
-        </div>
-    </div>
-
-    <div flex layout="row" layout-align="center center">
-        <div flex="80">
-            <md-content class="md-padding">
-                <h2>{{ctrl.getTitle(ctrl.selectedTab)}}</h2>
-                <div flex="100">
-                    <div ng-if="ctrl.endpointItemsLoadingComplete">
-                        <div flex="100" layout="row" style="margin-bottom:20px;">
-                            <sp-button sp-button-gray ng-click="ctrl.selectAll(true)">
-                                <i class="material-icons">done</i>
-                                &nbsp;Select all
-                            </sp-button>
-                            <sp-button sp-button-gray ng-click="ctrl.selectAll(false)">
-                                <i class="material-icons">clear</i>
-                                &nbsp;Select none
-                            </sp-button>
-                            <sp-button sp-button-blue ng-click="ctrl.installSelected()">
-                                <i class="material-icons">cloud_download</i>
-                                &nbsp;Install selected
-                            </sp-button>
-                            <sp-button sp-button-blue ng-click="ctrl.uninstallSelected()">
-                                <i class="material-icons">delete</i>
-                                &nbsp;Uninstall selected
-                            </sp-button>
-                        </div>
-                        <div ng-if="ctrl.selectedTab != 'all'"
-                             ng-repeat="endpointItem in ctrl.endpointItems | filter:{type:ctrl.selectedTab} |orderBy: '+name'">
-                            <ng-include src="'endpoint-item.tmpl.html'"></ng-include>
-                        </div>
-                        <div ng-if="ctrl.selectedTab == 'all'"
-                             ng-repeat="endpointItem in ctrl.endpointItems |orderBy: '+name'">
-                            <ng-include src="'endpoint-item.tmpl.html'"></ng-include>
-                        </div>
-                    </div>
-                    <div ng-if="!ctrl.endpointItemsLoadingComplete">
-                        <div flex="100" layout="row">
-                            <md-progress-circular class="md-accent" md-mode="indeterminate"
-                            ></md-progress-circular>
-                            <h4>&nbsp;&nbsp;Fetching data from endpoints, please wait...</h4>
-                        </div>
-                    </div>
-
-                </div>
-            </md-content>
-        </div>
-    </div>
-    <div flex layout="row" layout-align="center center" ng-repeat="result in ctrl.results">
-        <div flex-sm="100" flex-gt-sm="90" flex-gt-md="70" flex-gt-lg="50"
-             class="md-whiteframe-z2">
-
-            <md-content class="md-padding">
-                <div flex layout="row"><h3>{{result.elementName}}</h3>
-                    <md-progress-circular class="md-accent" style="width:12px;height:12px;" md-mode="indeterminate"
-                                          ng-show="result.loading"></md-progress-circular>
-                    <md-icon md-svg-icon="action:ic_done_24px" aria-label="Action" class="md-accent"
-                             ng-show="!result.loading && result.success"></md-icon>
-                    <md-icon md-svg-icon="alert:ic_error_24px" aria-label="Action" class="md-accent"
-                             ng-show="!result.loading && !(result.success)"></md-icon>
-
-                </div>
-                <div ng-repeat="detail in result.details">
-                    <div ng-show="!result.loading">{{detail.title}}</div>
-                    <div ng-show="!result.loading">{{detail.description}}</div>
-                    <md-divider/>
-                </div>
-
-            </md-content>
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/add.module.ts
index 7de767a..7c6fcd8 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/add.module.ts
@@ -16,9 +16,55 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
+import {NgModule} from "@angular/core";
+import {FlexLayoutModule} from "@angular/flex-layout";
+import {FormsModule} from "@angular/forms";
+import {MatTabsModule} from "@angular/material/tabs";
+import {CustomMaterialModule} from "../CustomMaterial/custom-material.module";
+import {CommonModule} from "@angular/common";
+import {AddComponent} from "./add.component";
+import {CoreUiModule} from "../core-ui/core-ui.module";
+import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
+import {PipelineElementTypeFilter} from "./filter/pipeline-element-type.pipe";
+import {EndpointItemComponent} from "./components/endpoint-item/endpoint-item.component";
+import {AddService} from "./services/add.service";
+import {AddEndpointComponent} from "./dialogs/add-endpoint/add-endpoint.component";
+import {OrderByPipe} from "./filter/order-by.pipe";
+import {EndpointInstallationComponent} from "./dialogs/endpoint-installation/endpoint-installation.component";
 
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    MatTabsModule,
+    FlexLayoutModule,
+    CoreUiModule,
+    CustomMaterialModule,
+    MatProgressSpinnerModule
+  ],
+  declarations: [
+    AddComponent,
+    AddEndpointComponent,
+    EndpointInstallationComponent,
+    EndpointItemComponent,
+    OrderByPipe,
+    PipelineElementTypeFilter
+  ],
+  providers: [
+    AddService,
+    OrderByPipe,
+    PipelineElementTypeFilter
+  ],
+  exports: [
+    AddComponent
+  ],
+  entryComponents: [
+    AddComponent
+  ]
+})
+export class AddModule {
+
+  constructor() {
+  }
+
+}
\ No newline at end of file
diff --git a/ui/src/app/add/components/endpoint-item/endpoint-item.component.html b/ui/src/app/add/components/endpoint-item/endpoint-item.component.html
new file mode 100644
index 0000000..902e757
--- /dev/null
+++ b/ui/src/app/add/components/endpoint-item/endpoint-item.component.html
@@ -0,0 +1,62 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" fxLayoutAlign="start start" class="pipeline-element-box"
+     style="padding:5px;margin-bottom:10px;background:{{getSelectedBackground()}}">
+    <div fxFlex fxLayout="row" style="width:100%;">
+        <div style="margin-right:10px;margin-left:10px;margin-top:10px;">
+            <div class="draggable-icon {{item.type}}">{{iconText(item.name)}}</div>
+        </div>
+        <div fxFlex fxLayout="column">
+            <div fxFlex fxLayoutAlign="end start">
+                <span class="{{itemTypeStyle}}">{{itemTypeTitle}}</span>
+            </div>
+            <div fxFlex fxLayoutAlign="start end" class="ml-5">
+                <button class="small-button" mat-button mat-raised-button color="primary" (click)="installSingleElement(item)" *ngIf="!item.installed">
+                    <i class="material-icons small-icon">cloud_download</i>
+                    <span>&nbsp;Install</span>
+                </button>
+                <button class="small-button" mat-button mat-raised-button color="primary"  (click)="uninstallSingleElement(item)" *ngIf="item.installed">
+                    <i class="material-icons small-icon">delete</i>
+                    <span>&nbsp;Uninstall</span>
+                </button>
+            </div>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column" style="padding-left:10px;margin-top:10px;">
+        <div fxLayout="column">
+            <div fxFlex fxLayout="column">
+                <h3><b>{{item.name}}</b></h3>
+                <p>{{item.description}}</p>
+                <div fxFlex fxLayout="column" *ngIf="item.type=='source'">
+                    <div fxLayout="row" fxLayoutAlign="start center" *ngFor="let stream of item.streams">
+                        <div style="min-height:60px;">
+                            <div class="draggable-icon-preview stream" style="margin-right:10px;">
+                                {{iconText(stream.name)}}
+                            </div>
+                        </div>
+                        <div style="min-height:60px;margin-left:10px;">
+                            <h5><b>{{stream.name}}</b></h5>
+                            <p>{{stream.description}}</p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/components/endpoint-item/endpoint-item.component.scss
similarity index 80%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/components/endpoint-item/endpoint-item.component.scss
index 7de767a..f723b27 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/components/endpoint-item/endpoint-item.component.scss
@@ -16,9 +16,18 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
+.pipeline-element-box {
+  height: 100%;
+  box-shadow: 1px 1px 2px #555;
+  border: 1px solid gray;
+  cursor: pointer;
+  padding: 10px;
+}
 
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+.small-icon {
+  font-size:12px;
+}
+
+.ml-5 {
+  margin-left:5px;
+}
\ No newline at end of file
diff --git a/ui/src/app/add/components/endpoint-item/endpoint-item.component.ts b/ui/src/app/add/components/endpoint-item/endpoint-item.component.ts
new file mode 100644
index 0000000..db88d19
--- /dev/null
+++ b/ui/src/app/add/components/endpoint-item/endpoint-item.component.ts
@@ -0,0 +1,97 @@
+/*
+ * 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, OnInit, Output} from "@angular/core";
+
+@Component({
+  selector: 'endpoint-item',
+  templateUrl: './endpoint-item.component.html',
+  styleUrls: ['./endpoint-item.component.scss']
+})
+export class EndpointItemComponent implements OnInit {
+
+  @Input()
+  item: any;
+
+  itemTypeTitle: string;
+  itemTypeStyle: string;
+
+  @Input()
+  itemSelected: boolean;
+
+  @Output()
+  triggerInstallation: EventEmitter<any> = new EventEmitter<any>();
+
+  ngOnInit(): void {
+   this.findItemTypeTitle();
+   this.findItemStyle();
+  }
+
+  iconText(s) {
+    var result = "";
+    if (s.length <= 4) {
+      result = s;
+    } else {
+      var words = s.split(" ");
+      words.forEach(function (word, i) {
+        if (i < 4) {
+          result += word.charAt(0);
+        }
+      });
+    }
+    return result.toUpperCase();
+  }
+
+  getSelectedBackground() {
+    if (this.itemSelected) return "#EEEEEE";
+    else return "#FFFFFF";
+  }
+
+  findItemTypeTitle() {
+    if (this.item.type === 'source') {
+      this.itemTypeTitle = "Data Source";
+    } else if (this.item.type === 'sepa') {
+      this.itemTypeTitle = "Data Processor";
+    } else {
+      this.itemTypeTitle = "Data Sink";
+    }
+  }
+
+  findItemStyle() {
+    let baseType = "pe-label ";
+    if (this.item.type == 'source') {
+      this.itemTypeStyle = baseType + "source-label";
+    } else if (this.item.type == 'sepa') {
+      this.itemTypeStyle = baseType + "processor-label";
+    } else {
+      this.itemTypeStyle = baseType + "sink-label";
+    }
+  }
+
+  installSingleElement(endpointItem) {
+    let endpointItems = [];
+    endpointItems.push(endpointItem);
+    this.triggerInstallation.emit({endpointItems: endpointItems, install: true});
+  }
+
+  uninstallSingleElement(endpointItem) {
+    let endpointItems = [];
+    endpointItems.push(endpointItem);
+    this.triggerInstallation.emit({endpointItems: endpointItems, install: false});
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html
new file mode 100644
index 0000000..800fe8a
--- /dev/null
+++ b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.html
@@ -0,0 +1,62 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <h5><b>Existing Endpoints</b></h5>
+        <div>
+            <div *ngFor="let rdfEndpoint of rdfEndpoints | orderBy: 'asc':'endpointUrl'">
+                <div layout="row" class="md-with-secondary" *ngIf="rdfEndpoint._id !== undefined">
+                    <div class="md-list-item-text" fxFlex="80" fxLayout="column">
+                        {{rdfEndpoint.endpointUrl}}
+                    </div>
+                    <div class="md-list-item-text" fxFlex="20" fxLayout="column">
+                        <button mat-button mat-flat-button (click)="removeRdfEndpoint(rdfEndpoint._id)">
+                            <mat-icon color="primary">delete</mat-icon>
+                        </button>
+                    </div>
+                </div>
+            </div>
+            <mat-divider></mat-divider>
+            <div *ngIf="addSelected">
+                <div fxLayout="row" class="md-with-secondary">
+                    <div class="md-list-item-text" fxFlex="80" fxLayout="column">
+                        <mat-form-field>
+                            <mat-label>Endpoint URL</mat-label>
+                            <input matInput type="text" [(ngModel)]="newEndpoint.endpointUrl">
+                        </mat-form-field>
+                    </div>
+                    <div class="md-list-item-text" flex="20" layout="column">
+                        <button mat-button mat-flat-button (click)="addRdfEndpoint(newEndpoint)">
+                            <mat-icon>save</mat-icon>
+                        </button>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div style="margin-top:10px;">
+            <button mat-button mat-raised-button color="primary" (click)="showAddInput()">Add Category</button>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions actions-align-right">
+        <button mat-button mat-raised-button class="mat-basic" (click)="close()">
+            Close
+        </button>
+    </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.scss
similarity index 83%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.scss
index 7de767a..0a776e5 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.scss
@@ -16,9 +16,4 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
-
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+@import '../../../../scss/sp/sp-dialog.scss';
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.controller.ts b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.ts
similarity index 55%
rename from ui/src/app/add/dialogs/add-endpoint/add-endpoint.controller.ts
rename to ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.ts
index 7648553..f00b9b0 100644
--- a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.controller.ts
+++ b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.component.ts
@@ -1,80 +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 {RestApi} from "../../../services/rest-api.service";
-
-export class AddEndpointController {
-
-    $mdDialog: any;
-    RestApi: RestApi;
-    rdfEndpoints: any;
-    addSelected: any;
-    newEndpoint: any;
-    getEndpointItems: any;
-
-    constructor($mdDialog, RestApi, getEndpointItems) {
-        this.$mdDialog = $mdDialog;
-        this.RestApi = RestApi;
-        this.rdfEndpoints = [];
-        this.addSelected = false;
-        this.newEndpoint = {};
-        this.getEndpointItems = getEndpointItems;
-    }
-
-    $onInit() {
-        this.loadRdfEndpoints();
-    }
-
-    showAddInput() {
-        this.addSelected = true;
-    }
-
-    loadRdfEndpoints() {
-        this.RestApi.getRdfEndpoints()
-            .then(rdfEndpoints => {
-                this.rdfEndpoints = rdfEndpoints.data;
-            });
-    }
-
-    addRdfEndpoint(rdfEndpoint) {
-        this.RestApi.addRdfEndpoint(rdfEndpoint)
-            .then(message => {
-                this.loadRdfEndpoints();
-                this.getEndpointItems();
-            });
-    }
-
-    removeRdfEndpoint(rdfEndpointId) {
-        this.RestApi.removeRdfEndpoint(rdfEndpointId)
-            .then(message => {
-                this.loadRdfEndpoints();
-                this.getEndpointItems();
-            });
-    }
-
-    hide() {
-        this.$mdDialog.hide();
-    }
-
-    cancel() {
-        this.$mdDialog.cancel();
-    };
-
-}
-
-AddEndpointController.$inject = ['$mdDialog', 'RestApi', 'getEndpointItems'];
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import {Component, OnInit} from "@angular/core";
+import {AddService} from "../../services/add.service";
+import {DialogRef} from "../../../core-ui/dialog/base-dialog/dialog-ref";
+
+@Component({
+    selector: 'add-endpoint-dialog',
+    templateUrl: './add-endpoint.component.html',
+    styleUrls: ['./add-endpoint.component.scss']
+})
+export class AddEndpointComponent implements OnInit {
+
+    rdfEndpoints: any;
+    addSelected: any;
+    newEndpoint: any;
+
+    endpointsChanged: boolean = false;
+
+    constructor(private AddService: AddService,
+                private DialogRef: DialogRef<AddEndpointComponent>) {
+        this.rdfEndpoints = [];
+        this.addSelected = false;
+        this.newEndpoint = {};
+    }
+
+    ngOnInit() {
+        this.loadRdfEndpoints();
+    }
+
+    showAddInput() {
+        this.addSelected = true;
+    }
+
+    loadRdfEndpoints() {
+        this.AddService.getRdfEndpoints()
+            .subscribe(rdfEndpoints => {
+                this.rdfEndpoints = rdfEndpoints;
+            });
+    }
+
+    addRdfEndpoint(rdfEndpoint) {
+        console.log(rdfEndpoint);
+        this.AddService.addRdfEndpoint(rdfEndpoint)
+            .subscribe(message => {
+                this.loadRdfEndpoints();
+                this.endpointsChanged = true;
+            });
+    }
+
+    removeRdfEndpoint(rdfEndpointId) {
+        this.AddService.removeRdfEndpoint(rdfEndpointId)
+            .subscribe(message => {
+                this.loadRdfEndpoints();
+                this.endpointsChanged = true;
+            });
+    }
+
+    close() {
+        this.DialogRef.close(this.endpointsChanged);
+    }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.tmpl.html b/ui/src/app/add/dialogs/add-endpoint/add-endpoint.tmpl.html
deleted file mode 100644
index 3d97e7c..0000000
--- a/ui/src/app/add/dialogs/add-endpoint/add-endpoint.tmpl.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<md-dialog aria-label="Endpoint Settings" flex="60" class="colored-frame">
-    <md-toolbar>
-        <div class="md-toolbar-tools">
-            <h2>Endpoint Settings</h2>
-            <span flex></span>
-            <md-button class="md-icon-button" ng-click="ctrl.cancel()">
-                <md-icon md-svg-icon="navigation:ic_close_24px" aria-label="Close dialog"></md-icon>
-            </md-button>
-        </div>
-    </md-toolbar>
-
-    <md-dialog-content flex="100" class="md-dialog-content">
-        <h5>Existing Endpoints</h5>
-        <md-list>
-            <div ng-repeat="rdfEndpoint in ctrl.rdfEndpoints | orderBy: '+endpointUrl'" ng-if="rdfEndpoint._id !== undefined">
-            <md-list-item layout="row" class="md-with-secondary" >
-                <div class="md-list-item-text" flex="80" layout="column">
-                    {{rdfEndpoint.endpointUrl}}
-                </div>
-                <div class="md-list-item-text" flex="20" layout="column">
-                    <sp-button sp-button-flat ng-click="ctrl.removeRdfEndpoint(rdfEndpoint._id)" class="md-icon-button"><md-icon md-svg-icon="action:ic_delete_24px" aria-label="Delete"></md-icon></sp-button>
-                </div>
-            </md-list-item>
-            <p/>
-            </div>
-            <md-divider></md-divider>
-            <div ng-show="ctrl.addSelected">
-                <md-list-item layout="row" class="md-with-secondary" >
-                    <div class="md-list-item-text" flex="80" layout="column">
-                        <md-input-container> <label>Endpoint URL</label> <input
-                                type="text" ng-model="ctrl.newEndpoint.endpointUrl">
-                        </md-input-container>
-                    </div>
-                    <div class="md-list-item-text" flex="20" layout="column">
-                        <sp-button sp-button-flat ng-click="ctrl.addRdfEndpoint(ctrl.newEndpoint)" class="md-icon-button"><md-icon md-svg-icon="content:ic_save_24px" aria-label="Delete"></md-icon></sp-button>
-                    </div>
-                </md-list-item>
-            </div>
-        </md-list>
-        <div style="margin-top:10px;">
-            <sp-button sp-button-blue ng-click="ctrl.showAddInput()" sp-button-flat>Add RDF Endpoint</sp-button>
-        </div>
-    </md-dialog-content>
-    <md-dialog-actions layout="row">
-        <sp-button sp-button-gray ng-click="ctrl.hide()">
-            Close
-        </sp-button>
-    </md-dialog-actions>
-</md-dialog>
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.html b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.html
new file mode 100644
index 0000000..6c7b15f
--- /dev/null
+++ b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.html
@@ -0,0 +1,51 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" class="md-dialog-content" style="padding:20px;" *ngIf="page == 'preview'">
+            <h4>You are about to {{install ? 'install' : 'uninstall'}} the following elements:</h4>
+            <div *ngFor="let endpointItem of endpointItemsToInstall">
+                <h5>{{endpointItem.name}}</h5>
+            </div>
+            <h5><b>Press 'Next' to start the process.</b></h5>
+        </div>
+        <div fxFlex="100" class="md-dialog-content" style="padding:20px;" *ngIf="page == 'installation'">
+            <div *ngFor="let status of installationStatus">
+                <h4>{{install ? 'Installing' : 'Uninstalling'}} {{status.id + 1}} of {{endpointItemsToInstall.length}}
+                    ({{status.name}})...{{status.status}}</h4>
+                <div>
+                    <div fxFlex fxLayout="column" *ngIf="status.details">
+                        <b>More Details:</b>
+                        <div class="md-padding"><i class="fa fa-terminal">{{status.details}}</i></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions actions-align-right">
+        <button mat-button mat-raised-button class="mat-basic" (click)="close()" style="margin-right: 10px;">
+            Close
+        </button>
+        <button mat-button mat-raised-button color="primary" (click)="next()" [disabled]="installationRunning">
+            {{nextButton}}
+        </button>
+    </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.scss
similarity index 83%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.scss
index 7de767a..0a776e5 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.scss
@@ -16,9 +16,4 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
-
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+@import '../../../../scss/sp/sp-dialog.scss';
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.ts b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.ts
new file mode 100644
index 0000000..4d1f425
--- /dev/null
+++ b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.component.ts
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import {Component, Input} from "@angular/core";
+import {DialogRef} from "../../../core-ui/dialog/base-dialog/dialog-ref";
+import {PipelineElementEndpointService} from "../../../platform-services/apis/pipeline-element-endpoint.service";
+
+@Component({
+  selector: 'endpoint-installation-dialog',
+  templateUrl: './endpoint-installation.component.html',
+  styleUrls: ['./endpoint-installation.component.scss']
+})
+export class EndpointInstallationComponent {
+
+  endpointItems: any;
+
+  @Input()
+  install: boolean;
+
+  @Input()
+  endpointItemsToInstall: any;
+
+  installedItemsChanged: boolean = false;
+
+  installationStatus: any;
+  installationFinished: boolean;
+  page: string;
+  nextButton: string;
+  installationRunning: boolean;
+
+  constructor(private DialogRef: DialogRef<EndpointInstallationComponent>,
+              private PipelineElementEndpointService: PipelineElementEndpointService) {
+    this.installationStatus = [];
+    this.installationFinished = false;
+    this.page = "preview";
+    this.nextButton = "Next";
+    this.installationRunning = false;
+  }
+
+  close() {
+    this.DialogRef.close(this.installedItemsChanged);
+  }
+
+  next() {
+    if (this.page === "installation") {
+      this.close();
+    } else {
+      this.page = "installation";
+      this.initiateInstallation(this.endpointItemsToInstall[0], 0);
+    }
+  }
+
+  initiateInstallation(endpointUri, index) {
+    this.installationRunning = true;
+    this.installationStatus.push({"name": endpointUri.name, "id": index, "status": "waiting"});
+    if (this.install) {
+      this.installElement(endpointUri, index);
+    } else {
+      this.uninstallElement(endpointUri, index);
+    }
+  }
+
+  installElement(endpointUri, index) {
+    endpointUri = encodeURIComponent(endpointUri.uri);
+
+    this.PipelineElementEndpointService.add(endpointUri, true)
+        .subscribe(data => {
+          if (data.success) {
+            this.installationStatus[index].status = "success";
+          } else {
+            this.installationStatus[index].status = "error";
+            this.installationStatus[index].details = data.notifications[0].additionalInformation;
+          }
+        }, data => {
+          this.installationStatus[index].status = "error";
+        })
+        .add(() => {
+          if (index < this.endpointItemsToInstall.length - 1) {
+            index++;
+            this.initiateInstallation(this.endpointItemsToInstall[index], index);
+          } else {
+            this.installedItemsChanged = true;
+            this.nextButton = "Close";
+            this.installationRunning = false;
+          }
+        });
+  }
+
+  uninstallElement(endpointUri, index) {
+    this.PipelineElementEndpointService.del(endpointUri.uri)
+        .subscribe(data => {
+          if (data.success) {
+            this.installationStatus[index].status = "success";
+          } else {
+            this.installationStatus[index].status = "error";
+          }
+        }, data => {
+          this.installationStatus[index].status = "error";
+        })
+        .add(() => {
+          if (index < this.endpointItemsToInstall.length - 1) {
+            index++;
+            this.initiateInstallation(this.endpointItemsToInstall[index], index);
+          } else {
+            this.nextButton = "Close";
+            this.installationRunning = false;
+            this.installedItemsChanged = true;
+          }
+        });
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.controller.ts b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.controller.ts
deleted file mode 100644
index 2f53911..0000000
--- a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.controller.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import {RestApi} from "../../../services/rest-api.service";
-
-export class EndpointInstallationController {
-
-    $mdDialog: any;
-    RestApi: RestApi;
-    endpointItems : any;
-    install: any;
-    endpointItemsToInstall: any;
-    installationStatus: any;
-    installationFinished: any;
-    page: any;
-    nextButton: any;
-    installationRunning: any;
-    getEndpointItems: any;
-
-    constructor($mdDialog, RestApi, endpointItems, install, getEndpointItems) {
-        this.$mdDialog = $mdDialog;
-        this.RestApi = RestApi;
-        this.endpointItems = endpointItems;
-        this.install = install;
-        this.endpointItemsToInstall = endpointItems;
-        this.installationStatus = [];
-        this.installationFinished = false;
-        this.page = "preview";
-        this.install = install;
-        this.nextButton = "Next";
-        this.installationRunning = false;
-        this.getEndpointItems = getEndpointItems;
-    }
-
-    hide() {
-        this.$mdDialog.hide();
-    }
-
-    cancel() {
-        this.$mdDialog.cancel();
-    }
-
-    next() {
-        if (this.page === "installation") {
-            this.cancel();
-        } else {
-            this.page = "installation";
-            this.initiateInstallation(this.endpointItemsToInstall[0], 0);
-        }
-    }
-
-    initiateInstallation(endpointUri, index) {
-        this.installationRunning = true;
-        this.installationStatus.push({"name": endpointUri.name, "id": index, "status": "waiting"});
-        if (this.install) {
-            this.installElement(endpointUri, index);
-        } else {
-            this.uninstallElement(endpointUri, index);
-        }
-    }
-
-
-    installElement(endpointUri, index) {
-        endpointUri = encodeURIComponent(endpointUri.uri);
-
-        this.RestApi.add(endpointUri, true)
-            .then(msg => {
-                let data = msg.data;
-                if (data.success) {
-                    this.installationStatus[index].status = "success";
-                } else {
-                    this.installationStatus[index].status = "error";
-                    this.installationStatus[index].details = data.notifications[0].additionalInformation;
-                }
-            }, data => {
-                this.installationStatus[index].status = "error";
-            })
-            .then(() => {
-                if (index < this.endpointItemsToInstall.length - 1) {
-                    index++;
-                    this.initiateInstallation(this.endpointItemsToInstall[index], index);
-                } else {
-                    this.getEndpointItems();
-                    this.nextButton = "Close";
-                    this.installationRunning = false;
-                }
-            });
-    }
-
-    uninstallElement(endpointUri, index) {
-        this.RestApi.del(endpointUri.uri)
-            .then(msg => {
-                let data = msg.data;
-                if (data.success) {
-                    this.installationStatus[index].status = "success";
-                } else {
-                    this.installationStatus[index].status = "error";
-                }
-            }, data => {
-                this.installationStatus[index].status = "error";
-            })
-            .then(() => {
-                if (index < this.endpointItemsToInstall.length - 1) {
-                    index++;
-                    this.initiateInstallation(this.endpointItemsToInstall[index], index);
-                } else {
-                    this.nextButton = "Close";
-                    this.installationRunning = false;
-                    this.getEndpointItems();
-                }
-            });
-    }
-}
-
-EndpointInstallationController.$inject = ['$mdDialog', 'RestApi', 'endpointItems', 'install', 'getEndpointItems'];
\ No newline at end of file
diff --git a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.tmpl.html b/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.tmpl.html
deleted file mode 100644
index 017752b..0000000
--- a/ui/src/app/add/dialogs/endpoint-installation/endpoint-installation.tmpl.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<md-dialog aria-label="Installation" flex="60" class="colored-frame">
-    <form>
-        <md-toolbar>
-            <div class="md-toolbar-tools">
-                <h2>Installation</h2>
-                <span flex></span>
-                <md-button class="md-icon-button" ng-click="ctrl.cancel()">
-                    <md-icon md-svg-icon="navigation:ic_close_24px" aria-label="Close dialog"></md-icon>
-                </md-button>
-            </div>
-        </md-toolbar>
-        <div>
-            <div flex="100" class="md-dialog-content" style="padding:20px;" ng-show="ctrl.page == 'preview'">
-                <h4>You are about to {{ctrl.install ? 'install' : 'uninstall'}} the following elements:</h4>
-                <div ng-repeat="endpointItem in ctrl.endpointItemsToInstall">
-                    <h5>{{endpointItem.name}}</h5>
-                </div>
-                <h5><b>Press 'Next' to start the process.</b></h5>
-            </div>
-            <div flex="100" class="md-dialog-content" style="padding:20px;" ng-show="ctrl.page == 'installation'">
-                <div ng-repeat="status in ctrl.installationStatus">
-                    <h4>{{ctrl.install ? 'Installing' : 'Uninstalling'}} {{status.id+1}} of {{ctrl.endpointItemsToInstall.length}} ({{status.name}})...{{status.status}}</h4>
-                    <div>
-                        <div flex layout="column" ng-show="status.details">
-                            <b>More Details:</b>
-                            <div class="md-padding"><i class="fa fa-terminal">{{status.details}}</i></div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-        </div>
-        <md-dialog-actions layout="row">
-            <sp-button sp-button-gray ng-click="ctrl.cancel()">
-                Cancel
-            </sp-button>
-            <sp-button sp-button-blue ng-disabled="ctrl.installationRunning" ng-click="ctrl.next()">
-                {{ctrl.nextButton}}
-            </sp-button>
-        </md-dialog-actions>
-    </form>
-</md-dialog>
\ No newline at end of file
diff --git a/ui/src/app/add/endpoint-item.tmpl.html b/ui/src/app/add/endpoint-item.tmpl.html
deleted file mode 100644
index e43120e..0000000
--- a/ui/src/app/add/endpoint-item.tmpl.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div flex="100" layout="column" layout-align="start start"
-     style="padding:5px;border:1px solid darkblue;margin-bottom:10px;background:{{ctrl.getSelectedBackground(endpointItem)}}"
-     ng-click="ctrl.toggleSelected(endpointItem)">
-    <div flex="100" layout-align="start start" class="{{ctrl.getItemStyle(endpointItem.type)}}">{{ctrl.getItemTitle(endpointItem.type)}}</div>
-    <div flex="100" style="width:100%;" layout="row" layout-align="start center">
-        <div flex="20" layout="row" style="margin:10px;">
-            <div class="draggable-icon {{endpointItem.type}}">{{ctrl.iconText(endpointItem.name)}}</div>
-        </div>
-        <div flex="80" layout="row" layout-align="start center" style="margin:10px;">
-            <div flex="100" layout="column">
-                <div layout="column">
-                    <div flex layout="column">
-                        <h2 class="md-title">{{endpointItem.name}}</h2>
-                        <p>{{endpointItem.description}}</p>
-                        <div flex layout="column" ng-if="endpointItem.type=='source'">
-                            <h4>Data streams included in this source</h4>
-                            <div flex layout="row" layout-align="start center" ng-repeat="stream in endpointItem.streams">
-                                <div flex="10" style="min-height:60px;">
-                                    <div class="draggable-icon-preview stream" style="margin-right:10px;">
-                                        {{ctrl.iconText(stream.name)}}
-                                    </div>
-                                </div>
-                                <div flex="90" style="min-height:60px;margin-left:10px;">
-                                    <h5><b>{{stream.name}}</b></h5>
-                                    <p>{{stream.description}}</p>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-
-                </div>
-
-                <div flex="100" layout="row" layout-align="end end">
-                    <div flex layout="row" layout-align="end end">
-						<span flex flex-order="1" layout="row" layout-align="end end" ng-if="!endpointItem.installed">
-							<sp-button sp-button-blue aria-label="Install"
-                                       ng-click="ctrl.installSingleElement(endpointItem)">
-                                <i class="material-icons">
-                                    cloud_download
-                                </i>
-								Install&nbsp;&nbsp;
-							</sp-button>
-						</span>
-                        <span flex flex-order="1" layout="row" layout-align="end end" ng-if="endpointItem.installed">
-	  						<md-progress-circular md-mode="indeterminate" class="md-accent"
-                                                  ng-show="uninstalling"></md-progress-circular>
-							<sp-button sp-button-blue aria-label="Uninstall"
-                                       ng-click="ctrl.uninstallSingleElement(endpointItem)">
-								<i class="material-icons">
-                                    delete
-                                </i>&nbsp;&nbsp; Uninstall&nbsp;&nbsp;
-							</sp-button>
-						</span>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
\ No newline at end of file
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/filter/order-by.pipe.ts
similarity index 55%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/filter/order-by.pipe.ts
index 7de767a..0af99c8 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/filter/order-by.pipe.ts
@@ -16,9 +16,26 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
+import {Pipe, PipeTransform} from '@angular/core';
 
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+@Pipe({name: 'orderBy'})
+export class OrderByPipe implements PipeTransform {
+
+  transform(value: any[], order = '', column: string = ''): any[] {
+    if (!value || order === '' || !order) {
+      return value;
+    }
+    if (value.length <= 1) {
+      return value;
+    }
+    if (!column || column === '') {
+      if (order === 'asc') {
+        return value.sort();
+      } else {
+        return value.sort().reverse();
+      }
+    }
+    let sortedValues = value.sort((a, b) => a[column].localeCompare(b[column]));
+    return order === 'asc' ? sortedValues : sortedValues.reverse();
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/add.module.ts b/ui/src/app/add/filter/pipeline-element-type.pipe.ts
similarity index 69%
copy from ui/src/app/add/add.module.ts
copy to ui/src/app/add/filter/pipeline-element-type.pipe.ts
index 7de767a..24bd5cc 100644
--- a/ui/src/app/add/add.module.ts
+++ b/ui/src/app/add/filter/pipeline-element-type.pipe.ts
@@ -16,9 +16,19 @@
  *
  */
 
-import * as angular from 'angular';
-import {AddCtrl} from './add.controller'
+import {Pipe, PipeTransform} from "@angular/core";
 
-export default angular.module('sp.add', [])
-	.controller('AddCtrl', AddCtrl)
-	.name;
+@Pipe({
+  name: 'pipelineElementTypeFilter',
+  pure: false
+})
+export class PipelineElementTypeFilter implements PipeTransform {
+
+  transform(value: any[], type: string): any[] {
+    if (type === "all") {
+      return value;
+    } else {
+      return value.filter(v => v.type === type);
+    }
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/add/services/add.service.ts b/ui/src/app/add/services/add.service.ts
new file mode 100644
index 0000000..74c5f52
--- /dev/null
+++ b/ui/src/app/add/services/add.service.ts
@@ -0,0 +1,49 @@
+/*
+ * 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 {AuthStatusService} from "../../services/auth-status.service";
+import {PlatformServicesCommons} from "../../platform-services/apis/commons.service";
+import {Observable} from "rxjs";
+
+@Injectable()
+export class AddService {
+
+
+  constructor(private http: HttpClient,
+              private authStatusService: AuthStatusService,
+              private platformServicesCommons: PlatformServicesCommons) {
+  }
+
+  getRdfEndpoints(): Observable<any> {
+    return this.http.get(this.platformServicesCommons.authUserBasePath() + "/rdfendpoints");
+  }
+
+  getRdfEndpointItems(): Observable<any> {
+    return this.http.get(this.platformServicesCommons.authUserBasePath() + "/rdfendpoints/items");
+  }
+
+  addRdfEndpoint(rdfEndpoint): Observable<any> {
+    return this.http.post(this.platformServicesCommons.authUserBasePath() + "/rdfendpoints", rdfEndpoint);
+  }
+
+  removeRdfEndpoint(rdfEndpointId): Observable<any> {
+    return this.http.delete(this.platformServicesCommons.authUserBasePath() + "/rdfendpoints/" + rdfEndpointId);
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/platform-services/apis/pipeline-element-endpoint.service.ts b/ui/src/app/platform-services/apis/pipeline-element-endpoint.service.ts
new file mode 100644
index 0000000..f8f78b5
--- /dev/null
+++ b/ui/src/app/platform-services/apis/pipeline-element-endpoint.service.ts
@@ -0,0 +1,52 @@
+import {Injectable} from "@angular/core";
+import {HttpClient, HttpParams} from "@angular/common/http";
+import {PlatformServicesCommons} from "./commons.service";
+import {Observable} from "rxjs";
+
+/*
+ * 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.
+ *
+ */
+
+@Injectable()
+export class PipelineElementEndpointService {
+
+  constructor(private http: HttpClient,
+              private platformServicesCommons: PlatformServicesCommons) {
+  }
+
+  add(elementUri, ispublic): Observable<any> {
+    const payload = new HttpParams()
+        .set('uri', elementUri)
+        .set('publicElement', ispublic);
+    return this.http.post(this.platformServicesCommons.authUserBasePath() + "/element", payload);
+  }
+
+  addBatch(elementUris, ispublic): Observable<any> {
+    const payload = new HttpParams()
+        .set('uri', elementUris)
+        .set('publicElement', ispublic);
+    return this.http.post(this.platformServicesCommons.authUserBasePath() + "/element/batch", payload);
+  }
+
+  update(elementUri): Observable<any> {
+    return this.http.put(this.platformServicesCommons.authUserBasePath() + "/element/" + encodeURIComponent(elementUri), undefined);
+  }
+
+  del(elementUri): Observable<any> {
+    return this.http.delete(this.platformServicesCommons.authUserBasePath() + "/element/" + encodeURIComponent(elementUri));
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/platform-services/platform.module.ts b/ui/src/app/platform-services/platform.module.ts
index 1d235d2..5df955d 100644
--- a/ui/src/app/platform-services/platform.module.ts
+++ b/ui/src/app/platform-services/platform.module.ts
@@ -22,12 +22,14 @@ import {PipelineTemplateService} from './apis/pipeline-template.service';
 import {PipelineElementService} from "./apis/pipeline-element.service";
 import {PipelineService} from "./apis/pipeline.service";
 import {PlatformServicesCommons} from "./apis/commons.service";
+import {PipelineElementEndpointService} from "./apis/pipeline-element-endpoint.service";
 
 @NgModule({
   imports: [],
   declarations: [],
   providers: [
     PlatformServicesCommons,
+    PipelineElementEndpointService,
     TsonLdSerializerService,
     PipelineTemplateService,
     PipelineElementService,
diff --git a/ui/src/app/services/rest-api.service.ts b/ui/src/app/services/rest-api.service.ts
index ad9491e..bb7f856 100644
--- a/ui/src/app/services/rest-api.service.ts
+++ b/ui/src/app/services/rest-api.service.ts
@@ -156,38 +156,6 @@ export class RestApi {
 
     };
 
-    add(elementUri, ispublic) {
-        return this.$http({
-            method: 'POST',
-            url: this.urlBase() + "/element",
-            data: $.param({uri: elementUri, publicElement: ispublic}),
-            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
-        })
-    }
-
-    addBatch(elementUris, ispublic) {
-        return this.$http({
-            method: 'POST',
-            url: this.urlBase() + "/element/batch",
-            data: $.param({uri: elementUris, publicElement: ispublic}),
-            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
-        })
-    }
-
-    update(elementUri) {
-        return this.$http({
-            method: 'PUT',
-            url: this.urlBase() + "/element/" + encodeURIComponent(elementUri)
-        })
-    }
-
-    del(elementUri) {
-        return this.$http({
-            method: 'DELETE',
-            url: this.urlBase() + "/element/" + encodeURIComponent(elementUri)
-        })
-    }
-
     jsonld(elementUri) {
         return this.$http.get(this.urlBase() +"/element/" + encodeURIComponent(elementUri) +"/jsonld");
     }
@@ -494,21 +462,6 @@ export class RestApi {
         return this.$http.get(this.urlBase() +"/marketplace/pods");
     }
 
-    getRdfEndpoints() {
-        return this.$http.get(this.urlBase() +"/rdfendpoints");
-    }
-
-    getRdfEndpointItems() {
-        return this.$http.get(this.urlBase() +"/rdfendpoints/items");
-    }
-
-    addRdfEndpoint(rdfEndpoint) {
-        return this.$http.post(this.urlBase() +"/rdfendpoints", rdfEndpoint);
-    }
-
-    removeRdfEndpoint(rdfEndpointId) {
-        return this.$http.delete(this.urlBase() +"/rdfendpoints/" +rdfEndpointId);
-    }
 
     getAuthc() {
         return this.$http.get(this.getServerUrl() + "/admin/authc");