Skip to content

Commit d7c6273

Browse files
feat(#3810): Support cloning of dashboards (#3811)
Co-authored-by: Philipp Zehnder <tenthe@users.noreply.github.com>
1 parent faac0ed commit d7c6273

File tree

28 files changed

+596
-184
lines changed

28 files changed

+596
-184
lines changed

streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardModel.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class DashboardModel implements Storable, SpResource {
4545
private String name;
4646
private String description;
4747
private boolean displayHeader;
48+
private int gridColumns = 8;
4849

4950
private Map<String, Object> dashboardTimeSettings;
5051
private Map<String, Object> dashboardGeneralSettings;
@@ -148,6 +149,10 @@ public void setDashboardLiveSettings(Map<String, Object> dashboardLiveSettings)
148149
this.dashboardLiveSettings = dashboardLiveSettings;
149150
}
150151

152+
public int getGridColumns() {
153+
return gridColumns;
154+
}
155+
151156
@Override
152157
public ResourceMetadata getMetadata() {
153158
return metadata;

ui/cypress/support/utils/GeneralUtils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,20 @@ export class GeneralUtils {
2020
public static tab(identifier: string) {
2121
return cy.dataCy(`tab-${identifier}`).click();
2222
}
23+
24+
public static openMenuForRow(rowText: string) {
25+
cy.contains('[role="row"], tr, mat-row', rowText) // be flexible on row element
26+
.scrollIntoView()
27+
.within(() => {
28+
// Hover the trigger to open the menu
29+
cy.dataCy('more-options').trigger('mouseenter', {
30+
force: true,
31+
});
32+
});
33+
34+
// Wait for the CDK overlay panel to become visible
35+
cy.get('.cdk-overlay-container .mat-mdc-menu-panel:visible').should(
36+
'exist',
37+
);
38+
}
2339
}

ui/cypress/support/utils/datalake/DataLakeUtils.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ConnectUtils } from '../connect/ConnectUtils';
2525
import { ConnectBtns } from '../connect/ConnectBtns';
2626
import { AdapterBuilder } from '../../builder/AdapterBuilder';
2727
import { differenceInMonths } from 'date-fns';
28+
import { GeneralUtils } from '../GeneralUtils';
2829

2930
export class DataLakeUtils {
3031
public static goToDatalake() {
@@ -174,8 +175,7 @@ export class DataLakeUtils {
174175
}
175176

176177
public static editDashboard(dashboardName: string) {
177-
// Click edit button
178-
// following only works if single view is available
178+
GeneralUtils.openMenuForRow(dashboardName);
179179
cy.dataCy('edit-dashboard-' + dashboardName).click();
180180
}
181181

@@ -200,6 +200,7 @@ export class DataLakeUtils {
200200
}
201201

202202
public static deleteDashboard(dashboardName: string) {
203+
GeneralUtils.openMenuForRow(dashboardName);
203204
cy.dataCy('delete-dashboard-' + dashboardName, {
204205
timeout: 10000,
205206
}).click();
@@ -214,6 +215,7 @@ export class DataLakeUtils {
214215
}
215216

216217
public static cancelDeleteDashboard(dashboardName: string) {
218+
GeneralUtils.openMenuForRow(dashboardName);
217219
cy.dataCy('delete-dashboard-' + dashboardName, {
218220
timeout: 10000,
219221
}).click();
@@ -364,7 +366,7 @@ export class DataLakeUtils {
364366
.click();
365367
}
366368

367-
public static clickOrderBy(order: String) {
369+
public static clickOrderBy(order: string) {
368370
if (order == 'ascending') {
369371
cy.dataCy('ascending-radio-button').click();
370372
} else {

ui/projects/streampipes/platform-services/src/lib/model/dashboard/dashboard.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface Dashboard {
5252
dashboardLiveSettings: DashboardLiveSettings;
5353
elementId?: string;
5454
metadata: ResourceMetadata;
55+
gridColumns: number;
5556
rev?: string;
5657
}
5758

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
import { Directive } from '@angular/core';
20+
@Directive({ selector: 'ng-template[spTableActions]', standalone: false })
21+
export class SpTableActionsDirective {}

ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.html

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,61 @@
2020
<table mat-table class="sp-table" [dataSource]="dataSource">
2121
<ng-content></ng-content>
2222

23+
@if (showActionsMenu) {
24+
<ng-container matColumnDef="actions">
25+
<th
26+
fxFlex
27+
fxLayoutAlign="center center"
28+
mat-header-cell
29+
*matHeaderCellDef
30+
></th>
31+
<td
32+
fxFlex
33+
fxLayoutAlign="end center"
34+
mat-cell
35+
*matCellDef="let element"
36+
>
37+
<div
38+
[matMenuTriggerFor]="menu"
39+
#menuTrigger="matMenuTrigger"
40+
(mouseenter)="mouseEnter(menuTrigger)"
41+
(mouseleave)="mouseLeave(menuTrigger)"
42+
>
43+
<button
44+
mat-icon-button
45+
[matMenuTriggerFor]="menu"
46+
#menuTrigger="matMenuTrigger"
47+
(click)="$event.stopPropagation()"
48+
[attr.data-cy]="'more-options'"
49+
>
50+
<mat-icon>more_vert</mat-icon>
51+
</button>
52+
</div>
53+
<mat-menu #menu="matMenu" [hasBackdrop]="false">
54+
<div
55+
(mouseenter)="mouseEnter(menuTrigger)"
56+
(mouseleave)="mouseLeave(menuTrigger)"
57+
>
58+
<ng-container
59+
*ngTemplateOutlet="
60+
actionsTemplate;
61+
context: { $implicit: element }
62+
"
63+
>
64+
</ng-container>
65+
</div>
66+
</mat-menu>
67+
</td>
68+
</ng-container>
69+
}
70+
2371
<tr mat-header-row *matHeaderRowDef="columns"></tr>
24-
<tr mat-row *matRowDef="let row; columns: columns"></tr>
72+
<tr
73+
mat-row
74+
*matRowDef="let row; columns: columns"
75+
(click)="rowClicked.emit(row)"
76+
[ngClass]="rowsClickable ? 'cursor-pointer' : ''"
77+
></tr>
2578

2679
<tr class="mat-row" *matNoDataRow>
2780
<td

ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@
2828
height: var(--mat-table-row-item-container-height, 52px);
2929
text-align: center;
3030
}
31+
32+
.cursor-pointer {
33+
cursor: pointer;
34+
}

ui/projects/streampipes/shared-ui/src/lib/components/sp-table/sp-table.component.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ import {
2222
Component,
2323
ContentChild,
2424
ContentChildren,
25+
EventEmitter,
2526
Input,
27+
Output,
2628
QueryList,
29+
TemplateRef,
2730
ViewChild,
2831
} from '@angular/core';
2932
import {
@@ -35,6 +38,8 @@ import {
3538
MatTableDataSource,
3639
} from '@angular/material/table';
3740
import { MatPaginator } from '@angular/material/paginator';
41+
import { SpTableActionsDirective } from './sp-table-actions.directive';
42+
import { MatMenuTrigger } from '@angular/material/menu';
3843

3944
@Component({
4045
selector: 'sp-table',
@@ -51,12 +56,20 @@ export class SpTableComponent<T> implements AfterViewInit, AfterContentInit {
5156
@ViewChild(MatTable, { static: true }) table: MatTable<T>;
5257

5358
@Input() columns: string[];
59+
@Input() rowsClickable = false;
60+
@Input() showActionsMenu = false;
5461

5562
@Input() dataSource: MatTableDataSource<T>;
5663

64+
@Output() rowClicked = new EventEmitter<T>();
65+
5766
@ViewChild('paginator') paginator: MatPaginator;
67+
@ContentChild(SpTableActionsDirective, { read: TemplateRef })
68+
actionsTemplate?: TemplateRef<any>;
5869

5970
pageSize = 1;
71+
timedOutCloser: any;
72+
trigger: MatMenuTrigger | undefined = undefined;
6073

6174
ngAfterViewInit() {
6275
this.dataSource.paginator = this.paginator;
@@ -72,4 +85,22 @@ export class SpTableComponent<T> implements AfterViewInit, AfterContentInit {
7285
);
7386
this.table.setNoDataRow(this.noDataRow);
7487
}
88+
89+
mouseEnter(trigger) {
90+
if (this.timedOutCloser) {
91+
clearTimeout(this.timedOutCloser);
92+
}
93+
if (this.trigger !== undefined) {
94+
this.trigger.closeMenu();
95+
}
96+
trigger.openMenu();
97+
this.trigger = trigger;
98+
}
99+
100+
mouseLeave(trigger) {
101+
this.timedOutCloser = setTimeout(() => {
102+
trigger.closeMenu();
103+
this.trigger = undefined;
104+
}, 50);
105+
}
75106
}

ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { InputSchemaPropertyComponent } from './components/input-schema-panel/in
9898
import { MatExpansionModule } from '@angular/material/expansion';
9999
import { SortByRuntimeNamePipe } from './pipes/sort-by-runtime-name.pipe';
100100
import { DragDropModule } from '@angular/cdk/drag-drop';
101+
import { SpTableActionsDirective } from './components/sp-table/sp-table-actions.directive';
101102

102103
@NgModule({
103104
declarations: [
@@ -149,6 +150,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
149150
InputSchemaPanelComponent,
150151
InputSchemaPropertyComponent,
151152
SortByRuntimeNamePipe,
153+
SpTableActionsDirective,
152154
],
153155
imports: [
154156
CommonModule,
@@ -216,6 +218,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
216218
PipelineElementComponent,
217219
InputSchemaPanelComponent,
218220
SidebarResizeComponent,
221+
SpTableActionsDirective,
219222
],
220223
})
221224
export class SharedUiModule {}

ui/projects/streampipes/shared-ui/src/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export * from './lib/components/sp-exception-message/exception-details-dialog/ex
4242
export * from './lib/components/sp-exception-message/exception-details/exception-details.component';
4343
export * from './lib/components/sp-label/sp-label.component';
4444
export * from './lib/components/sp-table/sp-table.component';
45+
export * from './lib/components/sp-table/sp-table-actions.directive';
4546
export * from './lib/components/warning-box/warning-box.component';
4647
export * from './lib/components/time-selector/time-selector.model';
4748
export * from './lib/components/time-selector/time-range-selector.component';

0 commit comments

Comments
 (0)