UI: Added new widget action copy and edit widget

This commit is contained in:
Vladyslav Prykhodko 2024-08-05 23:24:09 +03:00
parent 4c353534cc
commit 3ea10fe733
9 changed files with 111 additions and 13 deletions

View File

@ -501,6 +501,28 @@ export class DashboardUtilsService {
this.removeUnusedWidgets(dashboard); 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 { public getRootStateId(states: {[id: string]: DashboardState }): string {
for (const stateId of Object.keys(states)) { for (const stateId of Object.keys(states)) {
const state = states[stateId]; const state = states[stateId];

View File

@ -177,7 +177,9 @@ export class ItemBufferService {
} }
public pasteWidget(targetDashboard: Dashboard, targetState: string, public pasteWidget(targetDashboard: Dashboard, targetState: string,
targetLayout: DashboardLayoutId, position: WidgetPosition, targetLayout: DashboardLayoutId,
breakpoint: string,
position: WidgetPosition,
onAliasesUpdateFunction: () => void, onAliasesUpdateFunction: () => void,
onFiltersUpdateFunction: () => void): Observable<Widget> { onFiltersUpdateFunction: () => void): Observable<Widget> {
const widgetItem: WidgetItem = this.storeGet(WIDGET_ITEM); const widgetItem: WidgetItem = this.storeGet(WIDGET_ITEM);
@ -197,7 +199,7 @@ export class ItemBufferService {
return this.addWidgetToDashboard(targetDashboard, targetState, return this.addWidgetToDashboard(targetDashboard, targetState,
targetLayout, widget, aliasesInfo, filtersInfo, targetLayout, widget, aliasesInfo, filtersInfo,
onAliasesUpdateFunction, onFiltersUpdateFunction, onAliasesUpdateFunction, onFiltersUpdateFunction,
originalColumns, originalSize, targetRow, targetColumn).pipe( originalColumns, originalSize, targetRow, targetColumn, breakpoint).pipe(
map(() => widget) map(() => widget)
); );
} else { } else {
@ -205,8 +207,11 @@ export class ItemBufferService {
} }
} }
public pasteWidgetReference(targetDashboard: Dashboard, targetState: string, public pasteWidgetReference(targetDashboard: Dashboard,
targetLayout: DashboardLayoutId, position: WidgetPosition): Observable<Widget> { targetState: string,
targetLayout: DashboardLayoutId,
breakpoint: string,
position: WidgetPosition): Observable<Widget> {
const widgetReference: WidgetReference = this.storeGet(WIDGET_REFERENCE); const widgetReference: WidgetReference = this.storeGet(WIDGET_REFERENCE);
if (widgetReference) { if (widgetReference) {
const widget = targetDashboard.configuration.widgets[widgetReference.widgetId]; const widget = targetDashboard.configuration.widgets[widgetReference.widgetId];
@ -222,7 +227,7 @@ export class ItemBufferService {
return this.addWidgetToDashboard(targetDashboard, targetState, return this.addWidgetToDashboard(targetDashboard, targetState,
targetLayout, widget, null, targetLayout, widget, null,
null, null, null, originalColumns, null, null, null, originalColumns,
originalSize, targetRow, targetColumn).pipe( originalSize, targetRow, targetColumn, breakpoint).pipe(
map(() => widget) map(() => widget)
); );
} else { } else {
@ -242,7 +247,8 @@ export class ItemBufferService {
originalColumns: number, originalColumns: number,
originalSize: WidgetSize, originalSize: WidgetSize,
row: number, row: number,
column: number): Observable<Dashboard> { column: number,
breakpoint = 'default'): Observable<Dashboard> {
let theDashboard: Dashboard; let theDashboard: Dashboard;
if (dashboard) { if (dashboard) {
theDashboard = dashboard; theDashboard = dashboard;
@ -273,7 +279,7 @@ export class ItemBufferService {
} }
} }
this.dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget, this.dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget,
originalColumns, originalSize, row, column); originalColumns, originalSize, row, column, breakpoint);
if (callAliasUpdateFunction) { if (callAliasUpdateFunction) {
onAliasesUpdateFunction(); onAliasesUpdateFunction();
} }
@ -406,8 +412,7 @@ export class ItemBufferService {
} }
} }
if (gridSettings && if (gridSettings && gridSettings.columns) {
gridSettings.columns) {
originalColumns = gridSettings.columns; originalColumns = gridSettings.columns;
} }
originalColumns = originalColumns * layoutCount; originalColumns = originalColumns * layoutCount;

View File

@ -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) { copyWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget) {
this.itembuffer.copyWidget(this.dashboard, this.itembuffer.copyWidget(this.dashboard,
this.dashboardCtx.state, layoutCtx.id, widget, layoutCtx.breakpoint); 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) { 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( pos, this.entityAliasesUpdated.bind(this), this.filtersUpdated.bind(this)).subscribe(
(widget) => { (widget) => {
layoutCtx.widgets.addWidgetId(widget.id); layoutCtx.widgets.addWidgetId(widget.id);
@ -1394,7 +1421,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
} }
pasteWidgetReference($event: Event, layoutCtx: DashboardPageLayoutContext, pos: WidgetPosition) { 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( pos).subscribe(
(widget) => { (widget) => {
layoutCtx.widgets.addWidgetId(widget.id); layoutCtx.widgets.addWidgetId(widget.id);

View File

@ -56,6 +56,7 @@ export interface IDashboardController {
openDashboardState(stateId: string, openRightLayout: boolean); openDashboardState(stateId: string, openRightLayout: boolean);
addWidget($event: Event, layoutCtx: DashboardPageLayoutContext); addWidget($event: Event, layoutCtx: DashboardPageLayoutContext);
editWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); editWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget);
copyEditWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget);
exportWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget, widgetTitle: string); exportWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget, widgetTitle: string);
removeWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); removeWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget);
widgetMouseDown($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget); widgetMouseDown($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget);

View File

@ -231,6 +231,10 @@ export class DashboardLayoutComponent extends PageComponent implements ILayoutCo
this.layoutCtx.dashboardCtrl.editWidget($event, this.layoutCtx, widget); 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 { onExportWidget($event: Event, widget: Widget, widgetTitle: string): void {
this.layoutCtx.dashboardCtrl.exportWidget($event, this.layoutCtx, widget, widgetTitle); this.layoutCtx.dashboardCtrl.exportWidget($event, this.layoutCtx, widget, widgetTitle);
} }

View File

@ -401,6 +401,9 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo
case WidgetComponentActionType.EDIT: case WidgetComponentActionType.EDIT:
this.editWidget($event, widget); this.editWidget($event, widget);
break; break;
case WidgetComponentActionType.COPY_EDIT:
this.editCopyWidget($event, widget);
break;
case WidgetComponentActionType.EXPORT: case WidgetComponentActionType.EXPORT:
this.exportWidget($event, widget); this.exportWidget($event, widget);
break; 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) { private exportWidget($event: Event, widget: DashboardWidget) {
if ($event) { if ($event) {
$event.stopPropagation(); $event.stopPropagation();

View File

@ -62,6 +62,14 @@
matTooltipPosition="above"> matTooltipPosition="above">
<tb-icon>{{ widget.isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</tb-icon> <tb-icon>{{ widget.isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</tb-icon>
</button> </button>
<button mat-icon-button
[fxShow]="isEditActionEnabled && !widget.isFullscreen"
*ngIf="isReferenceWidget"
(click)="onCopyEdit($event)"
matTooltip="Edit copy widget"
matTooltipPosition="above">
<tb-icon>mdi:circle-edit-outline</tb-icon>
</button>
<button mat-icon-button <button mat-icon-button
[fxShow]="isEditActionEnabled && !widget.isFullscreen" [fxShow]="isEditActionEnabled && !widget.isFullscreen"
(click)="onEdit($event)" (click)="onEdit($event)"

View File

@ -45,7 +45,8 @@ export enum WidgetComponentActionType {
CONTEXT_MENU, CONTEXT_MENU,
EDIT, EDIT,
EXPORT, EXPORT,
REMOVE REMOVE,
COPY_EDIT,
} }
export class WidgetComponentAction { export class WidgetComponentAction {
@ -113,6 +114,8 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, A
private cssClass: string; private cssClass: string;
isReferenceWidget = false;
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private renderer: Renderer2, private renderer: Renderer2,
@ -122,6 +125,7 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, A
ngOnInit(): void { ngOnInit(): void {
this.widget.widgetContext.containerChangeDetector = this.cd; this.widget.widgetContext.containerChangeDetector = this.cd;
this.isReferenceWidget = this.dashboardWidgets.isReferenceWidget(this.widget);
const cssString = this.widget.widget.config.widgetCss; const cssString = this.widget.widget.config.widgetCss;
if (isNotEmptyStr(cssString)) { if (isNotEmptyStr(cssString)) {
this.cssClass = this.cssClass =
@ -184,6 +188,13 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, A
}); });
} }
onCopyEdit(event: MouseEvent) {
this.widgetComponentAction.emit({
event,
actionType: WidgetComponentActionType.COPY_EDIT
});
}
onExport(event: MouseEvent) { onExport(event: MouseEvent) {
this.widgetComponentAction.emit({ this.widgetComponentAction.emit({
event, event,

View File

@ -42,6 +42,7 @@ import { enumerable } from '@shared/decorators/enumerable';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbPopoverComponent } from '@shared/components/popover.component';
import { ComponentStyle, iconStyle, textStyle } from '@shared/models/widget-settings.models'; import { ComponentStyle, iconStyle, textStyle } from '@shared/models/widget-settings.models';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
export interface WidgetsData { export interface WidgetsData {
widgets: Array<Widget>; widgets: Array<Widget>;
@ -65,6 +66,7 @@ export interface WidgetContextMenuItem extends ContextMenuItem {
export interface DashboardCallbacks { export interface DashboardCallbacks {
onEditWidget?: ($event: Event, widget: Widget) => void; onEditWidget?: ($event: Event, widget: Widget) => void;
onCopyEditWidget?: ($event: Event, widget: Widget) => void;
onExportWidget?: ($event: Event, widget: Widget, widgeTitle: string) => void; onExportWidget?: ($event: Event, widget: Widget, widgeTitle: string) => void;
onRemoveWidget?: ($event: Event, widget: Widget) => void; onRemoveWidget?: ($event: Event, widget: Widget) => void;
onWidgetMouseDown?: ($event: Event, widget: Widget) => void; onWidgetMouseDown?: ($event: Event, widget: Widget) => void;
@ -137,7 +139,8 @@ export class DashboardWidgets implements Iterable<DashboardWidget> {
constructor(private dashboard: IDashboardComponent, constructor(private dashboard: IDashboardComponent,
private widgetsDiffer: IterableDiffer<Widget>, private widgetsDiffer: IterableDiffer<Widget>,
private widgetLayoutsDiffer: KeyValueDiffer<string, WidgetLayout>) { private widgetLayoutsDiffer: KeyValueDiffer<string, WidgetLayout>,
private dashboardUtils: DashboardUtilsService) {
} }
doCheck() { doCheck() {
@ -290,6 +293,11 @@ export class DashboardWidgets implements Iterable<DashboardWidget> {
return this.dashboardWidgets.find((dashboardWidget) => dashboardWidget.selected); return this.dashboardWidgets.find((dashboardWidget) => dashboardWidget.selected);
} }
isReferenceWidget(widget: DashboardWidget): boolean {
return this.dashboardUtils.isReferenceWidget(this.dashboard.stateController.dashboardCtrl.dashboardCtx.getDashboard(),
widget.widgetId);
}
private findWidgetById(widgetId: string): DashboardWidget { private findWidgetById(widgetId: string): DashboardWidget {
return this.dashboardWidgets.find((dashboardWidget) => dashboardWidget.widgetId === widgetId); return this.dashboardWidgets.find((dashboardWidget) => dashboardWidget.widgetId === widgetId);
} }