diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts index 5d5015a4a9..45da2d56a8 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -501,6 +501,28 @@ export class DashboardUtilsService { this.removeUnusedWidgets(dashboard); } + public isReferenceWidget(dashboard: Dashboard, widgetId: string): boolean { + const states = dashboard.configuration.states; + let foundWidgetRefs = 0; + + for (const state of Object.values(states)) { + for (const layout of Object.values(state.layouts)) { + if (layout.widgets[widgetId]) { + foundWidgetRefs++; + } + if (layout.breakpoints) { + for (const breakpoint of Object.values(layout.breakpoints)) { + if (breakpoint.widgets[widgetId]) { + foundWidgetRefs++; + } + } + } + } + } + + return foundWidgetRefs > 1; + } + public getRootStateId(states: {[id: string]: DashboardState }): string { for (const stateId of Object.keys(states)) { const state = states[stateId]; diff --git a/ui-ngx/src/app/core/services/item-buffer.service.ts b/ui-ngx/src/app/core/services/item-buffer.service.ts index b523ea0828..8e80ce1d25 100644 --- a/ui-ngx/src/app/core/services/item-buffer.service.ts +++ b/ui-ngx/src/app/core/services/item-buffer.service.ts @@ -177,7 +177,9 @@ export class ItemBufferService { } public pasteWidget(targetDashboard: Dashboard, targetState: string, - targetLayout: DashboardLayoutId, position: WidgetPosition, + targetLayout: DashboardLayoutId, + breakpoint: string, + position: WidgetPosition, onAliasesUpdateFunction: () => void, onFiltersUpdateFunction: () => void): Observable { const widgetItem: WidgetItem = this.storeGet(WIDGET_ITEM); @@ -197,7 +199,7 @@ export class ItemBufferService { return this.addWidgetToDashboard(targetDashboard, targetState, targetLayout, widget, aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, - originalColumns, originalSize, targetRow, targetColumn).pipe( + originalColumns, originalSize, targetRow, targetColumn, breakpoint).pipe( map(() => widget) ); } else { @@ -205,8 +207,11 @@ export class ItemBufferService { } } - public pasteWidgetReference(targetDashboard: Dashboard, targetState: string, - targetLayout: DashboardLayoutId, position: WidgetPosition): Observable { + public pasteWidgetReference(targetDashboard: Dashboard, + targetState: string, + targetLayout: DashboardLayoutId, + breakpoint: string, + position: WidgetPosition): Observable { const widgetReference: WidgetReference = this.storeGet(WIDGET_REFERENCE); if (widgetReference) { const widget = targetDashboard.configuration.widgets[widgetReference.widgetId]; @@ -222,7 +227,7 @@ export class ItemBufferService { return this.addWidgetToDashboard(targetDashboard, targetState, targetLayout, widget, null, null, null, null, originalColumns, - originalSize, targetRow, targetColumn).pipe( + originalSize, targetRow, targetColumn, breakpoint).pipe( map(() => widget) ); } else { @@ -242,7 +247,8 @@ export class ItemBufferService { originalColumns: number, originalSize: WidgetSize, row: number, - column: number): Observable { + column: number, + breakpoint = 'default'): Observable { let theDashboard: Dashboard; if (dashboard) { theDashboard = dashboard; @@ -273,7 +279,7 @@ export class ItemBufferService { } } this.dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget, - originalColumns, originalSize, row, column); + originalColumns, originalSize, row, column, breakpoint); if (callAliasUpdateFunction) { onAliasesUpdateFunction(); } @@ -406,8 +412,7 @@ export class ItemBufferService { } } - if (gridSettings && - gridSettings.columns) { + if (gridSettings && gridSettings.columns) { originalColumns = gridSettings.columns; } originalColumns = originalColumns * layoutCount; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 9cd3ae5655..139fa424a3 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -1374,6 +1374,33 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } } + copyEditWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget) { + $event.stopPropagation(); + + const widgetItem = deepClone(this.itembuffer.prepareWidgetItem(this.dashboard, this.dashboardCtx.state, + layoutCtx.id, widget, layoutCtx.breakpoint)); + + const targetRow = layoutCtx.widgetLayouts[widget.id].row; + const targetColumn = layoutCtx.widgetLayouts[widget.id].col; + + if (layoutCtx.widgets.removeWidgetId(widget.id)) { + this.dashboardUtils.removeWidgetFromLayout(this.dashboard, this.dashboardCtx.state, layoutCtx.id, + widget.id, layoutCtx.breakpoint); + } + + widgetItem.widget.id = this.utils.guid(); + + this.itembuffer.addWidgetToDashboard(this.dashboard, this.dashboardCtx.state, layoutCtx.id, widgetItem.widget, + widgetItem.aliasesInfo, widgetItem.filtersInfo, + this.entityAliasesUpdated.bind(this), this.filtersUpdated.bind(this), + widgetItem.originalColumns, widgetItem.originalSize, targetRow, targetColumn, layoutCtx.breakpoint + ).subscribe(() => { + layoutCtx.widgets.addWidgetId(widgetItem.widget.id); + this.runChangeDetection(); + this.editWidget($event,layoutCtx, widgetItem.widget); + }); + } + copyWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget) { this.itembuffer.copyWidget(this.dashboard, this.dashboardCtx.state, layoutCtx.id, widget, layoutCtx.breakpoint); @@ -1385,7 +1412,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } pasteWidget($event: Event, layoutCtx: DashboardPageLayoutContext, pos: WidgetPosition) { - this.itembuffer.pasteWidget(this.dashboard, this.dashboardCtx.state, layoutCtx.id, + this.itembuffer.pasteWidget(this.dashboard, this.dashboardCtx.state, layoutCtx.id, layoutCtx.breakpoint, pos, this.entityAliasesUpdated.bind(this), this.filtersUpdated.bind(this)).subscribe( (widget) => { layoutCtx.widgets.addWidgetId(widget.id); @@ -1394,7 +1421,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } pasteWidgetReference($event: Event, layoutCtx: DashboardPageLayoutContext, pos: WidgetPosition) { - this.itembuffer.pasteWidgetReference(this.dashboard, this.dashboardCtx.state, layoutCtx.id, + this.itembuffer.pasteWidgetReference(this.dashboard, this.dashboardCtx.state, layoutCtx.id, layoutCtx.breakpoint, pos).subscribe( (widget) => { layoutCtx.widgets.addWidgetId(widget.id); diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts index 7f4fbd26a9..fd4891b960 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts @@ -56,6 +56,7 @@ export interface IDashboardController { openDashboardState(stateId: string, openRightLayout: boolean); addWidget($event: Event, layoutCtx: DashboardPageLayoutContext); editWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); + copyEditWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); exportWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget, widgetTitle: string); removeWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); widgetMouseDown($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts index 05c7869f55..5c8ce30037 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/dashboard-layout.component.ts @@ -231,6 +231,10 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo this.layoutCtx.dashboardCtrl.editWidget($event, this.layoutCtx, widget); } + onCopyEditWidget($event: Event, widget: Widget): void { + this.layoutCtx.dashboardCtrl.copyEditWidget($event, this.layoutCtx, widget); + } + onExportWidget($event: Event, widget: Widget, widgetTitle: string): void { this.layoutCtx.dashboardCtrl.exportWidget($event, this.layoutCtx, widget, widgetTitle); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts index ce968d0e47..fb47e49af8 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts @@ -401,6 +401,9 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo case WidgetComponentActionType.EDIT: this.editWidget($event, widget); break; + case WidgetComponentActionType.COPY_EDIT: + this.editCopyWidget($event, widget); + break; case WidgetComponentActionType.EXPORT: this.exportWidget($event, widget); break; @@ -431,6 +434,15 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo } } + private editCopyWidget($event: Event, widget: DashboardWidget) { + if ($event) { + $event.stopPropagation(); + } + if (this.isEditActionEnabled && this.callbacks && this.callbacks.onCopyEditWidget) { + this.callbacks.onCopyEditWidget($event, widget.widget); + } + } + private exportWidget($event: Event, widget: DashboardWidget) { if ($event) { $event.stopPropagation(); diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html index 176e305d94..6ff6c9ec23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.html @@ -62,6 +62,14 @@ matTooltipPosition="above"> {{ widget.isFullscreen ? 'fullscreen_exit' : 'fullscreen' }} +