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 bea8504cbd..4d9788ce8e 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -523,6 +523,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 a501a63e44..d67f22f3da 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 @@ -1419,6 +1419,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); @@ -1430,7 +1457,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); @@ -1439,7 +1466,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 78e9bb8b87..3b4e40fd8f 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 @@ -57,6 +57,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 0a3d13bb31..b5c1565ef4 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 @@ -269,6 +269,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 7170bdb4ec..136429ced4 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 @@ -453,6 +453,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; @@ -483,6 +486,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.ts b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts index 1546c4f92a..3f9e0e9ffe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts @@ -47,7 +47,8 @@ export enum WidgetComponentActionType { CONTEXT_MENU, EDIT, EXPORT, - REMOVE + REMOVE, + COPY_EDIT, } export class WidgetComponentAction { @@ -126,6 +127,8 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O private editWidgetActionsTooltip: ITooltipsterInstance; + isReferenceWidget = false; + constructor(protected store: Store, private cd: ChangeDetectorRef, private renderer: Renderer2, @@ -136,6 +139,7 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O ngOnInit(): void { this.widget.widgetContext.containerChangeDetector = this.cd; + this.isReferenceWidget = this.dashboardWidgets.isReferenceWidget(this.widget); const cssString = this.widget.widget.config.widgetCss; if (isNotEmptyStr(cssString)) { this.cssClass = @@ -216,6 +220,13 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O }); } + onCopyEdit(event: MouseEvent) { + this.widgetComponentAction.emit({ + event, + actionType: WidgetComponentActionType.COPY_EDIT + }); + } + onExport(event: MouseEvent) { this.widgetComponentAction.emit({ event, @@ -328,6 +339,14 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O @Component({ template: `
+