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

zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new ce1d95f6e [#1113] Added buttons to start and stop all adapters (#1441)
ce1d95f6e is described below

commit ce1d95f6e11a9ed2d29363fe21bcf5f2ac8c03b5
Author: Neetha Reddy <[email protected]>
AuthorDate: Tue Mar 28 20:35:53 2023 +0530

    [#1113] Added buttons to start and stop all adapters (#1441)
    
    * Added buttons to start and stop all adapters
    
    * Changed variable names, added filters and removed redundancy
    
    * Added cypress tests for buttons
    
    ---------
    
    Co-authored-by: Neetha Reddy <[email protected]>
---
 ui/cypress/support/utils/connect/ConnectBtns.ts    |   8 ++
 ui/cypress/support/utils/connect/ConnectUtils.ts   |   9 ++
 .../tests/adapter/allAdapterActions.smoke.spec.ts  |  40 +++++++
 .../existing-adapters.component.html               |  28 ++++-
 .../existing-adapters.component.ts                 |  34 ++++++
 ui/src/app/connect/connect.module.ts               |   2 +
 .../all-adapter-actions-dialog.component.html      |  81 ++++++++++++++
 .../all-adapter-actions-dialog.component.scss      |  19 ++++
 .../all-adapter-actions-dialog.component.ts        | 120 +++++++++++++++++++++
 9 files changed, 337 insertions(+), 4 deletions(-)

diff --git a/ui/cypress/support/utils/connect/ConnectBtns.ts 
b/ui/cypress/support/utils/connect/ConnectBtns.ts
index f5fbf1451..0a336606a 100644
--- a/ui/cypress/support/utils/connect/ConnectBtns.ts
+++ b/ui/cypress/support/utils/connect/ConnectBtns.ts
@@ -91,5 +91,13 @@ export class ConnectBtns {
         return cy.dataCy('start-adapter-now-checkbox');
     }
 
+    public static startAllAdapters() {
+        return cy.dataCy('start-all-adapters-btn');
+    }
+
+    public static stopAllAdapters() {
+        return cy.dataCy('stop-all-adapters-btn');
+    }
+
     // ========================================================================
 }
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts 
b/ui/cypress/support/utils/connect/ConnectUtils.ts
index 18b9c51bf..79e984847 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -308,4 +308,13 @@ export class ConnectUtils {
             ignoreTime,
         );
     }
+
+    public static allAdapterActionsDialog() {
+        // Click next
+        cy.get('button').contains('Next').parent().click();
+        // Wait for the adapters to start/stop
+        cy.wait(2000);
+        // Close dialog
+        cy.get('button').contains('Close').parent().click();
+    }
 }
diff --git a/ui/cypress/tests/adapter/allAdapterActions.smoke.spec.ts 
b/ui/cypress/tests/adapter/allAdapterActions.smoke.spec.ts
new file mode 100644
index 000000000..fe91a5707
--- /dev/null
+++ b/ui/cypress/tests/adapter/allAdapterActions.smoke.spec.ts
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+import { ConnectUtils } from '../../support/utils/connect/ConnectUtils';
+import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
+
+describe('Testing Start/Stop All Adapters', () => {
+    beforeEach('Setup Test', () => {
+        // To set up test, we are adding 2 stream adapters that can be futher 
configured
+        cy.initStreamPipesTest();
+        ConnectUtils.addMachineDataSimulator('simulator-1');
+        ConnectUtils.addMachineDataSimulator('simulator-2');
+    });
+
+    it('Test start/stop all adapters', () => {
+        // Clicking the stop all adapters button
+        ConnectBtns.stopAllAdapters().click();
+        // Navigating through the stop all adapters dialog box
+        ConnectUtils.allAdapterActionsDialog();
+        // Clicking the start all adapters button
+        ConnectBtns.startAllAdapters().click();
+        // Navigating through the start all adapters dialog box
+        ConnectUtils.allAdapterActionsDialog();
+    });
+});
diff --git 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
index 4f1fbe342..c9865e324 100644
--- 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
+++ 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.html
@@ -32,12 +32,32 @@
         >
             <i class="material-icons">add</i>&nbsp;New adapter
         </button>
