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

riemer 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 39228cc6bf feat: Modify data table actions (#3816)
39228cc6bf is described below

commit 39228cc6bf41af6a69d26c532680ca8380c69a8d
Author: Dominik Riemer <[email protected]>
AuthorDate: Tue Oct 7 07:17:17 2025 +0200

    feat: Modify data table actions (#3816)
---
 ui/cypress.config.ts                               |  20 +-
 .../support/utils/DataDownloadDialogUtils.ts       |   2 +
 ui/cypress/support/utils/asset/AssetUtils.ts       |   3 +
 ui/cypress/support/utils/connect/ConnectBtns.ts    |  10 +
 ui/cypress/support/utils/connect/ConnectUtils.ts   |  28 ++-
 ui/cypress/support/utils/datalake/DataLakeBtns.ts  |   7 +-
 ui/cypress/support/utils/datalake/DataLakeUtils.ts |   3 +
 ui/cypress/support/utils/pipeline/PipelineUtils.ts |   8 +-
 ui/cypress/support/utils/user/PermissionUtils.ts   |  12 +-
 .../compactAdapterWithTransformation.spec.ts       |   4 +-
 .../tests/connect/compact/uiConfiguration.spec.ts  |   1 +
 ui/cypress/tests/connect/editAdapter.smoke.spec.ts |   9 +-
 .../editAdapterSettingsAndPipeline.smoke.spec.ts   |   3 +
 .../editAdapterTransformationRulesAreKept.spec.ts  |   1 +
 .../connect/editAdapterValuesAndFields.spec.ts     |   2 +
 ui/cypress/tests/connect/fileStream.spec.ts        |   4 +-
 .../connect/machineDataSimulator.smoke.spec.ts     |   2 +-
 .../opcua/startAndEditOpcAdapters.smoke.spec.ts    |   6 +-
 .../connect/rules/addNumericalStaticValue.spec.ts  |   2 +
 .../tests/datalake/configuration.smoke.spec.ts     |   2 +-
 .../tests/datalake/timeOrderDataView.spec.ts       |   2 +-
 .../tests/pipeline/pipelineTest.smoke.spec.ts      |   2 +-
 .../tests/pipeline/renamePipelineTest.spec.ts      |   4 +-
 .../pipeline/updatePipelineTest.smoke.spec.ts      |  15 +-
 .../userManagement/testGroupManagement.spec.ts     |   2 +-
 .../userManagement/testUserRoleConnect.spec.ts     |   4 +-
 .../userManagement/testUserRolePipeline.spec.ts    |   8 +-
 .../components/sp-table/sp-table.component.html    |  62 ++---
 .../components/sp-table/sp-table.component.scss    |   5 +
 ui/src/app/assets/assets.module.ts                 |   4 +
 .../asset-overview/asset-overview.component.html   |  80 +++---
 .../asset-overview/asset-overview.component.ts     |   2 +-
 .../existing-adapters.component.html               | 179 +++++++++-----
 .../existing-adapters.component.scss               |   2 +-
 .../existing-adapters.component.ts                 |   2 +-
 ui/src/app/connect/connect.module.ts               |   3 +
 .../dashboard-overview-table.component.html        |  36 +--
 .../data-explorer-overview-table.component.html    | 162 +++++-------
 .../pipeline-overview.component.html               | 273 +++++++++++++--------
 .../pipeline-overview.component.ts                 |   2 +-
 ui/src/app/pipelines/pipelines.module.ts           |   2 +
 ui/src/scss/sp/main.scss                           |   6 +
 42 files changed, 548 insertions(+), 438 deletions(-)

diff --git a/ui/cypress.config.ts b/ui/cypress.config.ts
index 822e9a8c0e..1c62181e9c 100644
--- a/ui/cypress.config.ts
+++ b/ui/cypress.config.ts
@@ -45,7 +45,25 @@ export default defineConfig({
         // We've imported your old cypress plugins here.
         // You may want to clean this up later by importing these.
         setupNodeEvents(on, config) {
-            return require('./cypress/plugins/index.ts')(on, config);
+            const plugins = require('./cypress/plugins/index.ts')(on, config);
+
+            // Add language setting for Chromium & Firefox
+            on('before:browser:launch', (browser, launchOptions) => {
+                if (browser.family === 'chromium') {
+                    // Chrome / Edge
+                    launchOptions.args.push('--lang=en-US,en');
+                } else if (browser.family === 'firefox') {
+                    // Firefox
+                    // preferences is optional in the type, so guard + cast
+                    launchOptions.preferences ??= {};
+                    (launchOptions.preferences as Record<string, unknown>)[
+                        'intl.accept_languages'
+                    ] = 'en-US';
+                }
+                return launchOptions;
+            });
+
+            return plugins;
         },
         specPattern: 'cypress/tests/**/*.{js,jsx,ts,tsx}',
         baseUrl: 'http://localhost:80',
diff --git a/ui/cypress/support/utils/DataDownloadDialogUtils.ts 
b/ui/cypress/support/utils/DataDownloadDialogUtils.ts
index 3a3b2da6ed..b7cf5a148d 100644
--- a/ui/cypress/support/utils/DataDownloadDialogUtils.ts
+++ b/ui/cypress/support/utils/DataDownloadDialogUtils.ts
@@ -20,6 +20,7 @@ import { ExportConfig } from 
'../../../projects/streampipes/shared-ui/src/lib/di
 import { DataLakeUtils } from './datalake/DataLakeUtils';
 import { FileNameService } from 
'../../../projects/streampipes/shared-ui/src/lib/dialog/data-download-dialog/services/file-name.service';
 import { CsvFormatExportConfig } from 
'../../../projects/streampipes/shared-ui/src/lib/dialog/data-download-dialog/model/format-export-config.model';
+import { GeneralUtils } from './GeneralUtils';
 
 export class DataDownloadDialogUtils {
     public static testDownload(
@@ -30,6 +31,7 @@ export class DataDownloadDialogUtils {
         // const exportDate: Date;
         DataLakeUtils.goToDatalake();
 
+        GeneralUtils.openMenuForRow(dataViewName);
         // select data view in edit mode
         DataLakeUtils.editDataView(dataViewName);
 
diff --git a/ui/cypress/support/utils/asset/AssetUtils.ts 
b/ui/cypress/support/utils/asset/AssetUtils.ts
index deb9f21095..3b10320edf 100644
--- a/ui/cypress/support/utils/asset/AssetUtils.ts
+++ b/ui/cypress/support/utils/asset/AssetUtils.ts
@@ -18,6 +18,7 @@
 
 import { AssetBtns } from './AssetBtns';
 import { ConnectUtils } from '../connect/ConnectUtils';
+import { GeneralUtils } from '../GeneralUtils';
 
 export class AssetUtils {
     public static goToAssets() {
@@ -59,6 +60,7 @@ export class AssetUtils {
     }
 
     public static editAsset(assetName: string) {
+        GeneralUtils.openMenuForRow(assetName);
         AssetBtns.editAssetBtn(assetName).click();
     }
 
@@ -84,6 +86,7 @@ export class AssetUtils {
     }
 
     public static deleteAsset(assetName: string) {
+        GeneralUtils.openMenuForRow(assetName);
         AssetBtns.deleteAssetBtn(assetName).click();
         cy.dataCy('confirm-delete').click();
     }
diff --git a/ui/cypress/support/utils/connect/ConnectBtns.ts 
b/ui/cypress/support/utils/connect/ConnectBtns.ts
index a6478b6af4..8ae843d54e 100644
--- a/ui/cypress/support/utils/connect/ConnectBtns.ts
+++ b/ui/cypress/support/utils/connect/ConnectBtns.ts
@@ -15,6 +15,8 @@
  *  limitations under the License.
  *
  */
+import { GeneralUtils } from '../GeneralUtils';
+
 export class ConnectBtns {
     public static detailsAdapter() {
         return cy.dataCy('details-adapter', { timeout: 10000 });
@@ -24,6 +26,10 @@ export class ConnectBtns {
         return cy.dataCy('delete-adapter', { timeout: 10000 });
     }
 
+    public static moreOptions() {
+        return cy.dataCy('more-options', { timeout: 10000 });
+    }
+
     public static editAdapter() {
         return cy.dataCy('edit-adapter');
     }
@@ -42,6 +48,10 @@ export class ConnectBtns {
         });
     }
 
+    public static openActionsMenu(adapterName: string) {
+        GeneralUtils.openMenuForRow(adapterName);
+    }
+
     public static refreshSchema() {
         return cy.dataCy('refresh-schema');
     }
diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts 
b/ui/cypress/support/utils/connect/ConnectUtils.ts
index 19e0f32874..a9c682a1eb 100644
--- a/ui/cypress/support/utils/connect/ConnectUtils.ts
+++ b/ui/cypress/support/utils/connect/ConnectUtils.ts
@@ -24,6 +24,7 @@ import { ConnectBtns } from './ConnectBtns';
 import { AdapterBuilder } from '../../builder/AdapterBuilder';
 import { UserUtils } from '../UserUtils';
 import { PipelineUtils } from '../pipeline/PipelineUtils';
+import { GeneralUtils } from '../GeneralUtils';
 
 export class ConnectUtils {
     public static testAdapter(
@@ -229,10 +230,11 @@ export class ConnectUtils {
         cy.get('button').contains('Close').parent().click();
     }
 
-    public static deleteAdapter() {
+    public static deleteAdapter(adapterName: string) {
         // Delete adapter
         this.goToConnect();
 
+        GeneralUtils.openMenuForRow(adapterName);
         cy.dataCy('delete-adapter').should('have.length', 1);
         this.clickDelete();
         cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should(
@@ -255,6 +257,7 @@ export class ConnectUtils {
     public static deleteAdapterAndAssociatedPipelines(switchUserCheck = false) 
{
         // Delete adapter and associated pipelines
         this.goToConnect();
+        ConnectBtns.openActionsMenu('simulator');
         cy.dataCy('delete-adapter').should('have.length', 1);
         this.clickDelete();
         cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', {
@@ -279,6 +282,7 @@ export class ConnectUtils {
     public static deleteAdapterAndAssociatedPipelinesPermissionDenied() {
         // Associated pipelines not owned by the user (unless admin) should 
not be deleted during adapter deletion
         this.goToConnect();
+        ConnectBtns.openActionsMenu('simulator');
         cy.dataCy('delete-adapter').should('have.length', 1);
         this.clickDelete();
         cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', {
@@ -363,12 +367,15 @@ export class ConnectUtils {
         return adapterConfiguration;
     }
 
-    public static startAndValidateAdapter(amountOfProperties: number) {
+    public static startAndValidateAdapter(
+        adapterName: string,
+        amountOfProperties: number,
+    ) {
         ConnectBtns.startAdapter().should('not.be.disabled');
 
         ConnectBtns.startAdapter().click();
 
-        ConnectUtils.validateEventsInPreview(amountOfProperties);
+        ConnectUtils.validateEventsInPreview(adapterName, amountOfProperties);
     }
 
     public static getLivePreviewValue(runtimeName: string) {
@@ -377,8 +384,12 @@ export class ConnectUtils {
         });
     }
 
-    public static validateEventsInPreview(amountOfProperties: number) {
+    public static validateEventsInPreview(
+        adapterName: string,
+        amountOfProperties: number,
+    ) {
         // View data
+        ConnectBtns.openActionsMenu(adapterName);
         ConnectBtns.detailsAdapter().click();
 
         // Validate resulting event
@@ -400,9 +411,14 @@ export class ConnectUtils {
      * Validates the event schema for an adapter by checking the amount of 
properties
      * and the runtime names of the event properties
      * @param runtimeNames runtime names of the event properties
+     * @param adapterName name of the adapter
      */
-    public static validateEventSchema(runtimeNames: string[]) {
+    public static validateEventSchema(
+        adapterName: string,
+        runtimeNames: string[],
+    ) {
         ConnectUtils.goToConnect();
+        GeneralUtils.openMenuForRow(adapterName);
         ConnectBtns.detailsAdapter().click();
 
         cy.get('tr.mat-mdc-row').should('have.length', runtimeNames.length);
@@ -459,7 +475,7 @@ export class ConnectUtils {
             cy.wait(1000);
             cy.dataCy('no-table-entries').should('be.visible');
         } else {
-            ConnectBtns.deleteAdapter().should('have.length', amount);
+            ConnectBtns.moreOptions().should('have.length', amount);
         }
     }
 }
diff --git a/ui/cypress/support/utils/datalake/DataLakeBtns.ts 
b/ui/cypress/support/utils/datalake/DataLakeBtns.ts
index 9f456e2f70..35b3ca1b66 100644
--- a/ui/cypress/support/utils/datalake/DataLakeBtns.ts
+++ b/ui/cypress/support/utils/datalake/DataLakeBtns.ts
@@ -16,6 +16,8 @@
  *
  */
 
+import { GeneralUtils } from '../GeneralUtils';
+
 export class DataLakeBtns {
     public static refreshDataLakeMeasures() {
         return cy.dataCy('refresh-data-lake-measures');
@@ -26,6 +28,9 @@ export class DataLakeBtns {
     }
 
     public static editDataViewButton(widgetName: string) {
-        return cy.dataCy('edit-data-view-' + widgetName).click();
+        GeneralUtils.openMenuForRow(widgetName);
+        return cy
+            .dataCy('edit-data-view-' + widgetName.replaceAll(' ', ''))
+            .click();
     }
 }
diff --git a/ui/cypress/support/utils/datalake/DataLakeUtils.ts 
b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
index 4b95327321..0aafa64f91 100644
--- a/ui/cypress/support/utils/datalake/DataLakeUtils.ts
+++ b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
@@ -182,6 +182,7 @@ export class DataLakeUtils {
     public static editDataView(dataViewName: string) {
         // Click edit button
         // following only works if single view is available
+        GeneralUtils.openMenuForRow(dataViewName);
         cy.dataCy('edit-data-view-' + dataViewName).click();
     }
 
@@ -208,6 +209,7 @@ export class DataLakeUtils {
     }
 
     public static deleteDataView(dataViewName: string) {
+        GeneralUtils.openMenuForRow(dataViewName);
         cy.dataCy('delete-data-view-' + dataViewName, {
             timeout: 10000,
         }).click();
@@ -223,6 +225,7 @@ export class DataLakeUtils {
     }
 
     public static cancelDeleteDataView(dataViewName: string) {
+        GeneralUtils.openMenuForRow(dataViewName);
         cy.dataCy('delete-data-view-' + dataViewName, {
             timeout: 10000,
         }).click();
diff --git a/ui/cypress/support/utils/pipeline/PipelineUtils.ts 
b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
index 783cb3d3dc..5af6c42d7a 100644
--- a/ui/cypress/support/utils/pipeline/PipelineUtils.ts
+++ b/ui/cypress/support/utils/pipeline/PipelineUtils.ts
@@ -24,6 +24,7 @@ import { PipelineBtns } from './PipelineBtns';
 import { ConnectUtils } from '../connect/ConnectUtils';
 import { PipelineBuilder } from '../../builder/PipelineBuilder';
 import { PipelineElementBuilder } from '../../builder/PipelineElementBuilder';
+import { GeneralUtils } from '../GeneralUtils';
 
 export class PipelineUtils {
     public static addPipeline(pipelineInput: PipelineInput) {
@@ -62,7 +63,8 @@ export class PipelineUtils {
         PipelineUtils.addPipeline(pipelineInput);
     }
 
-    public static editPipeline() {
+    public static editPipeline(pipelineName: string) {
+        GeneralUtils.openMenuForRow(pipelineName);
         cy.dataCy('modify-pipeline-btn').first().click();
     }
 
@@ -178,13 +180,15 @@ export class PipelineUtils {
         }
     }
 
-    public static deletePipeline() {
+    public static deletePipeline(pipelineName: string) {
         // Delete pipeline
         PipelineUtils.goToPipelines();
+        GeneralUtils.openMenuForRow(pipelineName);
         PipelineBtns.deletePipeline().should('have.length', 1);
         PipelineBtns.deletePipeline().click({ force: true });
 
         cy.dataCy('sp-pipeline-stop-and-delete').click();
+        cy.wait(2000);
 
         PipelineBtns.deletePipeline().should('have.length', 0);
     }
diff --git a/ui/cypress/support/utils/user/PermissionUtils.ts 
b/ui/cypress/support/utils/user/PermissionUtils.ts
index 9907c56acc..3242960d22 100644
--- a/ui/cypress/support/utils/user/PermissionUtils.ts
+++ b/ui/cypress/support/utils/user/PermissionUtils.ts
@@ -17,20 +17,22 @@
  */
 
 import { StaticPropertyUtils } from '../userInput/StaticPropertyUtils';
+import { GeneralUtils } from '../GeneralUtils';
 
 export class PermissionUtils {
-    public static openManagePermissions() {
+    public static openManagePermissions(resourceName: string) {
+        GeneralUtils.openMenuForRow(resourceName);
         cy.dataCy('open-manage-permissions').click();
     }
 
-    public static markElementAsPublic() {
-        PermissionUtils.openManagePermissions();
+    public static markElementAsPublic(resourceName: string) {
+        PermissionUtils.openManagePermissions(resourceName);
         StaticPropertyUtils.clickCheckbox('permission-public-element');
         PermissionUtils.save();
     }
 
-    public static authorizeUser(email: string) {
-        PermissionUtils.openManagePermissions();
+    public static authorizeUser(resourceName: string, email: string) {
+        PermissionUtils.openManagePermissions(resourceName);
 
         cy.dataCy('authorized-user').type(email);
         cy.get(`[data-cy="user-option-${email}"]`).click();
diff --git 
a/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts 
b/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts
index 4af2f359e2..e63f186c9e 100644
--- a/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts
+++ b/ui/cypress/tests/connect/compact/compactAdapterWithTransformation.spec.ts
@@ -19,6 +19,7 @@
 import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils';
 import { CompactAdapterUtils } from 
'../../../support/utils/connect/CompactAdapterUtils';
 import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+import { GeneralUtils } from '../../../support/utils/GeneralUtils';
 
 describe('Add Compact Adapters', () => {
     beforeEach('Setup Test', () => {
@@ -43,7 +44,7 @@ describe('Add Compact Adapters', () => {
                 'volume_flow',
             ];
 
-            ConnectUtils.validateEventSchema(runtimeNames);
+            ConnectUtils.validateEventSchema(compactAdapter.name, 
runtimeNames);
         });
     });
 
@@ -58,6 +59,7 @@ describe('Add Compact Adapters', () => {
 
         CompactAdapterUtils.storeCompactAdapter(compactAdapter).then(() => {
             ConnectUtils.goToConnect();
+            GeneralUtils.openMenuForRow(compactAdapter.name);
             ConnectBtns.detailsAdapter().click();
 
             // This assertion works because the original value is below 100
diff --git a/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts 
b/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts
index 719bb8c663..fb57cd2cd8 100644
--- a/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts
+++ b/ui/cypress/tests/connect/compact/uiConfiguration.spec.ts
@@ -42,6 +42,7 @@ describe('Test Compact Adapters', () => {
         ConnectUtils.startAdapter(adapterInput);
 
         // Validate code editor in adapter details
+        GeneralUtils.openMenuForRow(adapterInput.adapterName);
         ConnectBtns.detailsAdapter().click();
         GeneralUtils.tab('Code');
         validateCodeEditor();
diff --git a/ui/cypress/tests/connect/editAdapter.smoke.spec.ts 
b/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
index 7187510bc9..91c960c129 100644
--- a/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
+++ b/ui/cypress/tests/connect/editAdapter.smoke.spec.ts
@@ -40,6 +40,7 @@ describe('Test Edit Adapter', () => {
 
         // click edit adapter
         ConnectBtns.adapterOperationInProgressSpinner().should('not.exist');
+        ConnectBtns.openActionsMenu('simulator');
         ConnectBtns.editAdapter().should('not.be.disabled');
         ConnectBtns.editAdapter().click();
 
@@ -68,7 +69,7 @@ describe('Test Edit Adapter', () => {
 
         ConnectUtils.closeAdapterPreview();
 
-        ConnectUtils.startAndValidateAdapter(3);
+        ConnectUtils.startAndValidateAdapter('Edited Adapter', 3);
         ConnectUtils.goToConnect();
 
         // Validate that name of adapter and data stream
@@ -76,12 +77,13 @@ describe('Test Edit Adapter', () => {
     });
 
     it('Successfully edit adapter with persistence pipeline', () => {
-        ConnectUtils.addMachineDataSimulator('simulator', true, '100');
+        ConnectUtils.addMachineDataSimulator('simulator', true, '1000');
 
         ConnectUtils.goToConnect();
 
         // stop adapter and edit adapter
         ConnectBtns.stopAdapter().click();
+        ConnectBtns.openActionsMenu('simulator');
         ConnectBtns.editAdapter().click();
 
         // change data type of density to integer
@@ -91,6 +93,7 @@ describe('Test Edit Adapter', () => {
             'Integer',
             true,
         );
+        ConnectEventSchemaUtils.renameProperty('density', 'density2');
 
         ConnectUtils.storeAndStartEditedAdapter();
 
@@ -105,7 +108,7 @@ describe('Test Edit Adapter', () => {
             initialValue = value;
         });
 
-        cy.wait(5000);
+        cy.wait(3000);
 
         DataLakeBtns.refreshDataLakeMeasures().click();
 
diff --git 
a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.smoke.spec.ts 
b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.smoke.spec.ts
index 62b3f062f2..3b1e63e37c 100644
--- a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.smoke.spec.ts
+++ b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.smoke.spec.ts
@@ -24,6 +24,7 @@ import { PipelineBuilder } from 
'../../support/builder/PipelineBuilder';
 import { AdapterBuilder } from '../../support/builder/AdapterBuilder';
 import { DashboardUtils } from '../../support/utils/DashboardUtils';
 import { DataLakeUtils } from '../../support/utils/datalake/DataLakeUtils';
+import { GeneralUtils } from '../../support/utils/GeneralUtils';
 
 describe('Test Edit Adapter and Pipeline', () => {
     beforeEach('Setup Test', () => {
@@ -52,6 +53,7 @@ describe('Test Edit Adapter and Pipeline', () => {
     it('Edit adapter and test Pipeline behaviour', () => {
         // Edit Apater and select pressure
         ConnectUtils.goToConnect();
+        ConnectBtns.openActionsMenu('simulator');
         ConnectBtns.editAdapter().should('not.be.disabled');
         ConnectBtns.editAdapter().click();
         const newUserConfiguration = AdapterBuilder.create(
@@ -86,6 +88,7 @@ describe('Test Edit Adapter and Pipeline', () => {
             timeout: 60000,
         }).should('be.visible');
 
+        GeneralUtils.openMenuForRow('Pipeline Test');
         cy.dataCy('modify-pipeline-btn').click();
         cy.dataCy('settings-pipeline-element-button').eq(0).click();
         cy.dataCy('number-mapping').contains('pressure').click({ force: true 
});
diff --git 
a/ui/cypress/tests/connect/editAdapterTransformationRulesAreKept.spec.ts 
b/ui/cypress/tests/connect/editAdapterTransformationRulesAreKept.spec.ts
index 1885af9ea3..764f374b56 100644
--- a/ui/cypress/tests/connect/editAdapterTransformationRulesAreKept.spec.ts
+++ b/ui/cypress/tests/connect/editAdapterTransformationRulesAreKept.spec.ts
@@ -46,6 +46,7 @@ describe('Test Adapter Transformation Rules are properly 
stored', () => {
         ConnectUtils.closeAdapterPreview();
 
         // Edit adapter and check if given values and added property still 
provided
+        ConnectBtns.openActionsMenu('Test Adapter');
         ConnectBtns.editAdapter().should('not.be.disabled');
         ConnectBtns.editAdapter().click();
         cy.contains('Next').click();
diff --git a/ui/cypress/tests/connect/editAdapterValuesAndFields.spec.ts 
b/ui/cypress/tests/connect/editAdapterValuesAndFields.spec.ts
index 15cba76846..ff9cf46ba0 100644
--- a/ui/cypress/tests/connect/editAdapterValuesAndFields.spec.ts
+++ b/ui/cypress/tests/connect/editAdapterValuesAndFields.spec.ts
@@ -70,6 +70,7 @@ describe('Test Edit Adapter', () => {
         ConnectUtils.closeAdapterPreview();
 
         // Edit adapter and check if given values and added property still 
provided
+        ConnectBtns.openActionsMenu('Test Adapter');
         ConnectBtns.editAdapter().should('not.be.disabled');
         ConnectBtns.editAdapter().click();
         cy.contains('Next').click();
@@ -106,6 +107,7 @@ describe('Test Edit Adapter', () => {
         ConnectUtils.closeAdapterPreview();
 
         // Configure adapter with pressure instead of flowrate
+        ConnectBtns.openActionsMenu('Test Adapter');
         ConnectBtns.editAdapter().click();
         const newUserConfiguration = AdapterBuilder.create(
             'Machine_Data_Simulator',
diff --git a/ui/cypress/tests/connect/fileStream.spec.ts 
b/ui/cypress/tests/connect/fileStream.spec.ts
index 16050b097f..c25286db8a 100644
--- a/ui/cypress/tests/connect/fileStream.spec.ts
+++ b/ui/cypress/tests/connect/fileStream.spec.ts
@@ -21,6 +21,7 @@ import { FileManagementUtils } from 
'../../support/utils/FileManagementUtils';
 import { AdapterBuilder } from '../../support/builder/AdapterBuilder';
 import { ConnectBtns } from '../../support/utils/connect/ConnectBtns';
 import { ConnectEventSchemaUtils } from 
'../../support/utils/connect/ConnectEventSchemaUtils';
+import { GeneralUtils } from '../../support/utils/GeneralUtils';
 
 describe(
     'Test File Replay Adapter',
@@ -47,7 +48,7 @@ describe(
                 .build();
 
             ConnectUtils.testAdapter(adapterInput);
-            ConnectUtils.deleteAdapter();
+            ConnectUtils.deleteAdapter(adapterInput.adapterName);
         });
 
         it('File stream adapter should not allow add timestamp option in 
schema editor', () => {
@@ -124,6 +125,7 @@ describe(
             ConnectUtils.testAdapter(adapterInput);
 
             // click on edit adapter
+            GeneralUtils.openMenuForRow(adapterInput.adapterName);
             ConnectBtns.editAdapter().click();
 
             // validate that the file name is set as default
diff --git a/ui/cypress/tests/connect/machineDataSimulator.smoke.spec.ts 
b/ui/cypress/tests/connect/machineDataSimulator.smoke.spec.ts
index 3875d5bb14..2f26342c5f 100644
--- a/ui/cypress/tests/connect/machineDataSimulator.smoke.spec.ts
+++ b/ui/cypress/tests/connect/machineDataSimulator.smoke.spec.ts
@@ -31,6 +31,6 @@ describe('Test Machine Data Simulator Adapter', () => {
             .build();
 
         ConnectUtils.testAdapter(adapterInput);
-        ConnectUtils.deleteAdapter();
+        ConnectUtils.deleteAdapter(adapterInput.adapterName);
     });
 });
diff --git 
a/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.smoke.spec.ts 
b/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.smoke.spec.ts
index 6e387b8958..c613a89194 100644
--- a/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.smoke.spec.ts
+++ b/ui/cypress/tests/connect/opcua/startAndEditOpcAdapters.smoke.spec.ts
@@ -23,6 +23,7 @@ import { TreeStaticPropertyUtils } from 
'../../../support/utils/userInput/TreeSt
 import { ConnectEventSchemaUtils } from 
'../../../support/utils/connect/ConnectEventSchemaUtils';
 import { AdapterInput } from '../../../support/model/AdapterInput';
 import { OpcUaUtils } from '../../../support/utils/connect/OpcUaUtils';
+import { GeneralUtils } from '../../../support/utils/GeneralUtils';
 
 describe('Test starting and editing OPC-UA Adapters in different 
configurations', () => {
     beforeEach('Setup Test', () => {
@@ -66,7 +67,7 @@ describe('Test starting and editing OPC-UA Adapters in 
different configurations'
  */
 const startAdapterTest = (adapterInput: AdapterInput) => {
     ConnectUtils.testAdapter(adapterInput);
-    ConnectUtils.validateEventsInPreview(5);
+    ConnectUtils.validateEventsInPreview(adapterInput.adapterName, 5);
 };
 
 /**
@@ -76,6 +77,7 @@ const startAdapterTest = (adapterInput: AdapterInput) => {
 const editAdapterTest = (adapterInput: AdapterInput) => {
     ConnectUtils.testAdapter(adapterInput);
 
+    GeneralUtils.openMenuForRow(adapterInput.adapterName);
     ConnectBtns.editAdapter().click();
 
     // Validate that browse nodes are shown
@@ -87,7 +89,7 @@ const editAdapterTest = (adapterInput: AdapterInput) => {
     ConnectEventSchemaUtils.finishEventSchemaConfiguration();
     ConnectBtns.storeEditAdapter().click();
     ConnectUtils.closeAdapterPreview();
-    ConnectUtils.validateEventsInPreview(4);
+    ConnectUtils.validateEventsInPreview(adapterInput.adapterName, 4);
 };
 
 const getAdapterBuilderWithTextNodes = (pullMode: boolean) => {
diff --git a/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts 
b/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts
index 0745e6e247..f4962830bd 100644
--- a/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts
+++ b/ui/cypress/tests/connect/rules/addNumericalStaticValue.spec.ts
@@ -21,6 +21,7 @@ import { FileManagementUtils } from 
'../../../support/utils/FileManagementUtils'
 import { ConnectEventSchemaUtils } from 
'../../../support/utils/connect/ConnectEventSchemaUtils';
 import { DataLakeUtils } from '../../../support/utils/datalake/DataLakeUtils';
 import { ConnectBtns } from '../../../support/utils/connect/ConnectBtns';
+import { GeneralUtils } from '../../../support/utils/GeneralUtils';
 
 describe('Connect schema rule transformations', () => {
     beforeEach('Setup Test', () => {
@@ -61,6 +62,7 @@ describe('Connect schema rule transformations', () => {
         );
 
         ConnectUtils.goToConnect();
+        GeneralUtils.openMenuForRow(adapterConfiguration.adapterName);
         ConnectBtns.editAdapter().click();
         // This waiting time is required to ensure that the file is loaded 
correctly before the next button is clicked
         cy.wait(1000);
diff --git a/ui/cypress/tests/datalake/configuration.smoke.spec.ts 
b/ui/cypress/tests/datalake/configuration.smoke.spec.ts
index 1b095ab07e..a8fd3129a6 100644
--- a/ui/cypress/tests/datalake/configuration.smoke.spec.ts
+++ b/ui/cypress/tests/datalake/configuration.smoke.spec.ts
@@ -53,7 +53,7 @@ describe('Delete data in datalake', () => {
     before('Setup Test', () => {
         cy.initStreamPipesTest();
         DataLakeUtils.loadRandomDataSetIntoDataLake();
-        PipelineUtils.deletePipeline();
+        PipelineUtils.deletePipeline('Persist prepared_data');
     });
 
     it('Perform Test', () => {
diff --git a/ui/cypress/tests/datalake/timeOrderDataView.spec.ts 
b/ui/cypress/tests/datalake/timeOrderDataView.spec.ts
index 28ec6d97ef..2144304754 100644
--- a/ui/cypress/tests/datalake/timeOrderDataView.spec.ts
+++ b/ui/cypress/tests/datalake/timeOrderDataView.spec.ts
@@ -53,7 +53,7 @@ describe('Test Time Order in Data Explorer', () => {
 
         // Save and leave view, edit view again and check ascending order
         DataLakeBtns.saveDataViewButton();
-        DataLakeBtns.editDataViewButton('Newchart');
+        DataLakeBtns.editDataViewButton('New chart');
         DataLakeUtils.clickOrderBy('ascending');
         DataLakeUtils.openVisualizationConfig();
         DataLakeUtils.selectVisualizationType(DataExplorerWidget.TABLE);
diff --git a/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts 
b/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
index f17be7abc5..965f3dc5ac 100644
--- a/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
+++ b/ui/cypress/tests/pipeline/pipelineTest.smoke.spec.ts
@@ -25,6 +25,6 @@ describe('Test Random Data Simulator Stream Adapter', () => {
 
     it('Perform Test', () => {
         PipelineUtils.addSampleAdapterAndPipeline();
-        PipelineUtils.deletePipeline();
+        PipelineUtils.deletePipeline(`Pipeline Test`);
     });
 });
diff --git a/ui/cypress/tests/pipeline/renamePipelineTest.spec.ts 
b/ui/cypress/tests/pipeline/renamePipelineTest.spec.ts
index ea7c1e44af..46de0f3d66 100644
--- a/ui/cypress/tests/pipeline/renamePipelineTest.spec.ts
+++ b/ui/cypress/tests/pipeline/renamePipelineTest.spec.ts
@@ -29,7 +29,7 @@ describe('Test rename of running pipeline', () => {
         PipelineUtils.verifyPipelineCount(1);
         PipelineUtils.verifyPipelineName('Pipeline Test');
 
-        PipelineUtils.editPipeline();
+        PipelineUtils.editPipeline('Pipeline Test');
         cy.wait(1000);
         cy.dataCy('sp-editor-save-pipeline').click();
         cy.dataCy('sp-editor-pipeline-name').clear();
@@ -39,7 +39,7 @@ describe('Test rename of running pipeline', () => {
         PipelineUtils.verifyPipelineCount(1);
         PipelineUtils.verifyPipelineName('Renamed Pipeline');
 
-        PipelineUtils.editPipeline();
+        PipelineUtils.editPipeline('Renamed Pipeline');
         cy.dataCy('sp-editor-save-pipeline').click();
         cy.dataCy('sp-editor-pipeline-name').clear();
         PipelineUtils.clonePipeline('Cloned Renamed Pipeline');
diff --git a/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts 
b/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
index f1ff02d0c9..66df6816b8 100644
--- a/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
+++ b/ui/cypress/tests/pipeline/updatePipelineTest.smoke.spec.ts
@@ -24,23 +24,18 @@ describe('Test update of running pipeline', () => {
     });
 
     it('Perform Test', () => {
+        const pipelineName = 'Pipeline Test';
         PipelineUtils.addSampleAdapterAndPipeline();
-        PipelineUtils.editPipeline();
+        PipelineUtils.editPipeline(pipelineName);
         cy.wait(1000);
         PipelineUtils.startPipeline();
-        cy.dataCy('modify-pipeline-btn', { timeout: 10000 }).should(
-            'have.length',
-            1,
-        );
+        cy.dataCy('more-options', { timeout: 10000 }).should('have.length', 1);
 
-        PipelineUtils.editPipeline();
+        PipelineUtils.editPipeline(pipelineName);
         cy.wait(1000);
         cy.dataCy('sp-editor-save-pipeline').click();
         PipelineUtils.clonePipeline('Pipeline Test 2');
         PipelineUtils.finalizePipelineStart();
-        cy.dataCy('modify-pipeline-btn', { timeout: 10000 }).should(
-            'have.length',
-            2,
-        );
+        cy.dataCy('more-options', { timeout: 10000 }).should('have.length', 2);
     });
 });
diff --git a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts 
b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
index 03bb86b08c..d136a0b47c 100644
--- a/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
+++ b/ui/cypress/tests/userManagement/testGroupManagement.spec.ts
@@ -97,7 +97,7 @@ describe('Test Group Management for Pipelines', () => {
 
         // Add user group to pipeline
         PipelineUtils.goToPipelines();
-        PermissionUtils.openManagePermissions();
+        PermissionUtils.openManagePermissions('Pipeline Test');
         ConfigurationBtns.authorizedGroupsLabel().click();
         cy.get('mat-option').contains('User_Group').click();
         PermissionUtils.save();
diff --git a/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts 
b/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
index 584e7eed96..a517d854d1 100644
--- a/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRoleConnect.spec.ts
@@ -42,7 +42,7 @@ describe('Test User Roles for Connect', () => {
 
     it('Connect admin should see public adapters of other users', () => {
         // Set adapter to public
-        PermissionUtils.markElementAsPublic();
+        PermissionUtils.markElementAsPublic('simulator');
 
         switchUserAndValidateConnectModuleIsShown();
 
@@ -52,7 +52,7 @@ describe('Test User Roles for Connect', () => {
 
     it('Connect admin should see shared adapters of other users', () => {
         // Share adapter with user
-        PermissionUtils.authorizeUser(connectAdminUser.email);
+        PermissionUtils.authorizeUser('simulator', connectAdminUser.email);
 
         switchUserAndValidateConnectModuleIsShown();
 
diff --git a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts 
b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
index 0a67894ca3..67024c4ee4 100644
--- a/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
+++ b/ui/cypress/tests/userManagement/testUserRolePipeline.spec.ts
@@ -57,7 +57,7 @@ describe('Test User Roles for Pipelines', () => {
 
         // Add new authorized user to pipeline
         PipelineUtils.goToPipelines();
-        PermissionUtils.markElementAsPublic();
+        PermissionUtils.markElementAsPublic('Persist simulator');
 
         // Login as user and check if pipeline is visible to user
         UserUtils.switchUser(newUser);
@@ -74,8 +74,8 @@ describe('Test User Roles for Pipelines', () => {
 
         // Add new authorized user to pipeline
         PipelineUtils.goToPipelines();
-        PermissionUtils.markElementAsPublic();
-        PermissionUtils.authorizeUser(newUser.email);
+        PermissionUtils.markElementAsPublic('Persist simulator');
+        PermissionUtils.authorizeUser('Persist simulator', newUser.email);
 
         // Login as user and check if pipeline is visible to user
         UserUtils.switchUser(newUser);
@@ -93,7 +93,7 @@ describe('Test User Roles for Pipelines', () => {
         // Add new authorized user to pipeline
         PipelineUtils.goToPipelines();
         // PermissionUtils.markElementAsPublic();
-        PermissionUtils.authorizeUser(newUser.email);
+        PermissionUtils.authorizeUser('Persist simulator', newUser.email);
 
         // Login as user and check if pipeline is visible to user
         UserUtils.switchUser(newUser);
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.html
 
b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.html
index 5f7ad2cabd..045643415b 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.html
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.html
@@ -22,48 +22,40 @@
 
         @if (showActionsMenu) {
             <ng-container matColumnDef="actions">
-                <th
-                    fxFlex
-                    fxLayoutAlign="center center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                ></th>
-                <td
-                    fxFlex
-                    fxLayoutAlign="end center"
-                    mat-cell
-                    *matCellDef="let element"
-                >
-                    <div
-                        [matMenuTriggerFor]="menu"
-                        #menuTrigger="matMenuTrigger"
-                        (mouseenter)="mouseEnter(menuTrigger)"
-                        (mouseleave)="mouseLeave(menuTrigger)"
-                    >
-                        <button
-                            mat-icon-button
+                <th mat-header-cell *matHeaderCellDef></th>
+                <td mat-cell *matCellDef="let element">
+                    <div fxLayoutAlign="end center">
+                        <div
                             [matMenuTriggerFor]="menu"
                             #menuTrigger="matMenuTrigger"
-                            (click)="$event.stopPropagation()"
-                            [attr.data-cy]="'more-options'"
-                        >
-                            <mat-icon>more_vert</mat-icon>
-                        </button>
-                    </div>
-                    <mat-menu #menu="matMenu" [hasBackdrop]="false">
-                        <div
                             (mouseenter)="mouseEnter(menuTrigger)"
                             (mouseleave)="mouseLeave(menuTrigger)"
                         >
-                            <ng-container
-                                *ngTemplateOutlet="
-                                    actionsTemplate;
-                                    context: { $implicit: element }
-                                "
+                            <button
+                                mat-icon-button
+                                [matMenuTriggerFor]="menu"
+                                #menuTrigger="matMenuTrigger"
+                                (click)="$event.stopPropagation()"
+                                [attr.data-cy]="'more-options'"
                             >
-                            </ng-container>
+                                <mat-icon>more_vert</mat-icon>
+                            </button>
                         </div>
-                    </mat-menu>
+                        <mat-menu #menu="matMenu" [hasBackdrop]="false">
+                            <div
+                                (mouseenter)="mouseEnter(menuTrigger)"
+                                (mouseleave)="mouseLeave(menuTrigger)"
+                            >
+                                <ng-container
+                                    *ngTemplateOutlet="
+                                        actionsTemplate;
+                                        context: { $implicit: element }
+                                    "
+                                >
+                                </ng-container>
+                            </div>
+                        </mat-menu>
+                    </div>
                 </td>
             </ng-container>
         }
diff --git 
a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.scss
 
b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.scss
index bd8eea251f..4d0b280941 100644
--- 
a/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.scss
+++ 
b/ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.scss
@@ -32,3 +32,8 @@
 .cursor-pointer {
     cursor: pointer;
 }
+
+.right-column {
+    text-align: right; /* align contents inside cell */
+    margin-left: auto; /* push this column to the far right */
+}
diff --git a/ui/src/app/assets/assets.module.ts 
b/ui/src/app/assets/assets.module.ts
index 831273a1b9..3af98418a0 100644
--- a/ui/src/app/assets/assets.module.ts
+++ b/ui/src/app/assets/assets.module.ts
@@ -62,6 +62,8 @@ import { ViewAssetLabelsComponent } from 
'./components/asset-details/view-asset/
 import { ViewAssetBasicsComponent } from 
'./components/asset-details/view-asset/view-asset-basics/view-assset-basics.component';
 import { ViewAssetLinksComponent } from 
'./components/asset-details/view-asset/view-asset-links/view-asset-links.component';
 import { AssetLinkCardComponent } from 
'./components/asset-details/view-asset/view-asset-links/asset-link-card/asset-link-card.component';
+import { MatMenuItem } from '@angular/material/menu';
+import { TranslatePipe } from '@ngx-translate/core';
 
 @NgModule({
     imports: [
@@ -116,6 +118,8 @@ import { AssetLinkCardComponent } from 
'./components/asset-details/view-asset/vi
         SharedUiModule,
         MatTreeModule,
         MatSortModule,
+        MatMenuItem,
+        TranslatePipe,
     ],
     declarations: [
         AssetDetailsBasicsComponent,
diff --git 
a/ui/src/app/assets/components/asset-overview/asset-overview.component.html 
b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
index 98849fb525..6b7f059dd4 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.html
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
@@ -55,6 +55,9 @@
                     fxFlex="100"
                     [columns]="displayedColumns"
                     [dataSource]="dataSource"
+                    [showActionsMenu]="true"
+                    [rowsClickable]="true"
+                    (rowClicked)="goToDetailsView($event)"
                     matSort
                 >
                     <ng-container matColumnDef="name">
@@ -83,55 +86,36 @@
                             </div>
                         </td>
                     </ng-container>
-                    <ng-container matColumnDef="action">
-                        <th
-                            mat-header-cell
-                            *matHeaderCellDef
-                            style="justify-content: center"
-                        ></th>
-                        <td mat-cell *matCellDef="let asset">
-                            <div fxLayout="row" fxLayoutAlign="end center">
-                                <button
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Show info"
-                                    matTooltipPosition="above"
-                                    (click)="goToDetailsView(asset)"
-                                >
-                                    <i class="material-icons">search</i>
-                                </button>
-                                <button
-                                    *ngIf="hasWritePrivilege"
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Edit asset"
-                                    matTooltipPosition="above"
-                                    data-cy="edit-asset-button"
-                                    [attr.data-cy]="
-                                        'edit-asset-' + asset.assetName
-                                    "
-                                    (click)="goToDetailsView(asset, true)"
-                                >
-                                    <i class="material-icons">edit</i>
-                                </button>
+                    <ng-template spTableActions let-element>
+                        <button
+                            mat-menu-item
+                            (click)="goToDetailsView(element)"
+                        >
+                            <mat-icon>search</mat-icon>
+                            <span>{{ 'Show' | translate }}</span>
+                        </button>
+                        <button
+                            *ngIf="hasWritePrivilege"
+                            mat-menu-item
+                            data-cy="edit-asset-button"
+                            [attr.data-cy]="'edit-asset-' + element.assetName"
+                            (click)="goToDetailsView(element, true)"
+                        >
+                            <mat-icon>edit</mat-icon>
+                            <span>{{ 'Edit' | translate }}</span>
+                        </button>
 
-                                <button
-                                    *ngIf="hasWritePrivilege"
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Delete asset"
-                                    data-cy="delete"
-                                    matTooltipPosition="above"
-                                    [attr.data-cy]="
-                                        'delete-asset-' + asset.assetName
-                                    "
-                                    (click)="deleteAsset(asset)"
-                                >
-                                    <i class="material-icons">delete</i>
-                                </button>
-                            </div>
-                        </td>
-                    </ng-container>
+                        <button
+                            *ngIf="hasWritePrivilege"
+                            mat-menu-item
+                            data-cy="delete"
+                            [attr.data-cy]="'delete-asset-' + 
element.assetName"
+                            (click)="deleteAsset(element)"
+                        >
+                            <mat-icon>delete</mat-icon>
+                            <span>{{ 'Delete' | translate }}</span>
+                        </button>
+                    </ng-template>
                 </sp-table>
             </div>
         </div>
diff --git 
a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts 
b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
index f7421f59f0..38fcfd5593 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -47,7 +47,7 @@ import { MatDialog } from '@angular/material/dialog';
 export class SpAssetOverviewComponent implements OnInit {
     existingAssets: SpAssetModel[] = [];
 
-    displayedColumns: string[] = ['name', 'action'];
+    displayedColumns: string[] = ['name', 'actions'];
 
     dataSource: MatTableDataSource<SpAssetModel> =
         new MatTableDataSource<SpAssetModel>();
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 3f441fe4ef..abd0e5d7be 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
@@ -36,7 +36,9 @@
                 data-cy="connect-create-new-adapter-button"
                 (click)="createNewAdapter()"
             >
-                <i class="material-icons">add</i>&nbsp;New adapter
+                <i class="material-icons">add</i>&nbsp;{{
+                    'New adapter' | translate
+                }}
             </button>
             <button
                 mat-flat-button
@@ -46,7 +48,7 @@
                 (click)="startAllAdapters(true)"
             >
                 <mat-icon>play_arrow</mat-icon>
-                <span>Start all adapters</span>
+                <span>{{ 'Start all adapters' | translate }}</span>
             </button>
             <button
                 mat-flat-button
@@ -56,7 +58,7 @@
                 (click)="startAllAdapters(false)"
             >
                 <mat-icon>stop</mat-icon>
-                <span>Stop all adapters</span>
+                <span>{{ 'Stop all adapters' | translate }}</span>
             </button>
             <div fxFlex fxLayout="row" fxLayoutAlign="end center">
                 <sp-connect-filter-toolbar
@@ -101,12 +103,15 @@
                     fxFlex="100"
                     [columns]="displayedColumns"
                     [dataSource]="dataSource"
+                    [showActionsMenu]="true"
+                    [rowsClickable]="true"
+                    (rowClicked)="navigateToDetailsOverviewPage($event)"
                     data-cy="all-adapters-table"
                     matSort
                 >
                     <ng-container matColumnDef="status">
                         <th mat-header-cell mat-sort-header *matHeaderCellDef>
-                            Status
+                            {{ 'Status' | translate }}
                         </th>
                         <td mat-cell *matCellDef="let adapter">
                             <sp-adapter-status-light
@@ -141,7 +146,10 @@
                                     matTooltip="Start adapter"
                                     matTooltipPosition="above"
                                     data-cy="start-adapter"
-                                    (click)="startAdapter(adapter)"
+                                    (click)="
+                                        startAdapter(adapter);
+                                        $event.stopPropagation()
+                                    "
                                 >
                                     <i class="material-icons">play_arrow</i>
                                 </button>
@@ -152,7 +160,10 @@
                                     matTooltip="Stop adapter"
                                     matTooltipPosition="above"
                                     data-cy="stop-adapter"
-                                    (click)="stopAdapter(adapter)"
+                                    (click)="
+                                        stopAdapter(adapter);
+                                        $event.stopPropagation()
+                                    "
                                 >
                                     <i class="material-icons">stop</i>
                                 </button>
@@ -162,13 +173,15 @@
 
                     <ng-container matColumnDef="name">
                         <th mat-header-cell mat-sort-header *matHeaderCellDef>
-                            Name
+                            {{ 'Name' | translate }}
                         </th>
                         <td mat-cell *matCellDef="let adapter">
-                            <div>
+                            <div
+                                fxLayout="column"
+                                fxLayoutAlign="start start"
+                                class="truncate"
+                            >
                                 <b data-cy="adapter-name">{{ adapter.name 
}}</b>
-                            </div>
-                            <div>
                                 <small> {{ adapter.description }}</small>
                             </div>
                         </td>
@@ -191,7 +204,9 @@
                         </td>
                     </ng-container>
                     <ng-container matColumnDef="lastModified">
-                        <th mat-header-cell *matHeaderCellDef>Created</th>
+                        <th mat-header-cell *matHeaderCellDef>
+                            {{ 'Created' | translate }}
+                        </th>
                         <td mat-cell *matCellDef="let adapter">
                             <h5>
                                 {{
@@ -207,7 +222,7 @@
                             *matHeaderCellDef
                             matTooltip="Messages sent since last start"
                         >
-                            #Messages
+                            #{{ 'Messages' | translate }}
                         </th>
                         <td mat-cell *matCellDef="let adapter">
                             <sp-label
@@ -221,7 +236,9 @@
                     </ng-container>
 
                     <ng-container matColumnDef="lastMessage">
-                        <th mat-header-cell *matHeaderCellDef>Last message</th>
+                        <th mat-header-cell *matHeaderCellDef>
+                            {{ 'Last message' | translate }}
+                        </th>
                         <td mat-cell *matCellDef="let adapter">
                             <h5>
                                 {{
@@ -237,57 +254,93 @@
                         </td>
                     </ng-container>
 
-                    <ng-container matColumnDef="action">
-                        <th mat-header-cell *matHeaderCellDef></th>
-                        <td mat-cell *matCellDef="let adapter">
-                            <div fxLayout="row" fxLayoutAlign="end center">
-                                <button
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Show details"
-                                    matTooltipPosition="above"
-                                    data-cy="details-adapter"
-                                    (click)="
-                                        navigateToDetailsOverviewPage(adapter)
-                                    "
-                                >
-                                    <i class="material-icons">search</i>
-                                </button>
+                    <ng-template spTableActions let-element>
+                        <button
+                            mat-menu-item
+                            data-cy="details-adapter"
+                            (click)="navigateToDetailsOverviewPage(element)"
+                        >
+                            <mat-icon>search</mat-icon>
+                            <span>{{ 'Show' | translate }}</span>
+                        </button>
+                        <button
+                            mat-menu-item
+                            data-cy="edit-adapter"
+                            (click)="editAdapter(element)"
+                        >
+                            <mat-icon>edit</mat-icon>
+                            <span>{{ 'Edit' | translate }}</span>
+                        </button>
+                        <button
+                            mat-menu-item
+                            data-cy="open-manage-permissions"
+                            *ngIf="isAdmin"
+                            (click)="showPermissionsDialog(element)"
+                        >
+                            <mat-icon>share</mat-icon>
+                            <span>{{ 'Manage permissions' | translate }}</span>
+                        </button>
+                        <button
+                            mat-menu-item
+                            data-cy="delete-adapter"
+                            (click)="deleteAdapter(element)"
+                        >
+                            <mat-icon>delete</mat-icon>
+                            <span>{{ 'Delete' | translate }}</span>
+                        </button>
+                    </ng-template>
 
-                                <button
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Edit adapter"
-                                    data-cy="edit-adapter"
-                                    matTooltipPosition="above"
-                                    (click)="editAdapter(adapter)"
-                                >
-                                    <i class="material-icons">edit</i>
-                                </button>
-                                <button
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Manage permissions"
-                                    matTooltipPosition="above"
-                                    data-cy="open-manage-permissions"
-                                    *ngIf="isAdmin"
-                                    (click)="showPermissionsDialog(adapter)"
-                                >
-                                    <i class="material-icons">share</i>
-                                </button>
-                                <button
-                                    color="accent"
-                                    mat-icon-button
-                                    matTooltip="Delete adapter"
-                                    data-cy="delete-adapter"
-                                    matTooltipPosition="above"
-                                    (click)="deleteAdapter(adapter)"
-                                >
-                                    <i class="material-icons">delete</i>
-                                </button>
-                            </div>
-                        </td>
-                    </ng-container>
+                    <!--                    <ng-container 
matColumnDef="action">-->
+                    <!--                        <th mat-header-cell 
*matHeaderCellDef></th>-->
+                    <!--                        <td mat-cell *matCellDef="let 
adapter">-->
+                    <!--                            <div fxLayout="row" 
fxLayoutAlign="end center">-->
+                    <!--                                <button-->
+                    <!--                                    color="accent"-->
+                    <!--                                    mat-icon-button-->
+                    <!--                                    matTooltip="Show 
details"-->
+                    <!--                                    
matTooltipPosition="above"-->
+                    <!--                                    
data-cy="details-adapter"-->
+                    <!--                                    (click)="-->
+                    <!--                                        
navigateToDetailsOverviewPage(adapter)-->
+                    <!--                                    "-->
+                    <!--                                >-->
+                    <!--                                    <i 
class="material-icons">search</i>-->
+                    <!--                                </button>-->
+
+                    <!--                                <button-->
+                    <!--                                    color="accent"-->
+                    <!--                                    mat-icon-button-->
+                    <!--                                    matTooltip="Edit 
adapter"-->
+                    <!--                                    
data-cy="edit-adapter"-->
+                    <!--                                    
matTooltipPosition="above"-->
+                    <!--                                    
(click)="editAdapter(adapter)"-->
+                    <!--                                >-->
+                    <!--                                    <i 
class="material-icons">edit</i>-->
+                    <!--                                </button>-->
+                    <!--                                <button-->
+                    <!--                                    color="accent"-->
+                    <!--                                    mat-icon-button-->
+                    <!--                                    matTooltip="Manage 
permissions"-->
+                    <!--                                    
matTooltipPosition="above"-->
+                    <!--                                    
data-cy="open-manage-permissions"-->
+                    <!--                                    *ngIf="isAdmin"-->
+                    <!--                                    
(click)="showPermissionsDialog(adapter)"-->
+                    <!--                                >-->
+                    <!--                                    <i 
class="material-icons">share</i>-->
+                    <!--                                </button>-->
+                    <!--                                <button-->
+                    <!--                                    color="accent"-->
+                    <!--                                    mat-icon-button-->
+                    <!--                                    matTooltip="Delete 
adapter"-->
+                    <!--                                    
data-cy="delete-adapter"-->
+                    <!--                                    
matTooltipPosition="above"-->
+                    <!--                                    
(click)="deleteAdapter(adapter)"-->
+                    <!--                                >-->
+                    <!--                                    <i 
class="material-icons">delete</i>-->
+                    <!--                                </button>-->
+                    <!--                            </div>-->
+                    <!--                        </td>-->
+                    <!--                    </ng-container>-->
                 </sp-table>
             </div>
         </div>
diff --git 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
index 52a48bdf92..f47cad0e28 100644
--- 
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
+++ 
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.scss
@@ -23,7 +23,7 @@
 .adapter-icon {
     padding-top: 5px;
     padding-bottom: 5px;
-    max-height: 40px;
+    max-height: 35px;
 }
 
 .real-time {
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 34cc2adb65..1ca9ff7d61 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
@@ -70,7 +70,7 @@ export class ExistingAdaptersComponent implements OnInit, 
OnDestroy {
         'lastModified',
         'messagesSent',
         'lastMessage',
-        'action',
+        'actions',
     ];
 
     dataSource: MatTableDataSource<AdapterDescription> =
diff --git a/ui/src/app/connect/connect.module.ts 
b/ui/src/app/connect/connect.module.ts
index d6b5701047..a0cdb02303 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -108,6 +108,8 @@ import { AdapterCodePanelComponent } from 
'./components/adapter-code-panel/adapt
 import { AdapterDetailsCodeComponent } from 
'./components/adapter-details/adapter-details-code/adapter-details-code.component';
 import { MatTreeModule } from '@angular/material/tree';
 import { TranslateModule } from '@ngx-translate/core';
+import { TranslatePipe } from '@ngx-translate/core';
+
 @NgModule({
     imports: [
         MatTreeModule,
@@ -199,6 +201,7 @@ import { TranslateModule } from '@ngx-translate/core';
             },
         ]),
         SharedUiModule,
+        TranslatePipe,
     ],
     exports: [ErrorMessageComponent],
     declarations: [
diff --git 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
index 72f7db226d..2814907bd6 100644
--- 
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
+++ 
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
@@ -30,21 +30,13 @@
             (rowClicked)="onRowClicked($event)"
         >
             <ng-container matColumnDef="name">
-                <th
-                    fxFlex="40"
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Dashboards' | translate }}
                 </th>
                 <td
-                    fxFlex="40"
-                    fxLayoutAlign="center start"
                     mat-cell
                     data-cy="dashboard-table-overview"
                     *matCellDef="let element"
-                    fxLayout="column"
                 >
                     <div>
                         <b>{{ element.name }}</b>
@@ -56,19 +48,10 @@
             </ng-container>
 
             <ng-container matColumnDef="lastModified">
-                <th
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Last modified' | translate }}
                 </th>
-                <td
-                    fxLayoutAlign="center start"
-                    mat-cell
-                    *matCellDef="let element"
-                    fxLayout="column"
-                >
+                <td mat-cell *matCellDef="let element">
                     <div *ngIf="element.metadata">
                         {{
                             this.formatDate(
@@ -81,19 +64,10 @@
             </ng-container>
 
             <ng-container matColumnDef="createdAt">
-                <th
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Created' | translate }}
                 </th>
-                <td
-                    fxLayoutAlign="center start"
-                    mat-cell
-                    *matCellDef="let element"
-                    fxLayout="column"
-                >
+                <td mat-cell *matCellDef="let element">
                     <div *ngIf="element.metadata">
                         {{ this.formatDate(element.metadata.createdAtEpochMs) 
}}
                     </div>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
index 6857516236..49dfcc98ab 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.html
@@ -25,19 +25,15 @@
             fxFlex="100"
             [columns]="displayedColumns"
             [dataSource]="dataSource"
+            [showActionsMenu]="true"
+            [rowsClickable]="true"
+            (rowClicked)="openDataView($event, true)"
         >
             <ng-container matColumnDef="name">
-                <th
-                    fxFlex="60"
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Chart' | translate }}
                 </th>
                 <td
-                    fxFlex="60"
-                    fxLayoutAlign="start center"
                     mat-cell
                     data-cy="data-views-table-overview"
                     *matCellDef="let element"
@@ -47,21 +43,10 @@
             </ng-container>
 
             <ng-container matColumnDef="lastModified">
-                <th
-                    fxFlex="60"
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Last modified' | translate }}
                 </th>
-                <td
-                    fxFlex="60"
-                    fxLayoutAlign="center start"
-                    mat-cell
-                    *matCellDef="let element"
-                    fxLayout="column"
-                >
+                <td mat-cell *matCellDef="let element">
                     <div *ngIf="element.metadata">
                         {{
                             this.formatDate(
@@ -74,21 +59,10 @@
             </ng-container>
 
             <ng-container matColumnDef="createdAt">
-                <th
-                    fxFlex="60"
-                    fxLayoutAlign="start center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                >
+                <th mat-header-cell *matHeaderCellDef>
                     {{ 'Created' | translate }}
                 </th>
-                <td
-                    fxFlex="60"
-                    fxLayoutAlign="center start"
-                    mat-cell
-                    *matCellDef="let element"
-                    fxLayout="column"
-                >
+                <td mat-cell *matCellDef="let element">
                     <div *ngIf="element.metadata">
                         {{ this.formatDate(element.metadata.createdAtEpochMs) 
}}
                     </div>
@@ -96,78 +70,56 @@
                 </td>
             </ng-container>
 
-            <ng-container matColumnDef="actions">
-                <th
-                    fxFlex="40"
-                    fxLayoutAlign="center center"
-                    mat-header-cell
-                    *matHeaderCellDef
-                ></th>
-                <td
-                    fxFlex="40"
-                    fxLayoutAlign="start center"
-                    mat-cell
-                    *matCellDef="let element"
+            <ng-template spTableActions let-element>
+                <button mat-menu-item (click)="openDataView(element, false)">
+                    <mat-icon>visibility</mat-icon>
+                    <span>{{ 'Show' | translate }}</span>
+                </button>
+                <button
+                    mat-menu-item
+                    *ngIf="hasDataExplorerWritePrivileges"
+                    [attr.data-cy]="
+                        'edit-data-view-' +
+                        element.baseAppearanceConfig.widgetTitle.replaceAll(
+                            ' ',
+                            ''
+                        )
+                    "
+                    (click)="openDataView(element, true)"
                 >
-                    <div fxLayout="row" fxFlex="100" fxLayoutAlign="end 
center">
-                        <button
-                            mat-icon-button
-                            color="accent"
-                            [matTooltip]="'Show chart' | translate"
-                            (click)="openDataView(element, false)"
-                        >
-                            <i class="material-icons">visibility</i>
-                        </button>
-                        <button
-                            mat-icon-button
-                            color="accent"
-                            [matTooltip]="'Edit chart' | translate"
-                            *ngIf="hasDataExplorerWritePrivileges"
-                            [attr.data-cy]="
-                                'edit-data-view-' +
-                                
element.baseAppearanceConfig.widgetTitle.replaceAll(
-                                    ' ',
-                                    ''
-                                )
-                            "
-                            (click)="openDataView(element, true)"
-                        >
-                            <i class="material-icons">edit</i>
-                        </button>
-                        <button
-                            mat-icon-button
-                            color="accent"
-                            [matTooltip]="'Manage permissions' | translate"
-                            *ngIf="isAdmin"
-                            (click)="showPermissionsDialog(element)"
-                        >
-                            <i class="material-icons">share</i>
-                        </button>
-                        <button
-                            mat-icon-button
-                            color="accent"
-                            [matTooltip]="'Clone chart' | translate"
-                            *ngIf="hasDataExplorerWritePrivileges"
-                            (click)="cloneDataView(element)"
-                        >
-                            <i class="material-icons">flip_to_front</i>
-                        </button>
-                        <button
-                            mat-icon-button
-                            color="accent"
-                            [matTooltip]="'Delete chart' | translate"
-                            *ngIf="hasDataExplorerWritePrivileges"
-                            [attr.data-cy]="
-                                'delete-data-view-' +
-                                element.baseAppearanceConfig.widgetTitle
-                            "
-                            (click)="deleteDataView(element)"
-                        >
-                            <i class="material-icons">delete</i>
-                        </button>
-                    </div>
-                </td>
-            </ng-container>
+                    <mat-icon>edit</mat-icon>
+                    <span>{{ 'Edit chart' | translate }}</span>
+                </button>
+                <button
+                    mat-menu-item
+                    *ngIf="isAdmin"
+                    (click)="showPermissionsDialog(element)"
+                >
+                    <mat-icon>share</mat-icon>
+                    <span>{{ 'Manage permissions' | translate }}</span>
+                </button>
+                <button
+                    mat-menu-item
+                    *ngIf="hasDataExplorerWritePrivileges"
+                    (click)="cloneDataView(element)"
+                >
+                    <mat-icon>flip_to_front</mat-icon>
+                    <span>{{ 'Clone chart' | translate }}</span>
+                </button>
+                <button
+                    mat-menu-item
+                    [matTooltip]=""
+                    *ngIf="hasDataExplorerWritePrivileges"
+                    [attr.data-cy]="
+                        'delete-data-view-' +
+                        element.baseAppearanceConfig.widgetTitle
+                    "
+                    (click)="deleteDataView(element)"
+                >
+                    <mat-icon>delete</mat-icon>
+                    <span>{{ 'Delete chart' | translate }}</span>
+                </button>
+            </ng-template>
         </sp-table>
     </div>
 </div>
diff --git 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
index 9af05bbb05..b8137d0644 100644
--- 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
+++ 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
@@ -19,6 +19,11 @@
 <sp-table
     [dataSource]="dataSource"
     [columns]="displayedColumns"
+    [showActionsMenu]="true"
+    [rowsClickable]="true"
+    (rowClicked)="
+        pipelineOperationsService.showPipelineDetails($event.elementId)
+    "
     matSort
     data-cy="all-pipelines-table"
 >
@@ -58,7 +63,10 @@
                             class="ml-10"
                             mat-icon-button
                             [disabled]="!hasPipelineWritePrivileges"
-                            (click)="openPipelineNotificationsDialog(pipeline)"
+                            (click)="
+                                openPipelineNotificationsDialog(pipeline);
+                                $event.stopPropagation()
+                            "
                             *ngIf="pipeline.pipelineNotifications.length > 0"
                             matTooltip="{{
                                 pipeline.pipelineNotifications.length
@@ -95,44 +103,50 @@
     <ng-container matColumnDef="start">
         <th mat-header-cell *matHeaderCellDef>{{ 'Start' | translate }}</th>
         <td mat-cell *matCellDef="let pipeline">
-            <button
-                color="accent"
-                mat-icon-button
-                [matTooltip]="'Start pipeline' | translate"
-                matTooltipPosition="above"
-                data-cy="start-pipeline-button"
-                (click)="
-                    pipelineOperationsService.startPipeline(
-                        pipeline._id,
-                        refreshPipelinesEmitter,
-                        toggleRunningOperation
-                    )
-                "
-                [disabled]="
-                    !hasPipelineWritePrivileges || starting || !pipeline.valid
-                "
-                *ngIf="!pipeline.running"
-            >
-                <i class="material-icons">play_arrow</i>
-            </button>
-            <button
-                color="accent"
-                mat-icon-button
-                [matTooltip]="'Stop pipeline' | translate"
-                matTooltipPosition="above"
-                data-cy="stop-pipeline-button"
-                (click)="
-                    pipelineOperationsService.stopPipeline(
-                        pipeline._id,
-                        refreshPipelinesEmitter,
-                        toggleRunningOperation
-                    )
-                "
-                [disabled]="!hasPipelineWritePrivileges || stopping"
-                *ngIf="pipeline.running"
-            >
-                <i class="material-icons">stop</i>
-            </button>
+            <div fxLayoutAlign="start start">
+                <button
+                    color="accent"
+                    mat-icon-button
+                    [matTooltip]="'Start pipeline' | translate"
+                    matTooltipPosition="above"
+                    data-cy="start-pipeline-button"
+                    (click)="
+                        pipelineOperationsService.startPipeline(
+                            pipeline._id,
+                            refreshPipelinesEmitter,
+                            toggleRunningOperation
+                        );
+                        $event.stopPropagation()
+                    "
+                    [disabled]="
+                        !hasPipelineWritePrivileges ||
+                        starting ||
+                        !pipeline.valid
+                    "
+                    *ngIf="!pipeline.running"
+                >
+                    <i class="material-icons">play_arrow</i>
+                </button>
+                <button
+                    color="accent"
+                    mat-icon-button
+                    [matTooltip]="'Stop pipeline' | translate"
+                    matTooltipPosition="above"
+                    data-cy="stop-pipeline-button"
+                    (click)="
+                        pipelineOperationsService.stopPipeline(
+                            pipeline._id,
+                            refreshPipelinesEmitter,
+                            toggleRunningOperation
+                        );
+                        $event.stopPropagation()
+                    "
+                    [disabled]="!hasPipelineWritePrivileges || stopping"
+                    *ngIf="pipeline.running"
+                >
+                    <i class="material-icons">stop</i>
+                </button>
+            </div>
         </td>
     </ng-container>
 
@@ -140,11 +154,9 @@
         <th mat-header-cell mat-sort-header *matHeaderCellDef>
             {{ 'Name' | translate }}
         </th>
-        <td mat-cell *matCellDef="let pipeline">
-            <div>
+        <td mat-cell *matCellDef="let pipeline" class="truncate">
+            <div fxLayout="column" fxLayoutAlign="start start">
                 <b>{{ pipeline.name }}</b>
-            </div>
-            <div>
                 <small> {{ pipeline.description }}</small>
             </div>
         </td>
@@ -159,68 +171,115 @@
         </td>
     </ng-container>
 
-    <ng-container matColumnDef="action">
-        <th mat-header-cell *matHeaderCellDef></th>
-        <td mat-cell *matCellDef="let pipeline">
-            <div fxLayout="row" fxLayoutAlign="end center">
-                <button
-                    mat-icon-button
-                    [matTooltip]="'Show pipeline' | translate"
-                    matTooltipPosition="above"
-                    (click)="
-                        pipelineOperationsService.showPipelineDetails(
-                            pipeline._id
-                        )
-                    "
-                >
-                    <i class="material-icons">search</i>
-                </button>
-                <button
-                    color="accent"
-                    mat-icon-button
-                    [matTooltip]="'Modify pipeline' | translate"
-                    matTooltipPosition="above"
-                    *ngIf="hasPipelineWritePrivileges"
-                    (click)="
-                        pipelineOperationsService.modifyPipeline(pipeline._id)
-                    "
-                    data-cy="modify-pipeline-btn"
-                >
-                    <i class="material-icons">mode_edit</i>
-                </button>
-                <button
-                    color="accent"
-                    mat-icon-button
-                    [matTooltip]="'Permissions' | translate"
-                    matTooltipPosition="above"
-                    *ngIf="isAdmin"
-                    (click)="
-                        pipelineOperationsService.showPermissionsDialog(
-                            pipeline,
-                            refreshPipelinesEmitter
-                        )
-                    "
-                    data-cy="open-manage-permissions"
-                >
-                    <i class="material-icons">share</i>
-                </button>
-                <button
-                    color="accent"
-                    mat-icon-button
-                    [matTooltip]="'Delete pipeline' | translate"
-                    matTooltipPosition="above"
-                    *ngIf="hasPipelineWritePrivileges"
-                    (click)="
-                        pipelineOperationsService.showDeleteDialog(
-                            pipeline,
-                            refreshPipelinesEmitter
-                        )
-                    "
-                    data-cy="delete-pipeline"
-                >
-                    <i class="material-icons">delete</i>
-                </button>
-            </div>
-        </td>
-    </ng-container>
+    <ng-template spTableActions let-element>
+        <button
+            mat-menu-item
+            
(click)="pipelineOperationsService.showPipelineDetails(element._id)"
+        >
+            <mat-icon>search</mat-icon>
+            <span>{{ 'Show' | translate }}</span>
+        </button>
+        <button
+            mat-menu-item
+            *ngIf="hasPipelineWritePrivileges"
+            (click)="pipelineOperationsService.modifyPipeline(element._id)"
+            data-cy="modify-pipeline-btn"
+        >
+            <mat-icon>mode_edit</mat-icon>
+            <span>{{ 'Edit' | translate }}</span>
+        </button>
+        <button
+            mat-menu-item
+            *ngIf="isAdmin"
+            (click)="
+                pipelineOperationsService.showPermissionsDialog(
+                    element,
+                    refreshPipelinesEmitter
+                )
+            "
+            data-cy="open-manage-permissions"
+        >
+            <mat-icon>share</mat-icon>
+            <span>{{ 'Manage permissions' | translate }}</span>
+        </button>
+        <button
+            mat-menu-item
+            *ngIf="hasPipelineWritePrivileges"
+            (click)="
+                pipelineOperationsService.showDeleteDialog(
+                    element,
+                    refreshPipelinesEmitter
+                )
+            "
+            data-cy="delete-pipeline"
+        >
+            <mat-icon>delete</mat-icon>
+            <span>{{ 'Delete' | translate }}</span>
+        </button>
+    </ng-template>
+
+    <!--    <ng-container matColumnDef="action">-->
+    <!--        <th mat-header-cell *matHeaderCellDef></th>-->
+    <!--        <td mat-cell *matCellDef="let pipeline">-->
+    <!--            <div fxLayout="row" fxLayoutAlign="end center">-->
+    <!--                <button-->
+    <!--                    mat-icon-button-->
+    <!--                    [matTooltip]="'Show pipeline' | translate"-->
+    <!--                    matTooltipPosition="above"-->
+    <!--                    (click)="-->
+    <!--                        
pipelineOperationsService.showPipelineDetails(-->
+    <!--                            pipeline._id-->
+    <!--                        )-->
+    <!--                    "-->
+    <!--                >-->
+    <!--                    <i class="material-icons">search</i>-->
+    <!--                </button>-->
+    <!--                <button-->
+    <!--                    color="accent"-->
+    <!--                    mat-icon-button-->
+    <!--                    [matTooltip]="'Modify pipeline' | translate"-->
+    <!--                    matTooltipPosition="above"-->
+    <!--                    *ngIf="hasPipelineWritePrivileges"-->
+    <!--                    (click)="-->
+    <!--                        
pipelineOperationsService.modifyPipeline(pipeline._id)-->
+    <!--                    "-->
+    <!--                    data-cy="modify-pipeline-btn"-->
+    <!--                >-->
+    <!--                    <i class="material-icons">mode_edit</i>-->
+    <!--                </button>-->
+    <!--                <button-->
+    <!--                    color="accent"-->
+    <!--                    mat-icon-button-->
+    <!--                    [matTooltip]="'Permissions' | translate"-->
+    <!--                    matTooltipPosition="above"-->
+    <!--                    *ngIf="isAdmin"-->
+    <!--                    (click)="-->
+    <!--                        
pipelineOperationsService.showPermissionsDialog(-->
+    <!--                            pipeline,-->
+    <!--                            refreshPipelinesEmitter-->
+    <!--                        )-->
+    <!--                    "-->
+    <!--                    data-cy="open-manage-permissions"-->
+    <!--                >-->
+    <!--                    <i class="material-icons">share</i>-->
+    <!--                </button>-->
+    <!--                <button-->
+    <!--                    color="accent"-->
+    <!--                    mat-icon-button-->
+    <!--                    [matTooltip]="'Delete pipeline' | translate"-->
+    <!--                    matTooltipPosition="above"-->
+    <!--                    *ngIf="hasPipelineWritePrivileges"-->
+    <!--                    (click)="-->
+    <!--                        pipelineOperationsService.showDeleteDialog(-->
+    <!--                            pipeline,-->
+    <!--                            refreshPipelinesEmitter-->
+    <!--                        )-->
+    <!--                    "-->
+    <!--                    data-cy="delete-pipeline"-->
+    <!--                >-->
+    <!--                    <i class="material-icons">delete</i>-->
+    <!--                </button>-->
+    <!--            </div>-->
+    <!--        </td>-->
+    <!--    </ng-container>-->
 </sp-table>
diff --git 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
index d99c1019ed..aadc7548eb 100644
--- 
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
+++ 
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.ts
@@ -53,7 +53,7 @@ export class PipelineOverviewComponent implements OnInit, 
OnDestroy {
         'start',
         'name',
         'lastModified',
-        'action',
+        'actions',
     ];
 
     dataSource: MatTableDataSource<Pipeline>;
diff --git a/ui/src/app/pipelines/pipelines.module.ts 
b/ui/src/app/pipelines/pipelines.module.ts
index 6a5fc3223b..c3e263a273 100644
--- a/ui/src/app/pipelines/pipelines.module.ts
+++ b/ui/src/app/pipelines/pipelines.module.ts
@@ -48,6 +48,7 @@ import { MatDividerModule } from '@angular/material/divider';
 import { MatCheckboxModule } from '@angular/material/checkbox';
 import { MatIconModule } from '@angular/material/icon';
 import { TranslateModule } from '@ngx-translate/core';
+import { MatMenuItem } from '@angular/material/menu';
 
 @NgModule({
     imports: [
@@ -100,6 +101,7 @@ import { TranslateModule } from '@ngx-translate/core';
                 ],
             },
         ]),
+        MatMenuItem,
     ],
     declarations: [
         DeletePipelineDialogComponent,
diff --git a/ui/src/scss/sp/main.scss b/ui/src/scss/sp/main.scss
index 652fc08018..474e00fce5 100644
--- a/ui/src/scss/sp/main.scss
+++ b/ui/src/scss/sp/main.scss
@@ -19,6 +19,12 @@
 @use './variables' as spThemeVars;
 @use '../custom-theme/custom-variables' as customThemeVars;
 
+.truncate {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
 md-progress-linear.md-accent .md-container {
     background-color: rgb(168, 168, 168);
 }


Reply via email to