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 2022/08/25 14:38:31 UTC

[incubator-streampipes] 03/03: [hotfix] Add button to delete an adapter description

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

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

commit d0d11d52d9f3e0601ca3dcde8e6ac3309d72dc73
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Thu Aug 25 16:38:16 2022 +0200

    [hotfix] Add button to delete an adapter description
---
 .../master/management/DescriptionManagement.java      | 19 +++++++++++++++++++
 .../rest/impl/connect/DescriptionResource.java        | 17 +++++++++++++----
 .../platform-services/src/lib/apis/adapter.service.ts |  5 ++++-
 .../adapter-description.component.html                | 14 ++++++++++++--
 .../adapter-description.component.ts                  | 12 +++++++++++-
 .../data-marketplace/data-marketplace.component.html  |  1 +
 ui/src/app/connect/connect.module.ts                  |  2 ++
 7 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
index 834c76464..da40e4995 100644
--- a/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
+++ b/streampipes-connect-container-master/src/main/java/org/apache/streampipes/connect/container/master/management/DescriptionManagement.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.container.master.management;
 
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.adapter.AdapterRegistry;
 import org.apache.streampipes.connect.api.IFormat;
 import org.apache.streampipes.connect.api.exception.AdapterException;
@@ -25,6 +26,7 @@ import org.apache.streampipes.model.connect.adapter.AdapterDescription;
 import org.apache.streampipes.model.connect.grounding.FormatDescription;
 import org.apache.streampipes.storage.api.IAdapterStorage;
 import org.apache.streampipes.storage.couchdb.CouchDbStorageManager;
+import org.apache.streampipes.storage.management.StorageDispatcher;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -55,6 +57,15 @@ public class DescriptionManagement {
                 .findFirst();
     }
 
+    public void deleteAdapterDescription(String id) throws SpRuntimeException {
+        var adapterStorage = CouchDbStorageManager.INSTANCE.getAdapterDescriptionStorage();
+        var adapter = adapterStorage.getAdapter(id);
+        if (!isAdapterUsed(adapter)) {
+            adapterStorage.deleteAdapter(id);
+        } else {
+            throw new SpRuntimeException("This adapter is used by an existing instance and cannot be deleted");
+        }
+    }
     public String getAssets(String baseUrl) throws AdapterException {
         return WorkerRestClient.getAssets(baseUrl);
     }
@@ -67,4 +78,12 @@ public class DescriptionManagement {
         return WorkerRestClient.getDocumentationAsset(baseUrl);
     }
 
+    private boolean isAdapterUsed(AdapterDescription adapter) {
+        var allAdapters = StorageDispatcher.INSTANCE.getNoSqlStore().getAdapterInstanceStorage().getAllAdapters();
+
+        return allAdapters
+          .stream()
+          .anyMatch(runningAdapter -> runningAdapter.getAppId().equals(adapter.getAppId()));
+    }
+
 }
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
index 90e6508a6..56819527e 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/DescriptionResource.java
@@ -18,6 +18,7 @@
 package org.apache.streampipes.rest.impl.connect;
 
 import org.apache.streampipes.commons.exceptions.NoServiceEndpointsAvailableException;
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
 import org.apache.streampipes.connect.api.exception.AdapterException;
 import org.apache.streampipes.connect.container.master.management.DescriptionManagement;
 import org.apache.streampipes.connect.container.master.management.WorkerUrlProvider;
@@ -27,10 +28,7 @@ import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.List;
@@ -154,4 +152,15 @@ public class DescriptionResource extends AbstractAdapterResource<DescriptionMana
             return fail();
         }
     }
+
+    @DELETE
+    @Path("{adapterId}")
+    public Response deleteAdapter(@PathParam("adapterId") String adapterId) {
+        try {
+            this.managementService.deleteAdapterDescription(adapterId);
+            return ok();
+        } catch (SpRuntimeException e) {
+            return badRequest(e);
+        }
+    }
 }
diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
index d60352000..f337ab43e 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
@@ -38,13 +38,16 @@ export class AdapterService {
 
   getAdapterDescriptions(): Observable<AdapterDescriptionUnion[]> {
     return this.requestAdapterDescriptions('/master/description/adapters');
-
   }
 
   getAdapters(): Observable<AdapterDescriptionUnion[]> {
     return this.requestAdapterDescriptions('/master/adapters');
   }
 
+  deleteAdapterDescription(adapterId: string): Observable<any> {
+    return this.http.delete(`${this.connectPath}/master/description/${adapterId}`);
+  }
+
   requestAdapterDescriptions(path: string): Observable<AdapterDescriptionUnion[]> {
     return this.http
       .get(
diff --git a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
index 29c2b0821..52aa74ae5 100644
--- a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
+++ b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.html
@@ -19,13 +19,23 @@
 <div [className]="className" fxFlex="100"
      fxLayout="column">
     <div fxLayout="column">
-        <div class="type" fxLayout="column" fxLayoutAlign="start start">
-            <div class="type-data" fxLayout="row" fxLayoutAlign="start start">
+        <div class="type" fxLayout="row" fxLayoutAlign="start start" fxFlex="100">
+            <div class="type-data" fxLayout="row" fxLayoutAlign="start center" fxFlex>
                 <mat-icon *ngIf="isDataSetDescription" class="historic">lens</mat-icon>
                 <mat-icon *ngIf="isDataStreamDescription" class="real-time">lens</mat-icon>
                 <p *ngIf="isDataSetDescription">Data Set</p>
                 <p *ngIf="isDataStreamDescription">Data Stream</p>
             </div>
+            <div fxLayout="row" fxLayoutAlign="end end" style="margin-left:5px;">
+                <button class="small-button-add mat-basic no-min-width" (click)="$event.stopPropagation();"
+                        mat-raised-button mat-button [matMenuTriggerFor]="menu"><span style="font-size:12px;">...</span></button>
+                <mat-menu #menu="matMenu">
+                    <button mat-menu-item (click)="removeAdapter()">
+                        <mat-icon>delete</mat-icon>
+                        <span>&nbsp;Remove adapter</span>
+                    </button>
+                </mat-menu>
+            </div>
         </div>
         <div fxLayoutAlign="start center" fxLayout="column" class="icon">
             <img *ngIf="getIconUrl() && !adapter.icon" [src]="getIconUrl()" class="iconImg"/>
diff --git a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
index 89bea3356..c65fa3b09 100644
--- a/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
+++ b/ui/src/app/connect/components/data-marketplace/adapter-description/adapter-description.component.ts
@@ -22,6 +22,7 @@ import { AdapterExportDialog } from '../../../dialog/adapter-export/adapter-expo
 import { MatDialog } from '@angular/material/dialog';
 import { AdapterDescription, AdapterService } from '@streampipes/platform-services';
 import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { MatSnackBar } from '@angular/material/snack-bar';
 
 @Component({
   selector: 'sp-adapter-description',
@@ -50,7 +51,8 @@ export class AdapterDescriptionComponent implements OnInit {
   constructor(private connectService: ConnectService,
               private dataMarketplaceService: AdapterService,
               private dialogService: DialogService,
-              public dialog: MatDialog) {
+              public dialog: MatDialog,
+              private _snackBar: MatSnackBar) {
   }
 
   ngOnInit() {
@@ -111,4 +113,12 @@ export class AdapterDescriptionComponent implements OnInit {
       return `assets/img/connect/${this.adapter.iconUrl}`;
     }
   }
+
+  removeAdapter(): void {
+    this.dataMarketplaceService.deleteAdapterDescription(this.adapter.elementId).subscribe(res => {
+      this.updateAdapterEmitter.emit();
+    }, error => {
+      this._snackBar.open('Cannot delete an adapter which has an active instance running.');
+    });
+  }
 }
diff --git a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
index 0d279a7c8..61d9949d9 100644
--- a/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
+++ b/ui/src/app/connect/components/data-marketplace/data-marketplace.component.html
@@ -50,6 +50,7 @@
                     <sp-adapter-description attr.id="{{adapterDescription.name.replaceAll(' ', '_')}}"
                                             class="adapter-description"
                                             fxFlex="33"
+                                            (updateAdapterEmitter)="getAdapterDescriptions()"
                                             (click)="selectAdapter(adapterDescription.appId)"
                                             *ngFor="let adapterDescription of adapterDescriptions | adapterFilter:currentFilter"
                                             [adapter]="adapterDescription"></sp-adapter-description>
diff --git a/ui/src/app/connect/connect.module.ts b/ui/src/app/connect/connect.module.ts
index 1bd77b851..8d7bc1203 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -85,6 +85,7 @@ import { SpEpSettingsSectionComponent } from './dialog/edit-event-property/compo
 import { SpAdapterOptionsPanelComponent } from './components/new-adapter/start-adapter-configuration/adapter-options-panel/adapter-options-panel.component';
 import { SpAdapterTemplateDialogComponent } from './dialog/adapter-template/adapter-template-dialog.component';
 import { JsonPrettyPrintPipe } from './filter/json-pretty-print.pipe';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
 
 @NgModule({
   imports: [
@@ -100,6 +101,7 @@ import { JsonPrettyPrintPipe } from './filter/json-pretty-print.pipe';
     MatInputModule,
     MatFormFieldModule,
     MatSliderModule,
+    MatSnackBarModule,
     PlatformServicesModule,
     CoreUiModule,
     TreeModule,