From 07a45573b7a7678f14985589a985df8d553ffdc1 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 8 Aug 2024 12:15:56 +0300 Subject: [PATCH] UI: Add widget action tooltip reference hint and new action replaceReferenceWithWidgetCopy --- .../core/services/dashboard-utils.service.ts | 67 ++++++++++++++++- .../app/core/services/item-buffer.service.ts | 44 +---------- .../dashboard-page.component.ts | 33 +++------ .../dashboard-page/dashboard-page.models.ts | 2 +- .../layout/dashboard-layout.component.ts | 4 +- .../dashboard/dashboard.component.html | 2 +- .../dashboard/dashboard.component.ts | 12 +-- .../widget/widget-container.component.scss | 30 ++++++-- .../widget/widget-container.component.ts | 74 ++++++++++--------- .../home/models/dashboard-component.models.ts | 2 +- .../assets/locale/locale.constant-en_US.json | 6 +- ui-ngx/src/styles.scss | 6 ++ 12 files changed, 163 insertions(+), 119 deletions(-) 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 3f3972da8a..1df19d7496 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -29,7 +29,7 @@ import { GridSettings, WidgetLayout } from '@shared/models/dashboard.models'; -import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined, isEqual } from '@core/utils'; +import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined } from '@core/utils'; import { Datasource, datasourcesHasOnlyComparisonAggregation, @@ -40,7 +40,7 @@ import { TargetDeviceType, Widget, WidgetConfig, - WidgetConfigMode, + WidgetConfigMode, WidgetSize, widgetType, WidgetTypeDescriptor } from '@app/shared/models/widget.models'; @@ -933,4 +933,67 @@ export class DashboardUtilsService { } } + replaceReferenceWithWidgetCopy(widget: Widget, + dashboard: Dashboard, + targetState: string, + targetLayout: DashboardLayoutId, + breakpointId: string, + isRemoveWidget: boolean): Widget { + + const newWidget = deepClone(widget); + newWidget.id = this.utils.guid(); + + const originalColumns = this.getOriginalColumns(dashboard, targetState, targetLayout, breakpointId); + const originalSize = this.getOriginalSize(dashboard, targetState, targetLayout, widget, breakpointId); + + const layout = this.getDashboardLayoutConfig(dashboard.configuration.states[targetState].layouts[targetLayout], breakpointId); + const widgetLayout = layout.widgets[widget.id]; + const targetRow = widgetLayout.row; + const targetColumn = widgetLayout.col; + + if (isRemoveWidget) { + this.removeWidgetFromLayout(dashboard, targetState, targetLayout, widget.id, breakpointId); + } + + this.addWidgetToLayout(dashboard, targetState, targetLayout, newWidget, originalColumns, originalSize, + targetRow, targetColumn, breakpointId); + + return newWidget; + } + + getDashboardLayoutConfig(layout: DashboardLayout, breakpointId: string): DashboardLayout { + if (breakpointId !== 'default') { + return layout.breakpoints[breakpointId]; + } + return layout; + } + + getOriginalColumns(dashboard: Dashboard, sourceState: string, sourceLayout: DashboardLayoutId, breakpointId: string): number { + let originalColumns = 24; + let gridSettings = null; + const state = dashboard.configuration.states[sourceState]; + const layoutCount = Object.keys(state.layouts).length; + if (state) { + const layout = this.getDashboardLayoutConfig(state.layouts[sourceLayout], breakpointId); + if (layout) { + gridSettings = layout.gridSettings; + } + } + if (gridSettings && gridSettings.columns) { + originalColumns = gridSettings.columns; + } + originalColumns = originalColumns * layoutCount; + return originalColumns; + } + + getOriginalSize(dashboard: Dashboard, sourceState: string, sourceLayout: DashboardLayoutId, + widget: Widget, breakpointId: string): WidgetSize { + const layout = this.getDashboardLayoutConfig(dashboard.configuration.states[sourceState].layouts[sourceLayout], breakpointId); + const widgetLayout = layout.widgets[widget.id]; + return { + sizeX: widgetLayout.sizeX, + sizeY: widgetLayout.sizeY + }; + } + } 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 8e80ce1d25..3aa45c8439 100644 --- a/ui-ngx/src/app/core/services/item-buffer.service.ts +++ b/ui-ngx/src/app/core/services/item-buffer.service.ts @@ -95,8 +95,8 @@ export class ItemBufferService { const filtersInfo: FiltersInfo = { datasourceFilters: {} }; - const originalColumns = this.getOriginalColumns(dashboard, sourceState, sourceLayout, breakpoint); - const originalSize = this.getOriginalSize(dashboard, sourceState, sourceLayout, widget, breakpoint); + const originalColumns = this.dashboardUtils.getOriginalColumns(dashboard, sourceState, sourceLayout, breakpoint); + const originalSize = this.dashboardUtils.getOriginalSize(dashboard, sourceState, sourceLayout, widget, breakpoint); const datasources: Datasource[] = widget.type === widgetType.alarm ? [widget.config.alarmSource] : widget.config.datasources; if (widget.config && dashboard.configuration && dashboard.configuration.entityAliases) { @@ -396,42 +396,6 @@ export class ItemBufferService { return ruleChainImport; } - private getOriginalColumns(dashboard: Dashboard, sourceState: string, sourceLayout: DashboardLayoutId, - breakpoint: string): number { - let originalColumns = 24; - let gridSettings = null; - const state = dashboard.configuration.states[sourceState]; - const layoutCount = Object.keys(state.layouts).length; - if (state) { - let layout = state.layouts[sourceLayout]; - if (breakpoint !== 'default') { - layout = layout.breakpoints[breakpoint]; - } - if (layout) { - gridSettings = layout.gridSettings; - - } - } - if (gridSettings && gridSettings.columns) { - originalColumns = gridSettings.columns; - } - originalColumns = originalColumns * layoutCount; - return originalColumns; - } - - private getOriginalSize(dashboard: Dashboard, sourceState: string, sourceLayout: DashboardLayoutId, widget: Widget, - breakpoint: string): WidgetSize { - let layout = dashboard.configuration.states[sourceState].layouts[sourceLayout]; - if (breakpoint !== 'default') { - layout = layout.breakpoints[breakpoint]; - } - const widgetLayout = layout.widgets[widget.id]; - return { - sizeX: widgetLayout.sizeX, - sizeY: widgetLayout.sizeY - }; - } - private prepareAliasInfo(entityAlias: EntityAlias): EntityAliasInfo { return { alias: entityAlias.alias, @@ -449,8 +413,8 @@ export class ItemBufferService { private prepareWidgetReference(dashboard: Dashboard, sourceState: string, sourceLayout: DashboardLayoutId, widget: Widget, breakpoint: string): WidgetReference { - const originalColumns = this.getOriginalColumns(dashboard, sourceState, sourceLayout, breakpoint); - const originalSize = this.getOriginalSize(dashboard, sourceState, sourceLayout, widget, breakpoint); + const originalColumns = this.dashboardUtils.getOriginalColumns(dashboard, sourceState, sourceLayout, breakpoint); + const originalSize = this.dashboardUtils.getOriginalSize(dashboard, sourceState, sourceLayout, widget, breakpoint); return { dashboardId: dashboard.id.id, sourceState, 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 ba8da29c17..33fcf16b83 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 @@ -483,7 +483,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC if (!this.widgetEditMode && !this.readonly && this.dashboardUtils.isEmptyDashboard(this.dashboard)) { this.setEditMode(true, false); } - this.setEditMode(true, false); } private init(data: DashboardPageInitData) { @@ -1419,31 +1418,17 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } } - copyEditWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget) { + replaceReferenceWithWidgetCopy($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 isRemove = layoutCtx.widgets.removeWidgetId(widget.id); - const targetRow = layoutCtx.widgetLayouts[widget.id].row; - const targetColumn = layoutCtx.widgetLayouts[widget.id].col; + const widgetCopy = this.dashboardUtils.replaceReferenceWithWidgetCopy(widget, this.dashboard, this.dashboardCtx.state, + layoutCtx.id, layoutCtx.breakpoint, isRemove); - 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(); + layoutCtx.widgets.addWidgetId(widgetCopy.id); - 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); - }); + this.runChangeDetection(); } copyWidget($event: Event, layoutCtx: DashboardPageLayoutContext, widget: Widget) { @@ -1591,11 +1576,11 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC widgetContextActions.push( { action: (event, currentWidget) => { - this.copyEditWidget(event, layoutCtx, currentWidget); + this.replaceReferenceWithWidgetCopy(event, layoutCtx, currentWidget); }, enabled: true, - value: 'widget.copy-edit', - icon: 'edit' + value: 'widget.replace-reference-with-widget-copy', + icon: 'mdi:file-replace-outline' } ); } 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 ca7da5a611..5fecec5f3a 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,7 +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); + replaceReferenceWithWidgetCopy($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 38c4b99b49..451c9ed7f5 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,8 +269,8 @@ 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); + replaceReferenceWithWidgetCopy($event: Event, widget: Widget): void { + this.layoutCtx.dashboardCtrl.replaceReferenceWithWidgetCopy($event, this.layoutCtx, widget); } onExportWidget($event: Event, widget: Widget, widgetTitle: string): void { diff --git a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html index 6469429295..33c8d659f6 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html @@ -58,7 +58,7 @@ [disabled]="!item.enabled" (click)="item.action(widgetContextMenuEvent, widget)"> {{ item.shortcut | keyboardShortcut }} - {{item.icon}} + {{item.icon}} {{item.value}} 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 ffb804a288..336fc72f02 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,15 +453,15 @@ 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; case WidgetComponentActionType.REMOVE: this.removeWidget($event, widget); break; + case WidgetComponentActionType.REPLACE_REFERENCE_WITH_WIDGET_COPY: + this.replaceReferenceWithWidgetCopy($event, widget); + break; } } @@ -486,12 +486,12 @@ export class DashboardComponent extends PageComponent implements IDashboardCompo } } - private editCopyWidget($event: Event, widget: DashboardWidget) { + private replaceReferenceWithWidgetCopy($event: Event, widget: DashboardWidget) { if ($event) { $event.stopPropagation(); } - if (this.isEditActionEnabled && this.callbacks && this.callbacks.onCopyEditWidget) { - this.callbacks.onCopyEditWidget($event, widget.widget); + if (this.isEditActionEnabled && this.callbacks && this.callbacks.replaceReferenceWithWidgetCopy) { + this.callbacks.replaceReferenceWithWidgetCopy($event, widget.widget); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss index 7b6d8e59f0..02b6d2737b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@import '../scss/constants'; + .tb-widget-container { position: absolute; inset: 0; @@ -182,12 +184,30 @@ gridster-item:hover { line-height: 12px; font-weight: 500; color: rgba(0, 0, 0, 0.76); - .tb-widget-actions-panel { + .tb-widget-action-container { display: flex; - flex-direction: row; - place-content: center flex-start; - align-items: center; - gap: 8px; + flex-direction: column; + gap: 6px; + + .tb-widget-actions-panel { + display: flex; + flex-direction: row; + place-content: center space-between; + align-items: center; + gap: 8px; + } + .tb-widget-reference-panel { + display: flex; + flex-direction: row; + place-content: center space-between; + align-items: center; + gap: 8px; + font-weight: normal; + color: $tb-primary-color; + font-size: 11px; + padding: 4px 4px 4px 6px; + border-radius: 2px; + } } } } 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 75bfb193eb..d1332c1bd7 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 @@ -49,7 +49,7 @@ export enum WidgetComponentActionType { EDIT, EXPORT, REMOVE, - COPY_EDIT, + REPLACE_REFERENCE_WITH_WIDGET_COPY, } export class WidgetComponentAction { @@ -220,10 +220,10 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O }); } - onCopyEdit(event: MouseEvent) { + onReplaceReferenceWithWidgetCopy(event: MouseEvent) { this.widgetComponentAction.emit({ event, - actionType: WidgetComponentActionType.COPY_EDIT + actionType: WidgetComponentActionType.REPLACE_REFERENCE_WITH_WIDGET_COPY }); } @@ -343,37 +343,43 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O } @Component({ - template: `
- - - - -
`, + template: ` +
+
+ {{ 'widget.reference' | translate }} + +
+
+ + + +
+
`, styles: [], encapsulation: ViewEncapsulation.None }) diff --git a/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts b/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts index efdc6e3a9a..e7fdfa78e3 100644 --- a/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/dashboard-component.models.ts @@ -65,7 +65,7 @@ export interface WidgetContextMenuItem extends ContextMenuItem { export interface DashboardCallbacks { onEditWidget?: ($event: Event, widget: Widget) => void; - onCopyEditWidget?: ($event: Event, widget: Widget) => void; + replaceReferenceWithWidgetCopy?: ($event: Event, widget: Widget) => void; onExportWidget?: ($event: Event, widget: Widget, widgeTitle: string) => void; onRemoveWidget?: ($event: Event, widget: Widget) => void; onWidgetMouseDown?: ($event: Event, widget: Widget) => void; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 7bde596fe5..54baf60aa2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5601,10 +5601,9 @@ "remove": "Remove widget", "delete": "Delete widget", "edit": "Edit widget", - "edit-copy": "Edit copy widget", - "copy-edit": "Copy and edit", "remove-widget-title": "Are you sure you want to remove the widget '{{widgetTitle}}'?", "remove-widget-text": "After the confirmation the widget and all related data will become unrecoverable.", + "replace-reference-with-widget-copy": "Replace reference with widget copy", "timeseries": "Time series", "search-data": "Search data", "no-data-found": "No data found", @@ -5685,7 +5684,8 @@ "search": "Search widget", "filter": "Widget filter type", "loading-widgets": "Loading widgets...", - "widget-template-error": "Invalid widget HTML template." + "widget-template-error": "Invalid widget HTML template.", + "reference": "Reference" }, "widget-action": { "header-button": "Widget header button", diff --git a/ui-ngx/src/styles.scss b/ui-ngx/src/styles.scss index c1465ceb3c..969cb431e6 100644 --- a/ui-ngx/src/styles.scss +++ b/ui-ngx/src/styles.scss @@ -921,6 +921,12 @@ mat-icon { } .mat-mdc-icon-button { + &.tb-mat-16 { + @include tb-mat-icon-button-size(16); + .mat-icon { + @include tb-mat-icon-size(16); + } + } &.tb-mat-20 { @include tb-mat-icon-button-size(20); .mat-icon {