-        <sp-connect-filter-toolbar
-            class="filter-bar-margin"
-            (filterChangedEmitter)="applyFilter($event)"
+        <button
+            class="mr-10"
+            mat-button
+            color="accent"
+            data-cy="start-all-adapters-btn"
+            [disabled]="checkCurrentSelectionStatus(false)"
+            (click)="startAllAdapters(true)"
+        >
+            <mat-icon>play_arrow</mat-icon><span>Start all adapters</span>
+        </button>
+        <button
+            mat-button
+            color="accent"
+            data-cy="stop-all-adapters-btn"
+            [disabled]="checkCurrentSelectionStatus(true)"
+            (click)="startAllAdapters(false)"
         >
-        </sp-connect-filter-toolbar>
+            <mat-icon>stop</mat-icon>
+            <span>Stop all adapters</span>
+        </button>
         <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+            <sp-connect-filter-toolbar
+                class="filter-bar-margin"
+                (filterChangedEmitter)="applyFilter($event)"
+            >
+            </sp-connect-filter-toolbar>
             <button
                 mat-button
                 mat-icon-button
diff --git 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
index da5d4a016..e4dd536ea 100644
--- 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
+++ 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
@@ -25,6 +25,7 @@ import {
     SpMetricsEntry,
     StreamPipesErrorMessage,
     PipelineService,
+    AdapterStreamDescription,
 } from '@streampipes/platform-services';
 import { MatTableDataSource } from '@angular/material/table';
 import { ConnectService } from '../../services/connect.service';
@@ -36,6 +37,7 @@ import {
     SpExceptionDetailsDialogComponent,
 } from '@streampipes/shared-ui';
 import { DeleteAdapterDialogComponent } from 
'../../dialog/delete-adapter-dialog/delete-adapter-dialog.component';
+import { AllAdapterActionsComponent } from 
'../../dialog/start-all-adapters/all-adapter-actions-dialog.component';
 import { MatPaginator } from '@angular/material/paginator';
 import { MatSort } from '@angular/material/sort';
 import { ObjectPermissionDialogComponent } from 
'../../../core-ui/object-permission-dialog/object-permission-dialog.component';
@@ -131,6 +133,38 @@ export class ExistingAdaptersComponent implements OnInit {
         );
     }
 
