From 609ba690f5f0d53ea8a803b54dddb1860886f7dc Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 26 Mar 2025 17:06:45 +0200 Subject: [PATCH 01/14] Fixed Calculated fields creation of arguments with same name and adjustments --- .../calculated-fields-table-config.ts | 2 +- ...lated-field-arguments-table.component.html | 6 ++-- ...culated-field-arguments-table.component.ts | 36 +++++++++---------- ...lculated-field-argument-panel.component.ts | 11 +++--- ...entity-debug-settings-panel.component.html | 2 +- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts index 69c0a35fb5..c5b256ea89 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts @@ -160,7 +160,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig - +
}
From 6888f9ed5b3f58d905538e7b22a6d57e6904b15b Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 26 Mar 2025 17:20:16 +0200 Subject: [PATCH 02/14] refactoring --- .../calculated-field-arguments-table.component.ts | 2 +- .../panel/calculated-field-argument-panel.component.ts | 2 +- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index faca709b17..8f7e3b9893 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -180,7 +180,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces ctx, {}, {}, {}, true); - this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe((value ) => { + this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe(value=> { this.popoverComponent.hide(); if (isExists) { this.argumentsFormArray.at(index).setValue(value); diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts index 70cf529348..c5a7407d58 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts @@ -140,7 +140,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI } ngAfterViewInit(): void { - if (this.argument.refEntityId.id === NULL_UUID) { + if (this.argument.refEntityId?.id === NULL_UUID) { this.entityAutocomplete.selectEntityFormGroup.get('entity').markAsTouched(); } } 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 aa1c6dd6fb..4fd86ea533 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1000,8 +1000,8 @@ "calculated-field": "calculated field", "hint": { "main-limited": "No more than {{msg}} {{entity}} debug messages per {{time}} will be recorded.", - "on-failure": "Log all debug messages.", - "all-messages": "Log error messages only. " + "on-failure": "Log error messages only.", + "all-messages": "Log all debug messages." } }, "calculated-fields": { From 6a5e57566ef4503c4112d5594c8bab851406b634 Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Wed, 26 Mar 2025 18:47:56 +0200 Subject: [PATCH 03/14] fixed telemetry deletion --- .../calculatedField/CalculatedFieldEntityMessageProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java index 93214e4403..db65248a8f 100644 --- a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldEntityMessageProcessor.java @@ -422,7 +422,7 @@ public class CalculatedFieldEntityMessageProcessor extends AbstractContextAwareM private Map mapToArgumentsWithFetchedValue(CalculatedFieldCtx ctx, List removedTelemetryKeys) { Map deletedArguments = ctx.getArguments().entrySet().stream() - .filter(entry -> removedTelemetryKeys.contains(entry.getKey())) + .filter(entry -> removedTelemetryKeys.contains(entry.getValue().getRefEntityKey().getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); Map fetchedArgs = cfService.fetchArgsFromDb(tenantId, entityId, deletedArguments); From 3005b5bf8fc576fa6e4cb9832373eb063f98690b Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 27 Mar 2025 07:31:42 +0200 Subject: [PATCH 04/14] UI: Backward compatibility for header icon button action --- .../action/manage-widget-actions-dialog.component.html | 1 + .../widget/action/manage-widget-actions-dialog.component.ts | 1 + .../widget/action/manage-widget-actions.component.ts | 3 +++ .../widget/action/widget-action-dialog.component.ts | 6 +++++- .../config/basic/common/widget-actions-panel.component.ts | 1 + .../home/components/widget/widget-config.component.html | 1 + .../app/modules/home/components/widget/widget.component.ts | 2 +- 7 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.html index 3d88f08c8d..2376e52a64 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.html @@ -33,6 +33,7 @@ [callbacks]="data.callbacks" [widgetType] = "data.widgetType" [actionSources]="actionSources" + [defaultIconColor]="data.defaultIconColor" [additionalWidgetActionTypes]="data.additionalWidgetActionTypes" formControlName="actions"> diff --git a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts index bc3de16c69..067eb74166 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions-dialog.component.ts @@ -32,6 +32,7 @@ export interface ManageWidgetActionsDialogData { actionsData: WidgetActionsData; callbacks: WidgetActionCallbacks; widgetType: widgetType; + defaultIconColor?: string; additionalWidgetActionTypes?: WidgetActionType[]; } diff --git a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts index 730be78656..f555aeb2b2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/manage-widget-actions.component.ts @@ -73,6 +73,8 @@ export class ManageWidgetActionsComponent extends PageComponent implements OnIni @Input() widgetType: widgetType; + @Input() defaultIconColor: string; + @Input() callbacks: WidgetActionCallbacks; @Input() actionSources: {[actionSourceId: string]: WidgetActionSource}; @@ -239,6 +241,7 @@ export class ManageWidgetActionsComponent extends PageComponent implements OnIni actionsData, action: deepClone(action), widgetType: this.widgetType, + defaultIconColor: this.defaultIconColor, additionalWidgetActionTypes: this.additionalWidgetActionTypes } }).afterClosed().subscribe( diff --git a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts index b77b5c860f..7a74624774 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts @@ -61,6 +61,7 @@ export interface WidgetActionDialogData { actionsData: WidgetActionsData; action?: WidgetActionDescriptorInfo; widgetType: widgetType; + defaultIconColor?: string; additionalWidgetActionTypes?: WidgetActionType[]; } @@ -78,6 +79,8 @@ export class WidgetActionDialogComponent extends DialogComponent diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index f8fa032c8c..a15da83a28 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -365,7 +365,7 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, headerButtonStyle(buttonType: WidgetHeaderActionButtonType = WidgetHeaderActionButtonType.icon, customButtonStyle:{[key: string]: string}, - buttonColor: string = 'rgba(0,0,0,0.87)', + buttonColor: string = this.widget.config.color, backgroundColor: string, borderColor: string) { const buttonStyle = {}; From eccebac5cf3de14eb27629137fd03f5feec7a0b5 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 27 Mar 2025 09:05:08 +0200 Subject: [PATCH 05/14] UI: Fixed wind turbine cluster scada symbol --- .../data/json/system/scada_symbols/wind-turbine-cluster-hp.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg b/application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg index 74855dd35a..746ca9f1aa 100644 --- a/application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg +++ b/application/src/main/data/json/system/scada_symbols/wind-turbine-cluster-hp.svg @@ -349,7 +349,7 @@ - + From de10a97fabe0fbf2db6f26d93e089afa6ef96062 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 26 Mar 2025 16:20:54 +0200 Subject: [PATCH 06/14] UI: Fixed place map item action on multiple header button clicks --- ui-ngx/src/app/core/api/widget-api.models.ts | 2 +- .../home/components/widget/lib/maps/map.ts | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 7d0f091739..d5f1b45a82 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -91,7 +91,7 @@ export interface IWidgetUtils { } export interface PlaceMapItemActionData { - action: WidgetAction; + action: WidgetAction | WidgetActionDescriptor; additionalParams?: any; afterPlaceItemCallback: ($event: Event, descriptor: WidgetAction, entityId?: EntityId, entityName?: string, additionalParams?: any, entityLabel?: string) => void; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts index 6672941045..70433f7999 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts @@ -133,6 +133,7 @@ export abstract class TbMap { private currentEditButton: L.TB.ToolbarButton; private dragMode = true; + private createMapItemActionId: string; private get isPlacingItem(): boolean { return !!this.currentEditButton; @@ -685,9 +686,14 @@ export abstract class TbMap { } private createItem(actionData: PlaceMapItemActionData, prepareDrawMode: () => void) { - if (this.isPlacingItem) { + const actionId = 'id' in actionData.action ? actionData.action.id : 'map-button'; + if (this.createMapItemActionId === actionId) { + this.finishCreatedItem(); return; } + if (isDefined(this.createMapItemActionId)) { + this.finishCreatedItem(); + } this.updatePlaceItemState(actionData.additionalParams?.button, true); this.map.once('pm:create', (e) => { @@ -700,7 +706,7 @@ export abstract class TbMap { // @ts-ignore e.layer._pmTempLayer = true; e.layer.remove(); - this.finishAdd(); + this.finishCreatedItem(); }); prepareDrawMode(); @@ -713,10 +719,12 @@ export abstract class TbMap { iconClass: 'tb-close', title: this.ctx.translate.instant('action.cancel'), showText: true, - click: this.finishAdd + click: this.finishCreatedItem } ], false); + this.createMapItemActionId = actionId; + const convertLayerToCoordinates = (type: MapItemType, layer: L.Layer): {x: number; y: number} | TbPolygonRawCoordinates | TbCircleData => { switch (type) { case MapItemType.marker: @@ -748,6 +756,11 @@ export abstract class TbMap { } } + private finishCreatedItem = () => { + delete this.createMapItemActionId; + this.finishAdd(); + } + private finishAdd = () => { if (this.currentPopover) { this.currentPopover.hide(); From f74ca2fb971a3213dd6805dfd766c61dafc0c5f2 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 27 Mar 2025 11:16:06 +0200 Subject: [PATCH 07/14] Optimized entities map --- ...culated-field-arguments-table.component.ts | 65 +++++++++++++------ ...ulated-field-argument-panel.component.html | 1 + ...lculated-field-argument-panel.component.ts | 14 +++- .../shared/models/calculated-field.models.ts | 1 + 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index 8f7e3b9893..02b258b90e 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -49,7 +49,7 @@ import { TbPopoverService } from '@shared/components/popover.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { EntityId } from '@shared/models/id/entity-id'; import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; -import { getEntityDetailsPageURL, isDefined, isDefinedAndNotNull, isEqual } from '@core/utils'; +import { getEntityDetailsPageURL, isEqual } from '@core/utils'; import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbTableDatasource } from '@shared/components/table/table-datasource.abstract'; import { EntityService } from '@core/http/entity.service'; @@ -57,9 +57,9 @@ import { MatSort } from '@angular/material/sort'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { catchError } from 'rxjs/operators'; -import { NEVER } from 'rxjs'; +import { forkJoin, Observable } from 'rxjs'; import { NULL_UUID } from '@shared/models/id/has-uuid'; +import { BaseData } from '@shared/models/base-data'; @Component({ selector: 'tb-calculated-field-arguments-table', @@ -115,7 +115,6 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces private store: Store ) { this.argumentsFormArray.valueChanges.pipe(takeUntilDestroyed()).subscribe(value => { - this.updateEntityNameMap(value); this.updateDataSource(value); this.propagateChange(this.getArgumentsObject(value)); }); @@ -180,8 +179,11 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces ctx, {}, {}, {}, true); - this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe(value=> { + this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe(({ entityName, ...value }) => { this.popoverComponent.hide(); + if (entityName) { + this.entityNameMap.set(value.refEntityId.id, entityName); + } if (isExists) { this.argumentsFormArray.at(index).setValue(value); } else { @@ -220,7 +222,8 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces writeValue(argumentsObj: Record): void { this.argumentsFormArray.clear(); - this.populateArgumentsFormArray(argumentsObj) + this.populateArgumentsFormArray(argumentsObj); + this.updateEntityNameMap(this.argumentsFormArray.value); } getEntityDetailsPageURL(id: string, type: EntityType): string { @@ -238,23 +241,43 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces this.argumentsFormArray.updateValueAndValidity(); } - private updateEntityNameMap(value: CalculatedFieldArgumentValue[]): void { - value.forEach(({ refEntityId = {}}) => { - if (refEntityId.id && !this.entityNameMap.has(refEntityId.id)) { + private updateEntityNameMap(values: CalculatedFieldArgumentValue[]): void { + const entitiesByType = values.reduce((acc, { refEntityId = {}}) => { + if (refEntityId.id && refEntityId.entityType !== ArgumentEntityType.Tenant) { const { id, entityType } = refEntityId as EntityId; - this.entityService.getEntity(entityType as EntityType, id, { ignoreLoading: true, ignoreErrors: true }) - .pipe( - catchError(() => { - const control = this.argumentsFormArray.controls.find(control => control.value.refEntityId?.id === id); - control.setValue({ ...control.value, refEntityId: { ...control.value.refEntityId, id: NULL_UUID } }); - - return NEVER; - }), - takeUntilDestroyed(this.destroyRef) - ) - .subscribe(entity => this.entityNameMap.set(id, entity.name)); + acc[entityType] = acc[entityType] ?? []; + acc[entityType].push(id); } - }); + return acc; + }, {} as Record); + const tasks = Object.entries(entitiesByType).map(([entityType, ids]) => + this.entityService.getEntities(entityType as EntityType, ids) + ); + if (!tasks.length) { + return; + } + this.fetchEntityNames(tasks, values); + } + + private fetchEntityNames(tasks: Observable[]>[], values: CalculatedFieldArgumentValue[]): void { + forkJoin(tasks as Observable[]>[]) + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((result: Array>[]) => { + result.forEach((entities: BaseData[]) => entities.forEach((entity: BaseData) => this.entityNameMap.set(entity.id.id, entity.name))); + let updateTable = false; + values.forEach(({ refEntityId }) => { + if (refEntityId?.id && !this.entityNameMap.has(refEntityId.id) && refEntityId.entityType !== ArgumentEntityType.Tenant) { + updateTable = true; + const control = this.argumentsFormArray.controls.find(control => control.value.refEntityId?.id === refEntityId.id); + const value = control.value; + value.refEntityId.id = NULL_UUID; + control.setValue(value, { emitEvent: false }); + } + }); + if (updateTable) { + this.argumentsFormArray.updateValueAndValidity(); + } + }); } private getSortValue(argument: CalculatedFieldArgumentValue, column: string): string { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html index 15286af377..7521395cb4 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html @@ -88,6 +88,7 @@ [placeholder]="'action.set' | translate" [required]="true" [entityType]="ArgumentEntityTypeParamsMap.get(entityType).entityType" + (entityChanged)="entityNameSubject.next($event?.name)" /> } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts index c5a7407d58..2a64c90f20 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.ts @@ -36,7 +36,7 @@ import { EntityId } from '@shared/models/id/entity-id'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { EntityFilter } from '@shared/models/query/query.models'; import { AliasFilterType } from '@shared/models/alias.models'; -import { merge } from 'rxjs'; +import { BehaviorSubject, merge } from 'rxjs'; import { MINUTE } from '@shared/models/time/time.models'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { AppState } from '@core/core.state'; @@ -84,6 +84,7 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI argumentTypes: ArgumentType[]; entityFilter: EntityFilter; + entityNameSubject = new BehaviorSubject(null); readonly argumentEntityTypes = Object.values(ArgumentEntityType) as ArgumentEntityType[]; readonly ArgumentEntityTypeTranslations = ArgumentEntityTypeTranslations; @@ -151,6 +152,9 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI if (refEntityId.entityType === ArgumentEntityType.Tenant) { refEntityId.id = this.tenantId; } + if (refEntityId.entityType !== ArgumentEntityType.Current && refEntityId.entityType !== ArgumentEntityType.Tenant) { + value.entityName = this.entityNameSubject.value; + } if (value.defaultValue) { value.defaultValue = value.defaultValue.trim(); } @@ -211,12 +215,16 @@ export class CalculatedFieldArgumentPanelComponent implements OnInit, AfterViewI } private observeEntityTypeChanges(): void { - this.argumentFormGroup.get('refEntityId').get('entityType').valueChanges + this.refEntityIdFormGroup.get('entityType').valueChanges .pipe(distinctUntilChanged(), takeUntilDestroyed()) .subscribe(type => { this.argumentFormGroup.get('refEntityId').get('id').setValue(''); + const isEntityWithId = type !== ArgumentEntityType.Tenant && type !== ArgumentEntityType.Current; this.argumentFormGroup.get('refEntityId') - .get('id')[type === ArgumentEntityType.Tenant || type === ArgumentEntityType.Current ? 'disable' : 'enable'](); + .get('id')[isEntityWithId ? 'enable' : 'disable'](); + if (!isEntityWithId) { + this.entityNameSubject.next(null); + } if (!this.enableAttributeScopeSelection) { this.refEntityKeyFormGroup.get('scope').setValue(AttributeScope.SERVER_SCOPE); } diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 383f7c7f72..9cc9a62da8 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -144,6 +144,7 @@ export interface RefEntityId { export interface CalculatedFieldArgumentValue extends CalculatedFieldArgument { argumentName: string; + entityName?: string; } export type CalculatedFieldTestScriptFn = (calculatedField: CalculatedField, argumentsObj?: Record, closeAllOnSave?: boolean) => Observable; From 131e96a575951f1d38baf8b16547f2fd451cc458 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 27 Mar 2025 11:22:59 +0200 Subject: [PATCH 08/14] refatoring --- .../calculated-field-arguments-table.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index 02b258b90e..0e3d175f5e 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -89,7 +89,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces errorText = ''; argumentsFormArray = this.fb.array([]); - entityNameMap = new Map([[NULL_UUID, '']]); + entityNameMap = new Map(); sortOrder = { direction: 'asc', property: '' }; dataSource = new CalculatedFieldArgumentDatasource(); From 515eaa6d597d775508af1b0e7d9820d5e6861023 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 27 Mar 2025 12:10:09 +0200 Subject: [PATCH 09/14] refactoring --- .../calculated-field-arguments-table.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index ecf59aa7dd..7763fd6f03 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -183,7 +183,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces context: ctx, isModal: true }); - this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe(({ value, index }) => { + this.popoverComponent.tbComponentRef.instance.argumentsDataApplied.subscribe(({ entityName, ...value }) => { this.popoverComponent.hide(); if (entityName) { this.entityNameMap.set(value.refEntityId.id, entityName); From 908680dd3d09bfc75eb6fd863e1d687d7d72a1a1 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 27 Mar 2025 12:24:36 +0200 Subject: [PATCH 10/14] UI: Dynamic title height for widget title --- .../widget/dynamic-widget.component.ts | 3 +- .../widget/lib/maps/map-widget.component.html | 7 ++- .../widget/lib/maps/map-widget.component.scss | 3 + .../widget/lib/maps/map-widget.component.ts | 14 ++++- .../widget/widget-container.component.html | 63 ++++++++++--------- .../components/widget/widget.component.ts | 8 +++ .../home/models/widget-component.models.ts | 1 + 7 files changed, 66 insertions(+), 33 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts index b6919ec670..a0b6f07647 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts @@ -19,7 +19,7 @@ import { Directive, inject, Injector, OnDestroy, OnInit } from '@angular/core'; import { IDynamicWidgetComponent, widgetContextToken, - widgetErrorMessagesToken, + widgetErrorMessagesToken, widgetHeaderButtonActionToken, widgetTitlePanelToken } from '@home/models/widget-component.models'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; @@ -72,6 +72,7 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid public readonly ctx = inject(widgetContextToken); public readonly errorMessages = inject(widgetErrorMessagesToken); public readonly widgetTitlePanel = inject(widgetTitlePanelToken); + public readonly widgetHeaderButtonAction = inject(widgetHeaderButtonActionToken); constructor() { super(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html index b45869addf..9a200ef88c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html @@ -17,9 +17,10 @@ -->
- - - + + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss index 88157426f3..b8167ff06e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss @@ -34,4 +34,7 @@ div.tb-widget-title { padding: 0; } + .tb-widget-actions.tb-widget-actions-absolute { + z-index: 2; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts index 013a6c88a9..4bb2b11dd3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts @@ -15,6 +15,7 @@ /// import { + AfterViewInit, ChangeDetectorRef, Component, ElementRef, @@ -45,7 +46,7 @@ import { DomSanitizer } from '@angular/platform-browser'; styleUrls: ['./map-widget.component.scss'], encapsulation: ViewEncapsulation.None }) -export class MapWidgetComponent implements OnInit, OnDestroy { +export class MapWidgetComponent implements OnInit, OnDestroy, AfterViewInit { @ViewChild('mapElement', {static: false}) mapElement: ElementRef; @@ -58,6 +59,9 @@ export class MapWidgetComponent implements OnInit, OnDestroy { @Input() widgetTitlePanel: TemplateRef; + @Input() + widgetHeaderButtonAction: TemplateRef; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; padding: string; @@ -79,6 +83,14 @@ export class MapWidgetComponent implements OnInit, OnDestroy { this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; } + ngAfterViewInit() { + if (this.widgetComponent.dashboardWidget.showWidgetTitlePanel && !!this.widgetHeaderButtonAction) { + const tbWidgetTitle = $(".tb-widget-title")[0]; + if (getComputedStyle(tbWidgetTitle).getPropertyValue('min-height') === 'auto') + tbWidgetTitle.style.minHeight = $(".tb-widget-actions")[0].offsetHeight + 'px'; + } + } + ngOnDestroy() { if (this.map) { this.map.destroy(); 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 24658a8ad7..55182a8a01 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 @@ -33,33 +33,9 @@ -
-
- @for (action of widget.customHeaderActions; track action.name; let last = $last) { - - } -
- - - -
+ + +
+ [widgetTitlePanel]="widgetTitlePanel" + [widgetHeaderButtonAction]="widgetHeaderButtonAction">
@@ -102,6 +79,36 @@ + +
+
+ @for (action of widget.customHeaderActions; track action.name; let last = $last) { + + } +
+ + + +
+
+ @switch (action.buttonType) { @case (widgetHeaderActionButtonType.miniFab) { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index f8fa032c8c..5b5bb2fe57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -75,6 +75,7 @@ import { widgetContextToken, widgetErrorMessagesToken, WidgetHeaderAction, + widgetHeaderButtonActionToken, WidgetInfo, widgetTitlePanelToken, WidgetTypeInstance @@ -139,6 +140,9 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, @Input() widgetTitlePanel: TemplateRef; + @Input() + widgetHeaderButtonAction: TemplateRef; + @Input() isEdit: boolean; @@ -817,6 +821,10 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, { provide: widgetTitlePanelToken, useValue: this.widgetTitlePanel + }, + { + provide: widgetHeaderButtonActionToken, + useValue: this.widgetHeaderButtonAction } ], parent: this.injector diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index 11adb2f806..a27f1727c5 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -559,6 +559,7 @@ export class LabelVariablePattern { export const widgetContextToken = new InjectionToken('widgetContext'); export const widgetErrorMessagesToken = new InjectionToken('errorMessages'); export const widgetTitlePanelToken = new InjectionToken>('widgetTitlePanel'); +export const widgetHeaderButtonActionToken = new InjectionToken>('widgetHeaderButtonAction'); export interface IDynamicWidgetComponent { readonly ctx: WidgetContext; From 896a7f0b454a71bca3c9f0568c6121a50076725e Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 27 Mar 2025 12:30:10 +0200 Subject: [PATCH 11/14] UI[Map]: Fix help popover styles in settings; make popover body scrollable --- .../common/action/custom-action-pretty-editor.component.html | 3 ++- .../action/custom-action-pretty-resources-tabs.component.html | 3 ++- .../lib/settings/common/action/widget-action.component.html | 1 + .../common/map/data-layer-color-settings-panel.component.html | 3 ++- .../common/map/data-layer-color-settings-panel.component.scss | 1 + .../common/map/data-layer-pattern-settings.component.html | 3 ++- .../common/map/marker-clustering-settings.component.html | 3 ++- .../common/map/marker-image-settings-panel.component.scss | 1 + .../settings/common/map/trip-timeline-settings.component.html | 3 ++- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 10 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.html index abcc4ad7af..3d2e69e210 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-editor.component.html @@ -60,7 +60,8 @@ [validationArgs]="[]" [editorCompleter]="customPrettyActionEditorCompleter" functionTitle="{{ 'widget-action.custom-pretty-function' | translate }}" - [helpId]="helpId"> + [helpId]="helpId" + [helpPopupStyle]="{width: '900px'}"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.html index 0852e7cc0d..00c5f86dd3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/custom-action-pretty-resources-tabs.component.html @@ -101,7 +101,8 @@ [validationArgs]="[]" [editorCompleter]="customPrettyActionEditorCompleter" functionTitle="{{ 'widget-action.custom-pretty-function' | translate }}" - [helpId]="helpId"> + [helpId]="helpId" + [helpPopupStyle]="{width: '900px'}"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.html index c4c90067dd..a2a0e8c8fa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.html @@ -256,6 +256,7 @@ [editorCompleter]="customActionEditorCompleter" withModules helpId="widget/action/custom_action_fn" + [helpPopupStyle]="{width: '900px'}" > diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html index 51cbc572a5..281f20ccd4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html @@ -95,7 +95,8 @@ [functionArgs]="['data', 'dsData']" [globalVariables]="functionScopeVariables" functionTitle="{{ 'widgets.maps.data-layer.color-function' | translate }}" - [helpId]="helpId"> + [helpId]="helpId" + [helpPopupStyle]="{width: '900px'}"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.scss index 47ab07639b..4d5a14283d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.scss @@ -43,6 +43,7 @@ display: flex; flex-direction: column; min-height: 0; + overflow: auto; } .tb-data-layer-color-settings-panel-buttons { height: 40px; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html index 93ec63c128..451d3f7282 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html @@ -46,7 +46,8 @@ [globalVariables]="functionScopeVariables" [functionArgs]="['data', 'dsData']" functionTitle="{{ (patternType === 'label' ? 'widgets.maps.data-layer.label-function' : 'widgets.maps.data-layer.tooltip-function') | translate }}" - [helpId]="helpId"> + [helpId]="helpId" + [helpPopupStyle]="{width: '900px'}">
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.html index 2a85f8d514..346e5feed6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.html @@ -88,7 +88,8 @@ [globalVariables]="functionScopeVariables" [functionArgs]="['data', 'childCount']" functionTitle="{{ 'widgets.maps.data-layer.marker.clustering.marker-color-function' | translate }}" - helpId="widget/lib/map/clustering_color_fn"> + helpId="widget/lib/map/clustering_color_fn" + [helpPopupStyle]="{width: '900px'}"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.scss index 9a53a50729..3d93bf7ad7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.scss @@ -41,6 +41,7 @@ display: flex; flex-direction: column; min-height: 0; + overflow: auto; } .tb-marker-image-settings-panel-buttons { height: 40px; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.html index 9729c3559d..55b17fce93 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.html @@ -70,7 +70,8 @@ [globalVariables]="functionScopeVariables" [functionArgs]="['data', 'dsData']" functionTitle="{{ 'widgets.maps.timeline.location-snap-filter-function' | translate }}" - helpId="widget/lib/map/trip_point_as_anchor_fn"> + helpId="widget/lib/map/trip_point_as_anchor_fn" + [helpPopupStyle]="{width: '900px'}"> 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 1c972fe1c0..1b986b1be2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -8013,7 +8013,7 @@ "pattern-type-function": "Function", "label-pattern": "Label (pattern examples: '${entityName}', '${entityName}: (Text ${keyName} units.)' )", "label-function": "Label function", - "tooltip-pattern": "Tooltip (for ex. 'Text ${keyName} units.' or Link text')", + "tooltip-pattern": "Tooltip (for ex. 'Text ${keyName} units.' or Link text)", "tooltip-function": "Tooltip function", "tooltip-trigger": "Tooltip trigger", "tooltip-trigger-click": "Show tooltip on click", From d527213dc63b5e89ca01a944d077988330e6913c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 27 Mar 2025 12:48:54 +0200 Subject: [PATCH 12/14] Fixed minor change detection bug --- .../entity/debug/entity-debug-settings-button.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts index 85a90aef63..90beed2f7e 100644 --- a/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts +++ b/ui-ngx/src/app/modules/home/components/entity/debug/entity-debug-settings-button.component.ts @@ -153,5 +153,6 @@ export class EntityDebugSettingsButtonComponent implements ControlValueAccessor } else { this.debugSettingsFormGroup.enable({emitEvent: false}); } + this.cd.markForCheck(); } } From 1901808b26ab5660712fd41a1798065925780e2a Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 27 Mar 2025 18:04:16 +0200 Subject: [PATCH 13/14] UI: Ref after review --- .../json/system/widget_types/image_map.json | 4 ++-- .../data/json/system/widget_types/map.json | 4 ++-- .../json/system/widget_types/route_map.json | 4 ++-- .../json/system/widget_types/trip_map.json | 4 ++-- .../widget/dynamic-widget.component.ts | 3 +-- .../widget/lib/maps/map-widget.component.html | 12 ++++++++---- .../widget/lib/maps/map-widget.component.scss | 3 +++ .../widget/lib/maps/map-widget.component.ts | 18 +----------------- .../widget/widget-component.service.ts | 3 +++ .../widget/widget-container.component.html | 10 +++++----- .../widget/widget-container.component.ts | 7 +++++++ .../home/components/widget/widget.component.ts | 8 ++------ .../home/models/widget-component.models.ts | 2 +- ui-ngx/src/app/shared/models/widget.models.ts | 1 + 14 files changed, 40 insertions(+), 43 deletions(-) diff --git a/application/src/main/data/json/system/widget_types/image_map.json b/application/src/main/data/json/system/widget_types/image_map.json index 2a4fe71696..991c0b463f 100644 --- a/application/src/main/data/json/system/widget_types/image_map.json +++ b/application/src/main/data/json/system/widget_types/image_map.json @@ -9,9 +9,9 @@ "sizeX": 8.5, "sizeY": 6, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n", "settingsForm": [], "dataKeySettingsForm": [], "settingsDirective": "tb-map-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/map.json b/application/src/main/data/json/system/widget_types/map.json index b9069d8af6..e498922d36 100644 --- a/application/src/main/data/json/system/widget_types/map.json +++ b/application/src/main/data/json/system/widget_types/map.json @@ -9,9 +9,9 @@ "sizeX": 8.5, "sizeY": 6, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}\n", "settingsForm": [], "dataKeySettingsForm": [], "settingsDirective": "tb-map-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/route_map.json b/application/src/main/data/json/system/widget_types/route_map.json index f1d2cd571c..37346f1157 100644 --- a/application/src/main/data/json/system/widget_types/route_map.json +++ b/application/src/main/data/json/system/widget_types/route_map.json @@ -9,9 +9,9 @@ "sizeX": 8.5, "sizeY": 6, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}", "settingsForm": [], "dataKeySettingsForm": [], "latestDataKeySettingsForm": [], diff --git a/application/src/main/data/json/system/widget_types/trip_map.json b/application/src/main/data/json/system/widget_types/trip_map.json index a596e74c1f..8f54f64b6b 100644 --- a/application/src/main/data/json/system/widget_types/trip_map.json +++ b/application/src/main/data/json/system/widget_types/trip_map.json @@ -9,9 +9,9 @@ "sizeX": 8.5, "sizeY": 6, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n trip: true,\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n datasourcesOptional: true,\n additionalWidgetActionTypes: ['placeMapItem']\n };\n}", "settingsForm": [], "dataKeySettingsForm": [], "latestDataKeySettingsForm": [], diff --git a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts index a0b6f07647..b6919ec670 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts @@ -19,7 +19,7 @@ import { Directive, inject, Injector, OnDestroy, OnInit } from '@angular/core'; import { IDynamicWidgetComponent, widgetContextToken, - widgetErrorMessagesToken, widgetHeaderButtonActionToken, + widgetErrorMessagesToken, widgetTitlePanelToken } from '@home/models/widget-component.models'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; @@ -72,7 +72,6 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid public readonly ctx = inject(widgetContextToken); public readonly errorMessages = inject(widgetErrorMessagesToken); public readonly widgetTitlePanel = inject(widgetTitlePanelToken); - public readonly widgetHeaderButtonAction = inject(widgetHeaderButtonActionToken); constructor() { super(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html index 9a200ef88c..e64ee71170 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.html @@ -17,10 +17,14 @@ -->
- - - - + @if (widgetComponent.dashboardWidget.showWidgetTitlePanel) { +
+ + +
+ } @else { + + }
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss index b8167ff06e..eab92a664f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.scss @@ -34,6 +34,9 @@ div.tb-widget-title { padding: 0; } + .tb-widget-title-row .tb-widget-actions { + margin: 0; + } .tb-widget-actions.tb-widget-actions-absolute { z-index: 2; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts index 4bb2b11dd3..4ef3c3cd45 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts @@ -15,14 +15,12 @@ /// import { - AfterViewInit, ChangeDetectorRef, Component, ElementRef, Input, OnDestroy, OnInit, - TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; @@ -46,7 +44,7 @@ import { DomSanitizer } from '@angular/platform-browser'; styleUrls: ['./map-widget.component.scss'], encapsulation: ViewEncapsulation.None }) -export class MapWidgetComponent implements OnInit, OnDestroy, AfterViewInit { +export class MapWidgetComponent implements OnInit, OnDestroy { @ViewChild('mapElement', {static: false}) mapElement: ElementRef; @@ -56,12 +54,6 @@ export class MapWidgetComponent implements OnInit, OnDestroy, AfterViewInit { @Input() ctx: WidgetContext; - @Input() - widgetTitlePanel: TemplateRef; - - @Input() - widgetHeaderButtonAction: TemplateRef; - backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; padding: string; @@ -83,14 +75,6 @@ export class MapWidgetComponent implements OnInit, OnDestroy, AfterViewInit { this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; } - ngAfterViewInit() { - if (this.widgetComponent.dashboardWidget.showWidgetTitlePanel && !!this.widgetHeaderButtonAction) { - const tbWidgetTitle = $(".tb-widget-title")[0]; - if (getComputedStyle(tbWidgetTitle).getPropertyValue('min-height') === 'auto') - tbWidgetTitle.style.minHeight = $(".tb-widget-actions")[0].offsetHeight + 'px'; - } - } - ngOnDestroy() { if (this.map) { this.map.destroy(); diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 1a397d3a1f..f4e69c954c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -631,6 +631,9 @@ export class WidgetComponentService { if (isUndefined(result.typeParameters.embedTitlePanel)) { result.typeParameters.embedTitlePanel = false; } + if (isUndefined(result.typeParameters.embedActionsPanel)) { + result.typeParameters.embedActionsPanel = false; + } if (isUndefined(result.typeParameters.overflowVisible)) { result.typeParameters.overflowVisible = false; } 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 55182a8a01..531d0e3529 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 @@ -33,8 +33,8 @@ - - + +
@@ -45,7 +45,7 @@ [isPreview]="isPreview" [isMobile]="isMobile" [widgetTitlePanel]="widgetTitlePanel" - [widgetHeaderButtonAction]="widgetHeaderButtonAction"> + [widgetHeaderActionsPanel]="widgetHeaderActionsPanel">
@@ -79,10 +79,10 @@ - +
@for (action of widget.customHeaderActions; track action.name; let last = $last) { 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 430cce40b1..51ed592e7e 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 @@ -48,6 +48,7 @@ import { TbContextMenuEvent } from '@shared/models/jquery-event.models'; import { WidgetHeaderActionButtonType } from '@shared/models/widget.models'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; import ITooltipsterGeoHelper = JQueryTooltipster.ITooltipsterGeoHelper; +import { WidgetComponent } from '@home/components/widget/widget.component'; export enum WidgetComponentActionType { MOUSE_DOWN, @@ -216,6 +217,12 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O }); } + widgetActionAbsolute(widgetComponent: WidgetComponent, absolute = false) { + return absolute ? true : + !(this.widget.showWidgetTitlePanel && !widgetComponent.widgetContext?.embedTitlePanel && + (this.widget.showTitle||this.widget.hasAggregation)) && !widgetComponent.widgetContext?.embedActionsPanel; + } + onClicked(event: MouseEvent): void { if (event && this.isEdit) { event.stopPropagation(); diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index 5b5bb2fe57..73f90d9665 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -75,7 +75,6 @@ import { widgetContextToken, widgetErrorMessagesToken, WidgetHeaderAction, - widgetHeaderButtonActionToken, WidgetInfo, widgetTitlePanelToken, WidgetTypeInstance @@ -141,7 +140,7 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, widgetTitlePanel: TemplateRef; @Input() - widgetHeaderButtonAction: TemplateRef; + widgetHeaderActionsPanel: TemplateRef; @Input() isEdit: boolean; @@ -487,6 +486,7 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, this.widgetType = this.widgetInfo.widgetTypeFunction; this.typeParameters = this.widgetInfo.typeParameters; this.widgetContext.embedTitlePanel = this.typeParameters.embedTitlePanel; + this.widgetContext.embedActionsPanel = this.typeParameters.embedActionsPanel; this.widgetContext.overflowVisible = this.typeParameters.overflowVisible; if (!this.widgetType) { @@ -821,10 +821,6 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges, { provide: widgetTitlePanelToken, useValue: this.widgetTitlePanel - }, - { - provide: widgetHeaderButtonActionToken, - useValue: this.widgetHeaderButtonAction } ], parent: this.injector diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index a27f1727c5..00afa2b68d 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -312,6 +312,7 @@ export class WidgetContext { timeWindow?: WidgetTimewindow; embedTitlePanel?: boolean; + embedActionsPanel?: boolean; overflowVisible?: boolean; hideTitlePanel = false; @@ -559,7 +560,6 @@ export class LabelVariablePattern { export const widgetContextToken = new InjectionToken('widgetContext'); export const widgetErrorMessagesToken = new InjectionToken('errorMessages'); export const widgetTitlePanelToken = new InjectionToken>('widgetTitlePanel'); -export const widgetHeaderButtonActionToken = new InjectionToken>('widgetHeaderButtonAction'); export interface IDynamicWidgetComponent { readonly ctx: WidgetContext; diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 2300ae2341..038c738bb0 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -185,6 +185,7 @@ export interface WidgetTypeParameters { previewWidth?: string; previewHeight?: string; embedTitlePanel?: boolean; + embedActionsPanel?: boolean; overflowVisible?: boolean; hideDataTab?: boolean; hideDataSettings?: boolean; From 7f438da69b1c6251b90e8cd7307961ef168708c4 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 28 Mar 2025 11:23:00 +0200 Subject: [PATCH 14/14] UI: Embed action for chart widgets --- .../main/data/json/system/widget_types/bar_chart.json | 4 ++-- .../system/widget_types/bar_chart_with_labels.json | 4 ++-- .../src/main/data/json/system/widget_types/bars.json | 4 ++-- .../main/data/json/system/widget_types/doughnut.json | 4 ++-- .../json/system/widget_types/horizontal_doughnut.json | 4 ++-- .../data/json/system/widget_types/line_chart.json | 4 ++-- .../src/main/data/json/system/widget_types/pie.json | 4 ++-- .../data/json/system/widget_types/point_chart.json | 4 ++-- .../data/json/system/widget_types/polar_area.json | 4 ++-- .../src/main/data/json/system/widget_types/radar.json | 4 ++-- .../data/json/system/widget_types/range_chart.json | 4 ++-- .../data/json/system/widget_types/state_chart.json | 4 ++-- .../json/system/widget_types/time_series_chart.json | 4 ++-- .../chart/bar-chart-with-labels-widget.component.html | 9 ++++++++- .../chart/bar-chart-with-labels-widget.component.scss | 7 +++++++ .../chart/bar-chart-with-labels-widget.component.ts | 7 +++---- .../lib/chart/latest-chart-widget.component.html | 1 - .../widget/lib/chart/latest-chart.component.html | 9 ++++++++- .../widget/lib/chart/latest-chart.component.scss | 7 +++++++ .../widget/lib/chart/latest-chart.component.ts | 7 ++----- .../lib/chart/range-chart-widget.component.html | 9 ++++++++- .../lib/chart/range-chart-widget.component.scss | 6 ++++++ .../widget/lib/chart/range-chart-widget.component.ts | 7 +++---- .../lib/chart/time-series-chart-widget.component.html | 11 ++++++++--- .../lib/chart/time-series-chart-widget.component.scss | 6 ++++++ .../lib/chart/time-series-chart-widget.component.ts | 3 --- 26 files changed, 92 insertions(+), 49 deletions(-) diff --git a/application/src/main/data/json/system/widget_types/bar_chart.json b/application/src/main/data/json/system/widget_types/bar_chart.json index 01f16d96b5..58f6244fd3 100644 --- a/application/src/main/data/json/system/widget_types/bar_chart.json +++ b/application/src/main/data/json/system/widget_types/bar_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'bar',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('bar'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'bar',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('bar'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json b/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json index a2fc5f5c9d..6972e859b0 100644 --- a/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json +++ b/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'humidity', label: 'Humidity', type: 'timeseries' }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'humidity', label: 'Humidity', type: 'timeseries' }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/bars.json b/application/src/main/data/json/system/widget_types/bars.json index 481288da9b..ce640c95b1 100644 --- a/application/src/main/data/json/system/widget_types/bars.json +++ b/application/src/main/data/json/system/widget_types/bars.json @@ -9,9 +9,9 @@ "sizeX": 5, "sizeY": 4, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.barChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.barChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-bar-chart-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/doughnut.json b/application/src/main/data/json/system/widget_types/doughnut.json index 5065100a91..bf03a75b09 100644 --- a/application/src/main/data/json/system/widget_types/doughnut.json +++ b/application/src/main/data/json/system/widget_types/doughnut.json @@ -9,9 +9,9 @@ "sizeX": 4, "sizeY": 3, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '300px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '300px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-doughnut-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/horizontal_doughnut.json b/application/src/main/data/json/system/widget_types/horizontal_doughnut.json index a6e7f4d3bd..050984268c 100644 --- a/application/src/main/data/json/system/widget_types/horizontal_doughnut.json +++ b/application/src/main/data/json/system/widget_types/horizontal_doughnut.json @@ -9,9 +9,9 @@ "sizeX": 4, "sizeY": 2.5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '220px',\n embedTitlePanel: true,\n horizontal: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.doughnutWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.doughnutWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '380px',\n previewHeight: '220px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n horizontal: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind power', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar power', type: 'timeseries', color: '#FF4D5A' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-doughnut-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/line_chart.json b/application/src/main/data/json/system/widget_types/line_chart.json index 3ef1b83c03..0468c42f8e 100644 --- a/application/src/main/data/json/system/widget_types/line_chart.json +++ b/application/src/main/data/json/system/widget_types/line_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'line',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('line'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'line',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('line'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/pie.json b/application/src/main/data/json/system/widget_types/pie.json index 01c96a5077..94e02d06ef 100644 --- a/application/src/main/data/json/system/widget_types/pie.json +++ b/application/src/main/data/json/system/widget_types/pie.json @@ -9,9 +9,9 @@ "sizeX": 5, "sizeY": 4, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.pieChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.pieChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.pieChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.pieChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-pie-chart-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/point_chart.json b/application/src/main/data/json/system/widget_types/point_chart.json index a3f1ed5f60..74cd137665 100644 --- a/application/src/main/data/json/system/widget_types/point_chart.json +++ b/application/src/main/data/json/system/widget_types/point_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'point',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('point'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'point',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('point'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/polar_area.json b/application/src/main/data/json/system/widget_types/polar_area.json index 2bdce5d9ad..36fcaee465 100644 --- a/application/src/main/data/json/system/widget_types/polar_area.json +++ b/application/src/main/data/json/system/widget_types/polar_area.json @@ -9,9 +9,9 @@ "sizeX": 5, "sizeY": 4, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.polarAreaChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.polarAreaChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.polarAreaChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.polarAreaChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-polar-area-chart-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/radar.json b/application/src/main/data/json/system/widget_types/radar.json index 07b0fa6981..a6961feb6d 100644 --- a/application/src/main/data/json/system/widget_types/radar.json +++ b/application/src/main/data/json/system/widget_types/radar.json @@ -9,9 +9,9 @@ "sizeX": 5, "sizeY": 4, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.radarChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.radarChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.radarChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.radarChartWidget.onDataUpdated();\n};\n\nself.typeParameters = function() {\n return {\n previewWidth: '500px',\n previewHeight: '380px',\n embedTitlePanel: true,\n embedActionsPanel: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'windPower', label: 'Wind', type: 'timeseries', color: '#08872B' },\n { name: 'solarPower', label: 'Solar', type: 'timeseries', color: '#FF4D5A' },\n { name: 'hydroelectricPower', label: 'Hydroelectric', type: 'timeseries', color: '#FFDE30' }];\n }\n };\n};\n\nself.onDestroy = function() {\n};\n\n", "settingsSchema": "", "dataKeySettingsSchema": "", "settingsDirective": "tb-radar-chart-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/range_chart.json b/application/src/main/data/json/system/widget_types/range_chart.json index ea5109873b..911d91876f 100644 --- a/application/src/main/data/json/system/widget_types/range_chart.json +++ b/application/src/main/data/json/system/widget_types/range_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.rangeChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.rangeChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries' }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.rangeChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.rangeChartWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: false,\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries' }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/state_chart.json b/application/src/main/data/json/system/widget_types/state_chart.json index ea65f55b43..d2a3031318 100644 --- a/application/src/main/data/json/system/widget_types/state_chart.json +++ b/application/src/main/data/json/system/widget_types/state_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n chartType: 'state',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('state'),\n defaultDataKeysFunction: function() {\n return [{ name: 'state', label: 'State', type: 'timeseries', units: '', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n chartType: 'state',\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('state'),\n defaultDataKeysFunction: function() {\n return [{ name: 'state', label: 'State', type: 'timeseries', units: '', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/application/src/main/data/json/system/widget_types/time_series_chart.json b/application/src/main/data/json/system/widget_types/time_series_chart.json index 449fffd11b..d61472b6f9 100644 --- a/application/src/main/data/json/system/widget_types/time_series_chart.json +++ b/application/src/main/data/json/system/widget_types/time_series_chart.json @@ -9,9 +9,9 @@ "sizeX": 8, "sizeY": 5, "resources": [], - "templateHtml": "\n", + "templateHtml": "\n", "templateCss": "", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n embedActionsPanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html index 8833b60cfe..0e0170c603 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html @@ -17,7 +17,14 @@ -->
- + @if (widgetComponent.dashboardWidget.showWidgetTitlePanel) { +
+ + +
+ } @else { + + }
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss index 3c584b7fb8..76cae3cf24 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss @@ -104,4 +104,11 @@ } } } + + .tb-widget-title-row .tb-widget-actions { + margin: 0; + } + .tb-widget-actions.tb-widget-actions-absolute { + z-index: 2; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts index 51be4a70bf..746daf43b3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts @@ -40,6 +40,7 @@ import { } from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models'; import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart'; import { DataKey } from '@shared/models/widget.models'; +import { WidgetComponent } from '@home/components/widget/widget.component'; @Component({ selector: 'tb-bar-chart-with-labels-widget', @@ -57,9 +58,6 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft @Input() ctx: WidgetContext; - @Input() - widgetTitlePanel: TemplateRef; - showLegend: boolean; legendClass: string; @@ -73,7 +71,8 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft private timeSeriesChart: TbTimeSeriesChart; - constructor(private imagePipe: ImagePipe, + constructor(public widgetComponent: WidgetComponent, + private imagePipe: ImagePipe, private sanitizer: DomSanitizer, private renderer: Renderer2, private cd: ChangeDetectorRef) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart-widget.component.html index 7f7fb47389..8e90ab8fb6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart-widget.component.html @@ -19,6 +19,5 @@ #latestChart [ctx]="ctx" [settings]="settings" - [widgetTitlePanel]="widgetTitlePanel" [callbacks]="callbacks" > diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.html index 578f7fdf4b..20cfdf4623 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.html @@ -17,7 +17,14 @@ -->
- + @if (widgetComponent.dashboardWidget.showWidgetTitlePanel) { +
+ + +
+ } @else { + + }
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.scss index 3566820c8d..2eb0ceb940 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.scss @@ -106,4 +106,11 @@ } } } + + .tb-widget-title-row .tb-widget-actions { + margin: 0; + } + .tb-widget-actions.tb-widget-actions-absolute { + z-index: 2; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts index 651240342c..85905dfd3e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/latest-chart.component.ts @@ -68,9 +68,6 @@ export class LatestChartComponent implements OnInit, OnDestroy, AfterViewInit { @Input() ctx: WidgetContext; - @Input() - widgetTitlePanel: TemplateRef; - @Input() callbacks: LatestChartComponentCallbacks; @@ -98,9 +95,9 @@ export class LatestChartComponent implements OnInit, OnDestroy, AfterViewInit { private latestChart: TbLatestChart; - constructor(private imagePipe: ImagePipe, + constructor(public widgetComponent: WidgetComponent, + private imagePipe: ImagePipe, private sanitizer: DomSanitizer, - private widgetComponent: WidgetComponent, private renderer: Renderer2, private translate: TranslateService, private cd: ChangeDetectorRef) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.html index 8880503eb5..39112c484b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.html @@ -17,7 +17,14 @@ -->
- + @if (widgetComponent.dashboardWidget.showWidgetTitlePanel) { +
+ + +
+ } @else { + + }
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss index 6f4b21a78d..ff339362a1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.scss @@ -104,4 +104,10 @@ } } } + .tb-widget-title-row .tb-widget-actions { + margin: 0; + } + .tb-widget-actions.tb-widget-actions-absolute { + z-index: 2; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts index eacbb883a4..0201ec7d5f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts @@ -48,6 +48,7 @@ import { Observable } from 'rxjs'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart'; +import { WidgetComponent } from '@home/components/widget/widget.component'; @Component({ selector: 'tb-range-chart-widget', @@ -65,9 +66,6 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn @Input() ctx: WidgetContext; - @Input() - widgetTitlePanel: TemplateRef; - showLegend: boolean; legendClass: string; @@ -86,7 +84,8 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn private timeSeriesChart: TbTimeSeriesChart; - constructor(private imagePipe: ImagePipe, + constructor(public widgetComponent: WidgetComponent, + private imagePipe: ImagePipe, private sanitizer: DomSanitizer, private renderer: Renderer2, private cd: ChangeDetectorRef) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html index 1ba501674e..1efcf30781 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html @@ -17,9 +17,14 @@ -->
- - - + @if (widgetComponent.dashboardWidget.showWidgetTitlePanel) { +
+ + +
+ } @else { + + }
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss index f500d3009b..37067ef935 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss @@ -156,4 +156,10 @@ $maxLegendHeight: 35%; } } } + .tb-widget-title-row .tb-widget-actions { + margin: 0; + } + .tb-widget-actions.tb-widget-actions-absolute { + z-index: 2; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts index 2e9f297b4a..2fd12b1b98 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts @@ -61,9 +61,6 @@ export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterV @Input() ctx: WidgetContext; - @Input() - widgetTitlePanel: TemplateRef; - horizontalLegendPosition = false; showLegend: boolean;