+    checkCurrentSelectionStatus(status) {
+        let active = true;
+        this.existingAdapters.forEach(adapter => {
+            if (
+                adapter instanceof AdapterStreamDescription &&
+                adapter.running == status
+            ) {
+                active = false;
+            }
+        });
+        return active;
+    }
+
+    startAllAdapters(action: boolean) {
+        const dialogRef: DialogRef<AllAdapterActionsComponent> =
+            this.dialogService.open(AllAdapterActionsComponent, {
+                panelType: PanelType.STANDARD_PANEL,
+                title: (action ? 'Start' : 'Stop') + ' all adapters',
+                width: '70vw',
+                data: {
+                    adapters: this.existingAdapters,
+                    action: action,
+                },
+            });
+
+        dialogRef.afterClosed().subscribe(data => {
+            if (data) {
+                this.getAdaptersRunning();
+            }
+        });
+    }
+
     openAdapterStatusErrorDialog(
         message: StreamPipesErrorMessage,
         title: string,
diff --git a/ui/src/app/connect/connect.module.ts 
b/ui/src/app/connect/connect.module.ts
index 5fa2a0052..b6d076625 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -89,6 +89,7 @@ import { SpAdapterDetailsLogsComponent } from 
'./components/adapter-details/adap
 import { SpAdapterDetailsMetricsComponent } from 
'./components/adapter-details/adapter-details-metrics/adapter-details-metrics.component';
 import { SpecificAdapterConfigurationComponent } from 
'./components/adapter-configuration/specific-adapter-configuration/specific-adapter-configuration.component';
 import { CanNotEditAdapterDialog } from 
'./dialog/can-not-edit-adapter-dialog/can-not-edit-adapter-dialog.component';
+import { AllAdapterActionsComponent } from 
'./dialog/start-all-adapters/all-adapter-actions-dialog.component';
 
 @NgModule({
     imports: [
@@ -191,6 +192,7 @@ import { CanNotEditAdapterDialog } from 
'./dialog/can-not-edit-adapter-dialog/ca
         EditAdapterComponent,
         EventSchemaErrorHintsComponent,
         CanNotEditAdapterDialog,
+        AllAdapterActionsComponent,
     ],
     providers: [
         RestService,
diff --git 
a/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.html
 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.html
new file mode 100644
index 000000000..fb62d1347
--- /dev/null
+++ 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.html
@@ -0,0 +1,81 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div>
+            <div
+                fxFlex="100"
+                class="md-dialog-content"
+                style="padding: 20px"
+                *ngIf="page === 'preview'"
+            >
+                <h4>
+                    You are about to {{ action ? 'start' : 'stop' }} the
+                    following adapters:
+                </h4>
+                <div *ngFor="let adapter of adaptersToModify">
+                    <h5>{{ adapter.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 === 'running'"
+            >
+                <div *ngFor="let status of actionStatus">
+                    <h4>
+                        {{ action ? 'Starting adapter ' : 'Stopping adapter' }}
+                        {{ status.id + 1 }} of {{ adaptersToModify.length }} 
({{
+                            status.name
+                        }})...{{ status.status }}
+                    </h4>
+                </div>
+                <div *ngIf="adaptersToModify.length === 0">
+                    <h4>
+                        Sorry, there are no adapters that are currently
+                        {{ action ? 'idle.' : 'running.' }}
+                    </h4>
+                </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(false)"
+            style="margin-right: 10px"
+        >
+            Cancel
+        </button>
+        <button
+            mat-button
+            mat-raised-button
+            color="accent"
+            [disabled]="actionRunning"
+            (click)="next()"
+        >
+            {{ nextButton }}
+        </button>
+    </div>
+</div>
diff --git 
a/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.scss
 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.scss
new file mode 100644
index 000000000..fddade7bf
--- /dev/null
+++ 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.scss
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+@import '../../../../scss/sp/sp-dialog.scss';
diff --git 
a/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
new file mode 100644
index 000000000..f99fa3ad7
--- /dev/null
+++ 
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import {
+    AdapterDescriptionUnion,
+    AdapterService,
+    AdapterStreamDescription,
+} from '@streampipes/platform-services';
+
+@Component({
+    selector: 'sp-start-all-adapters-dialog',
+    templateUrl: './all-adapter-actions-dialog.component.html',
+    styleUrls: ['./all-adapter-actions-dialog.component.scss'],
+})
+export class AllAdapterActionsComponent implements OnInit {
+    @Input()
+    adapters: AdapterDescriptionUnion[];
+
+    adaptersToModify: AdapterDescriptionUnion[];
+    actionStatus: any;
+    actionFinished: boolean;
+    page: string;
+    nextButton: string;
+    actionRunning: boolean;
+
+    @Input()
+    action: boolean;
+
+    constructor(
+        private dialogRef: DialogRef<AllAdapterActionsComponent>,
+        private adapterService: AdapterService,
+    ) {
+        this.adaptersToModify = [];
+        this.actionStatus = [];
+        this.actionFinished = false;
+        this.page = 'preview';
+        this.nextButton = 'Next';
+        this.actionRunning = false;
+    }
+
+    ngOnInit() {
+        this.getAdaptersToModify();
+        if (this.adaptersToModify.length === 0) {
+            this.nextButton = 'Close';
+            this.page = 'running';
+        }
+    }
+
+    close(refreshAdapters: boolean) {
+        this.dialogRef.close(refreshAdapters);
+    }
+
+    next() {
+        if (this.page === 'running') {
+            this.close(true);
+        } else {
+            this.page = 'running';
+            this.initiateAction(this.adaptersToModify[0], 0);
+        }
+    }
+
+    getAdaptersToModify() {
+        this.adapters.forEach(adapter => {
+            if (
+                adapter instanceof AdapterStreamDescription &&
+                adapter.running != this.action
+            ) {
+                this.adaptersToModify.push(adapter);
+            }
+        });
+    }
+
+    initiateAction(adapter: AdapterDescriptionUnion, index) {
+        this.actionRunning = true;
+        this.actionStatus.push({
+            name: adapter.name,
+            id: index,
+            status: 'waiting',
+        });
+        this.runAdapterAction(adapter, index);
+    }
+
+    runAdapterAction(adapter: AdapterDescriptionUnion, index) {
+        const observable = this.action
+            ? this.adapterService.startAdapter(adapter)
+            : this.adapterService.stopAdapter(adapter);
+        observable
+            .subscribe(data => {
+                this.actionStatus[index].status = data.success
+                    ? 'success'
+                    : 'error';
+            })
+            .add(() => {
+                if (index < this.adaptersToModify.length - 1) {
+                    index++;
+                    this.initiateAction(this.adaptersToModify[index], index);
+                } else {
+                    this.nextButton = 'Close';
+                    this.actionRunning = false;
+                }
+            });
+    }
+}

Reply via email to