Browse Source

Merge remote-tracking branch 'maks/gateway-list' into gateway-list

pull/8337/head
imbeacon 3 years ago
parent
commit
617c2abe7b
  1. 2
      application/src/main/data/json/demo/dashboards/gateway_list.json
  2. 5
      ui-ngx/src/app/core/services/dialog.service.ts
  3. 26
      ui-ngx/src/app/core/services/utils.service.ts
  4. 22
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html
  5. 29
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.scss
  6. 7
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts
  7. 22
      ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html
  8. 10
      ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts
  9. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts
  10. 22
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.html
  11. 10
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.ts
  12. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts
  13. 22
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.html
  14. 10
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts
  15. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts
  16. 22
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.html
  17. 10
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts
  18. 7
      ui-ngx/src/app/modules/home/components/widget/config/widget-config-components.module.ts
  19. 15
      ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts
  20. 2
      ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts
  21. 2
      ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts
  22. 4
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss
  23. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts
  24. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts
  25. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts
  26. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts
  27. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts
  28. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.html
  29. 7
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts
  30. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts
  31. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts
  32. 16
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.html
  33. 43
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts
  34. 14
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts
  35. 84
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts
  36. 54
      ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts
  37. 20
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  38. 8
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
  39. 13
      ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
  40. 30
      ui-ngx/src/app/shared/components/color-input.component.ts
  41. 8
      ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html
  42. 9
      ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts
  43. 1
      ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html
  44. 3
      ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts
  45. 1
      ui-ngx/src/app/shared/models/public-api.ts
  46. 29
      ui-ngx/src/app/shared/models/widget-settings.models.ts
  47. 7
      ui-ngx/src/app/shared/models/widget.models.ts
  48. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  49. 2
      ui-ngx/src/form.scss

2
application/src/main/data/json/demo/dashboards/gateway_list.json

@ -231,7 +231,7 @@
"type": "customPretty",
"customHtml": "<form #addEntityForm=\"ngForm\" [formGroup]=\"addEntityFormGroup\"\r\n (ngSubmit)=\"save()\" class=\"add-entity-form\">\r\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\r\n <h2>Add gateway</h2>\r\n <span fxFlex></span>\r\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\r\n <mat-icon class=\"material-icons\">close</mat-icon>\r\n </button>\r\n </mat-toolbar>\r\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\r\n </mat-progress-bar>\r\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\r\n <div mat-dialog-content fxLayout=\"column\">\r\n <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayout.xs=\"column\" fxLayoutGap.xs=\"0\">\r\n <mat-form-field fxFlex class=\"mat-block\">\r\n <mat-label>Name</mat-label>\r\n <input matInput formControlName=\"entityName\" required>\r\n <mat-error *ngIf=\"addEntityFormGroup.get('entityName').hasError('required')\">\r\n Gateway name is required.\r\n </mat-error>\r\n </mat-form-field>\r\n </div>\r\n <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayout.xs=\"column\" fxLayoutGap.xs=\"0\">\r\n <tb-entity-subtype-autocomplete\r\n fxFlex\r\n class=\"mat-block\"\r\n formControlName=\"type\"\r\n [required]=\"true\"\r\n [entityType]=\"'DEVICE'\"\r\n ></tb-entity-subtype-autocomplete>\r\n </div>\r\n </div>\r\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\r\n <button mat-button color=\"primary\"\r\n type=\"button\"\r\n [disabled]=\"(isLoading$ | async)\"\r\n (click)=\"cancel()\" cdkFocusInitial>\r\n Cancel\r\n </button>\r\n <button mat-button mat-raised-button color=\"primary\"\r\n type=\"submit\"\r\n [disabled]=\"(isLoading$ | async) || addEntityForm.invalid || !addEntityForm.dirty\">\r\n Create\r\n </button>\r\n </div>\r\n</form>\r\n",
"customCss": ".add-entity-form {\r\n min-width: 400px !important;\r\n}\r\n\r\n.add-entity-form .boolean-value-input {\r\n padding-left: 5px;\r\n}\r\n\r\n.add-entity-form .boolean-value-input .checkbox-label {\r\n margin-bottom: 8px;\r\n color: rgba(0,0,0,0.54);\r\n font-size: 12px;\r\n}\r\n\r\n.relations-list .header {\r\n padding-right: 5px;\r\n padding-bottom: 5px;\r\n padding-left: 5px;\r\n}\r\n\r\n.relations-list .header .cell {\r\n padding-right: 5px;\r\n padding-left: 5px;\r\n font-size: 12px;\r\n font-weight: 700;\r\n color: rgba(0, 0, 0, .54);\r\n white-space: nowrap;\r\n}\r\n\r\n.relations-list .mat-form-field-infix {\r\n width: auto !important;\r\n}\r\n\r\n.relations-list .body {\r\n padding-right: 5px;\r\n padding-bottom: 15px;\r\n padding-left: 5px;\r\n}\r\n\r\n.relations-list .body .row {\r\n padding-top: 5px;\r\n}\r\n\r\n.relations-list .body .cell {\r\n padding-right: 5px;\r\n padding-left: 5px;\r\n}\r\n\r\n.relations-list .body .md-button {\r\n margin: 0;\r\n}\r\n\r\n",
"customFunction": "let $injector = widgetContext.$scope.$injector;\r\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\r\nlet assetService = $injector.get(widgetContext.servicesMap.get('assetService'));\r\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\r\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\r\nlet entityRelationService = $injector.get(widgetContext.servicesMap.get('entityRelationService'));\r\n\r\nopenAddEntityDialog();\r\n\r\nfunction openAddEntityDialog() {\r\n customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\r\n}\r\n\r\nfunction AddEntityDialogController(instance) {\r\n let vm = instance;\r\n\r\n vm.addEntityFormGroup = vm.fb.group({\r\n entityName: ['', [vm.validators.required]],\r\n entityType: ['DEVICE'],\r\n entityLabel: [''],\r\n type: ['', [vm.validators.required]],\r\n });\r\n\r\n vm.cancel = function() {\r\n vm.dialogRef.close(null);\r\n };\r\n\r\n\r\n vm.save = function() {\r\n vm.addEntityFormGroup.markAsPristine();\r\n saveEntityObservable().subscribe(\r\n function (device) {\r\n widgetContext.updateAliases();\r\n vm.dialogRef.close(null);\r\n goToConfigState(device);\r\n }\r\n );\r\n };\r\n \r\n function goToConfigState(device) {\r\n const stateParams = {};\r\n stateParams.entityId = device.id;\r\n stateParams.entityName = device.name;\r\n const newStateParams = {\r\n targetEntityParamName: 'default',\r\n new_gateway: {\r\n entityId: device.id,\r\n entityName: device.name\r\n }\r\n }\r\n const params = {...stateParams, ...newStateParams};\r\n widgetContext.stateController.openState('gateway_details', params, false);\r\n }\r\n\r\n function saveEntityObservable() {\r\n const formValues = vm.addEntityFormGroup.value;\r\n let entity = {\r\n name: formValues.entityName,\r\n type: formValues.type,\r\n label: formValues.entityLabel,\r\n additionalInfo: {\r\n gateway: true\r\n }\r\n };\r\n return deviceService.saveDevice(entity);\r\n }\r\n}\r\n",
"customFunction": "let $injector = widgetContext.$scope.$injector;\r\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\r\nlet assetService = $injector.get(widgetContext.servicesMap.get('assetService'));\r\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\r\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\r\nlet entityRelationService = $injector.get(widgetContext.servicesMap.get('entityRelationService'));\r\nlet userSettingsService = $injector.get(widgetContext.servicesMap.get('userSettingsService'));\r\n\r\nopenAddEntityDialog();\r\n\r\nfunction openAddEntityDialog() {\r\n customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\r\n}\r\n\r\nfunction AddEntityDialogController(instance) {\r\n let vm = instance;\r\n let userSettings;\r\n userSettingsService.loadUserSettings().subscribe(settings=> {\r\n userSettings = settings;\r\n if (!userSettings.createdGatewaysCount) userSettings.createdGatewaysCount = 0;\r\n });\r\n \r\n\r\n vm.addEntityFormGroup = vm.fb.group({\r\n entityName: ['', [vm.validators.required]],\r\n entityType: ['DEVICE'],\r\n entityLabel: [''],\r\n type: ['', [vm.validators.required]],\r\n });\r\n\r\n vm.cancel = function() {\r\n vm.dialogRef.close(null);\r\n };\r\n\r\n\r\n vm.save = function() {\r\n vm.addEntityFormGroup.markAsPristine();\r\n saveEntityObservable().subscribe(\r\n function (device) {\r\n widgetContext.updateAliases();\r\n userSettingsService.putUserSettings({ createdGatewaysCount: ++userSettings.createdGatewaysCount }).subscribe(_=>{\r\n });\r\n vm.dialogRef.close(null);\r\n goToConfigState(device);\r\n }\r\n );\r\n };\r\n \r\n function goToConfigState(device) {\r\n const stateParams = {};\r\n stateParams.entityId = device.id;\r\n stateParams.entityName = device.name;\r\n const newStateParams = {\r\n targetEntityParamName: 'default',\r\n new_gateway: {\r\n entityId: device.id,\r\n entityName: device.name\r\n }\r\n }\r\n const params = {...stateParams, ...newStateParams};\r\n widgetContext.stateController.openState('gateway_details', params, false);\r\n }\r\n\r\n function saveEntityObservable() {\r\n const formValues = vm.addEntityFormGroup.value;\r\n let entity = {\r\n name: formValues.entityName,\r\n type: formValues.type,\r\n label: formValues.entityLabel,\r\n additionalInfo: {\r\n gateway: true\r\n }\r\n };\r\n return deviceService.saveDevice(entity);\r\n }\r\n}\r\n",
"customResources": [],
"openInSeparateDialog": false,
"openInPopover": false,

5
ui-ngx/src/app/core/services/dialog.service.ts

@ -96,13 +96,14 @@ export class DialogService {
return dialogRef.afterClosed();
}
colorPicker(color: string): Observable<string> {
colorPicker(color: string, colorClearButton = false): Observable<string> {
return this.dialog.open<ColorPickerDialogComponent, ColorPickerDialogData, string>(ColorPickerDialogComponent,
{
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
color
color,
colorClearButton
},
autoFocus: false
}).afterClosed();

26
ui-ngx/src/app/core/services/utils.service.ts

@ -17,7 +17,7 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../../../../src/typings/rawloader.typings.d.ts" />
import { Inject, Injectable, NgZone } from '@angular/core';
import { ElementRef, Inject, Injectable, NgZone } from '@angular/core';
import { WINDOW } from '@core/services/window.service';
import { ExceptionData } from '@app/shared/models/error.models';
import {
@ -45,7 +45,7 @@ import { alarmFields, alarmSeverityTranslations, alarmStatusTranslations } from
import { materialColors } from '@app/shared/models/material.models';
import { WidgetInfo } from '@home/models/widget-component.models';
import jsonSchemaDefaults from 'json-schema-defaults';
import { Observable } from 'rxjs';
import { fromEvent, Observable, Subscription } from 'rxjs';
import { publishReplay, refCount } from 'rxjs/operators';
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
import {
@ -57,6 +57,8 @@ import {
import { EntityId } from '@shared/models/id/entity-id';
import { DatePipe } from '@angular/common';
import { entityTypeTranslations } from '@shared/models/entity-type.models';
import { OverlayRef } from '@angular/cdk/overlay';
import { ResizeObserver } from '@juggle/resize-observer';
const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g');
@ -528,4 +530,24 @@ export class UtilsService {
return base64toObj(b64Encoded);
}
public updateOverlayMaxHeigth(overlay: OverlayRef, observeElementRef?: ElementRef): Subscription {
const observeElement = observeElementRef ? observeElementRef.nativeElement : overlay.overlayElement.children[0];
const setMaxHeigthOverlay = () => {
const top = observeElement.getBoundingClientRect().top;
const viewport = window.innerHeight;
overlay.updateSize({
maxHeight: viewport - top
});
};
const observer = new ResizeObserver(() => {
setMaxHeigthOverlay();
observer.unobserve(observeElement);
});
observer.observe(observeElement);
return fromEvent(window, 'resize').subscribe(() => setMaxHeigthOverlay());
}
}

22
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html

@ -55,29 +55,28 @@
</form>
</ng-template>
<ng-template #alarmFilter>
<div class="tb-form-panel no-padding no-border" [formGroup]="alarmFilterConfigForm">
<div class="tb-form-row space-between" ngClass.xs="filters-row-mobile">
<div class="fixed-title-width" ngClass.xs="filters-title-mobile" translate>alarm.alarm-status-list</div>
<div class="tb-form-panel tb-alarm-filter-config-component no-padding no-border" [formGroup]="alarmFilterConfigForm">
<div class="tb-form-row space-between column-xs">
<div class="fixed-title-width" translate>alarm.alarm-status-list</div>
<mat-chip-listbox multiple formControlName="statusList">
<mat-chip-option *ngFor="let searchStatus of alarmSearchStatuses" [value]="searchStatus">
{{ alarmSearchStatusTranslationMap.get(searchStatus) | translate }}
</mat-chip-option>
</mat-chip-listbox>
</div>
<div class="tb-form-row space-between" ngClass.xs="filters-row-mobile">
<div class="fixed-title-width" ngClass.xs="filters-title-mobile" translate>alarm.alarm-severity-list</div>
<div class="tb-form-row space-between column-xs">
<div class="fixed-title-width" translate>alarm.alarm-severity-list</div>
<mat-chip-listbox multiple formControlName="severityList">
<mat-chip-option *ngFor="let alarmSeverity of alarmSeverities" [value]="alarmSeverity">
{{ alarmSeverityTranslationMap.get(alarmSeverityEnum[alarmSeverity]) | translate }}
</mat-chip-option>
</mat-chip-listbox>
</div>
<div class="tb-form-row" ngClass.xs="filters-row-mobile">
<div class="fixed-title-width" ngClass.xs="filters-title-mobile" translate>alarm.alarm-type-list</div>
<div class="tb-form-row column-xs">
<div class="fixed-title-width" translate>alarm.alarm-type-list</div>
<mat-form-field fxFlex appearance="outline"
subscriptSizing="dynamic"
class="tb-chips"
ngClass.xs="filters-fields-width-mobile">
class="tb-chips">
<mat-chip-grid #alarmTypeChipList formControlName="typeList">
<mat-chip-row *ngFor="let type of alarmTypeList()"
[removable]="true" (removed)="removeAlarmType(type)">
@ -92,10 +91,9 @@
</mat-chip-grid>
</mat-form-field>
</div>
<div class="tb-form-row" ngClass.xs="filters-row-mobile">
<div class="fixed-title-width" ngClass.xs="filters-title-mobile" translate>alarm.assignee</div>
<div class="tb-form-row column-xs">
<div class="fixed-title-width" translate>alarm.assignee</div>
<tb-alarm-assignee-select fxFlex inline="true"
ngClass.xs="filters-fields-width-mobile"
[userMode]="userMode"
formControlName="assigneeId">
</tb-alarm-assignee-select>

29
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.scss

@ -14,25 +14,11 @@
* limitations under the License.
*/
:host {
display: block;
overflow: scroll;
display: flex;
max-width: 100%;
.mdc-button {
max-width: 100%;
}
.filters-row-mobile {
flex-direction: column;
align-items: start;
border: none;
padding: 0;
}
.filters-title-mobile {
font-size: 14px;
}
.filters-fields-width-mobile {
width: 100%;
}
}
:host ::ng-deep {
@ -45,9 +31,16 @@
text-overflow: ellipsis;
}
}
.mat-mdc-chip {
.mdc-evolution-chip__cell, .mat-mdc-chip-action, .mat-mdc-chip-action-label {
overflow: hidden;
}
::ng-deep {
.tb-alarm-filter-config-component {
flex: 1;
.mat-mdc-chip {
.mdc-evolution-chip__cell, .mat-mdc-chip-action, .mat-mdc-chip-action-label {
overflow: hidden;
}
}
}
}

7
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts

@ -44,6 +44,8 @@ import { MatChipInputEvent } from '@angular/material/chips';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { TranslateService } from '@ngx-translate/core';
import { deepClone } from '@core/utils';
import { Subscription } from 'rxjs';
import { UtilsService } from '@core/services/utils.service';
export const ALARM_FILTER_CONFIG_DATA = new InjectionToken<any>('AlarmFilterConfigData');
@ -114,6 +116,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
panelResult: AlarmFilterConfig = null;
private alarmFilterConfig: AlarmFilterConfig;
private resizeWindows: Subscription;
private propagateChange = (_: any) => {};
@ -125,6 +128,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
private translate: TranslateService,
private overlay: Overlay,
private nativeElement: ElementRef,
private utils: UtilsService,
private viewContainerRef: ViewContainerRef) {
}
@ -213,6 +217,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
});
this.alarmFilterOverlayRef.attach(new TemplatePortal(this.alarmFilterPanel,
this.viewContainerRef));
this.resizeWindows = this.utils.updateOverlayMaxHeigth(this.alarmFilterOverlayRef);
}
cancel() {
@ -220,6 +225,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
if (this.overlayRef) {
this.overlayRef.dispose();
} else {
this.resizeWindows.unsubscribe();
this.alarmFilterOverlayRef.dispose();
}
}
@ -233,6 +239,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
if (this.overlayRef) {
this.overlayRef.dispose();
} else {
this.resizeWindows.unsubscribe();
this.alarmFilterOverlayRef.dispose();
}
}

22
ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html

@ -50,13 +50,24 @@
</tb-data-keys-panel>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row">
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="alarmsTableWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
@ -68,6 +79,7 @@
formControlName="titleIcon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
@ -84,12 +96,14 @@
<div class="tb-form-row space-between">
<div>{{ 'widget-config.text-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="color">
</tb-color-input>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.background-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="backgroundColor">
</tb-color-input>
</div>

10
ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.ts

@ -61,6 +61,8 @@ export class AlarmsTableBasicConfigComponent extends BasicWidgetConfigComponent
columns: [this.getColumns(configData.config.alarmSource), []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.settings?.alarmsTitle, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showTitleIcon: [configData.config.showTitleIcon, []],
titleIcon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
@ -82,6 +84,8 @@ export class AlarmsTableBasicConfigComponent extends BasicWidgetConfigComponent
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.widgetConfig.config.settings.alarmsTitle = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor;
@ -100,6 +104,8 @@ export class AlarmsTableBasicConfigComponent extends BasicWidgetConfigComponent
const showTitleIcon: boolean = this.alarmsTableWidgetConfigForm.get('showTitleIcon').value;
if (showTitle) {
this.alarmsTableWidgetConfigForm.get('title').enable();
this.alarmsTableWidgetConfigForm.get('titleFont').enable();
this.alarmsTableWidgetConfigForm.get('titleColor').enable();
this.alarmsTableWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
if (showTitleIcon) {
this.alarmsTableWidgetConfigForm.get('titleIcon').enable();
@ -110,11 +116,15 @@ export class AlarmsTableBasicConfigComponent extends BasicWidgetConfigComponent
}
} else {
this.alarmsTableWidgetConfigForm.get('title').disable();
this.alarmsTableWidgetConfigForm.get('titleFont').disable();
this.alarmsTableWidgetConfigForm.get('titleColor').disable();
this.alarmsTableWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
this.alarmsTableWidgetConfigForm.get('titleIcon').disable();
this.alarmsTableWidgetConfigForm.get('iconColor').disable();
}
this.alarmsTableWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
this.alarmsTableWidgetConfigForm.get('titleFont').updateValueAndValidity({emitEvent});
this.alarmsTableWidgetConfigForm.get('titleColor').updateValueAndValidity({emitEvent});
this.alarmsTableWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
this.alarmsTableWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
this.alarmsTableWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});

2
ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts

@ -34,7 +34,6 @@ import {
TimeseriesTableBasicConfigComponent
} from '@home/components/widget/config/basic/cards/timeseries-table-basic-config.component';
import { FlotBasicConfigComponent } from '@home/components/widget/config/basic/chart/flot-basic-config.component';
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
import {
AlarmsTableBasicConfigComponent
} from '@home/components/widget/config/basic/alarm/alarms-table-basic-config.component';
@ -57,7 +56,6 @@ import {
imports: [
CommonModule,
SharedModule,
WidgetSettingsModule,
WidgetConfigComponentsModule
],
exports: [

22
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.html

@ -39,13 +39,24 @@
</tb-data-keys-panel>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row">
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="entitiesTableWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
@ -57,6 +68,7 @@
formControlName="titleIcon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
@ -72,12 +84,14 @@
<div class="tb-form-row space-between">
<div>{{ 'widget-config.text-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="color">
</tb-color-input>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.background-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="backgroundColor">
</tb-color-input>
</div>

10
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.ts

@ -80,6 +80,8 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
columns: [this.getColumns(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.settings?.entitiesTitle, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showTitleIcon: [configData.config.showTitleIcon, []],
titleIcon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
@ -100,6 +102,8 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.widgetConfig.config.settings.entitiesTitle = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor;
@ -118,6 +122,8 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
const showTitleIcon: boolean = this.entitiesTableWidgetConfigForm.get('showTitleIcon').value;
if (showTitle) {
this.entitiesTableWidgetConfigForm.get('title').enable();
this.entitiesTableWidgetConfigForm.get('titleFont').enable();
this.entitiesTableWidgetConfigForm.get('titleColor').enable();
this.entitiesTableWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
if (showTitleIcon) {
this.entitiesTableWidgetConfigForm.get('titleIcon').enable();
@ -128,11 +134,15 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
}
} else {
this.entitiesTableWidgetConfigForm.get('title').disable();
this.entitiesTableWidgetConfigForm.get('titleFont').disable();
this.entitiesTableWidgetConfigForm.get('titleColor').disable();
this.entitiesTableWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
this.entitiesTableWidgetConfigForm.get('titleIcon').disable();
this.entitiesTableWidgetConfigForm.get('iconColor').disable();
}
this.entitiesTableWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetConfigForm.get('titleFont').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetConfigForm.get('titleColor').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
this.entitiesTableWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts

@ -29,7 +29,7 @@ import { WidgetConfigComponent } from '@home/components/widget/widget-config.com
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { getTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component';
import { isUndefined } from '@core/utils';
import { getLabel, setLabel } from '@home/components/widget/config/widget-settings.models';
import { getLabel, setLabel } from '@shared/models/widget-settings.models';
@Component({
selector: 'tb-simple-card-basic-config',

22
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.html

@ -39,13 +39,24 @@
</tb-data-keys-panel>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row">
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="timeseriesTableWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
@ -57,6 +68,7 @@
formControlName="titleIcon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
@ -72,12 +84,14 @@
<div class="tb-form-row space-between">
<div>{{ 'widget-config.text-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="color">
</tb-color-input>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.background-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="backgroundColor">
</tb-color-input>
</div>

10
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts

@ -66,6 +66,8 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
columns: [this.getColumns(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showTitleIcon: [configData.config.showTitleIcon, []],
titleIcon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
@ -85,6 +87,8 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
this.widgetConfig.config.actions = config.actions;
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.title = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor;
@ -104,6 +108,8 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
const showTitleIcon: boolean = this.timeseriesTableWidgetConfigForm.get('showTitleIcon').value;
if (showTitle) {
this.timeseriesTableWidgetConfigForm.get('title').enable();
this.timeseriesTableWidgetConfigForm.get('titleFont').enable();
this.timeseriesTableWidgetConfigForm.get('titleColor').enable();
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
if (showTitleIcon) {
this.timeseriesTableWidgetConfigForm.get('titleIcon').enable();
@ -114,11 +120,15 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
}
} else {
this.timeseriesTableWidgetConfigForm.get('title').disable();
this.timeseriesTableWidgetConfigForm.get('titleFont').disable();
this.timeseriesTableWidgetConfigForm.get('titleColor').disable();
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
this.timeseriesTableWidgetConfigForm.get('titleIcon').disable();
this.timeseriesTableWidgetConfigForm.get('iconColor').disable();
}
this.timeseriesTableWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
this.timeseriesTableWidgetConfigForm.get('titleFont').updateValueAndValidity({emitEvent});
this.timeseriesTableWidgetConfigForm.get('titleColor').updateValueAndValidity({emitEvent});
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
this.timeseriesTableWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
this.timeseriesTableWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});

2
ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts

@ -34,7 +34,7 @@ import {
DateFormatSettings,
getLabel,
setLabel
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import {
valueCardDefaultSettings,
ValueCardLayout,

22
ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.html

@ -39,13 +39,24 @@
</tb-data-keys-panel>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row">
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="flotWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row space-between">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
@ -57,6 +68,7 @@
formControlName="titleIcon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
@ -70,12 +82,14 @@
<div class="tb-form-row space-between">
<div>{{ 'widget-config.text-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="color">
</tb-color-input>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.background-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="backgroundColor">
</tb-color-input>
</div>

10
ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts

@ -66,6 +66,8 @@ export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
series: [this.getSeries(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showTitleIcon: [configData.config.showTitleIcon, []],
titleIcon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
@ -89,6 +91,8 @@ export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
this.widgetConfig.config.actions = config.actions;
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.title = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor;
@ -114,6 +118,8 @@ export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
const showLegend: boolean = this.flotWidgetConfigForm.get('showLegend').value;
if (showTitle) {
this.flotWidgetConfigForm.get('title').enable();
this.flotWidgetConfigForm.get('titleFont').enable();
this.flotWidgetConfigForm.get('titleColor').enable();
this.flotWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
if (showTitleIcon) {
this.flotWidgetConfigForm.get('titleIcon').enable();
@ -124,6 +130,8 @@ export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
}
} else {
this.flotWidgetConfigForm.get('title').disable();
this.flotWidgetConfigForm.get('titleFont').disable();
this.flotWidgetConfigForm.get('titleColor').disable();
this.flotWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
this.flotWidgetConfigForm.get('titleIcon').disable();
this.flotWidgetConfigForm.get('iconColor').disable();
@ -134,6 +142,8 @@ export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
this.flotWidgetConfigForm.get('legendConfig').disable();
}
this.flotWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('titleFont').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('titleColor').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
this.flotWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});

7
ui-ngx/src/app/modules/home/components/widget/config/widget-config-components.module.ts

@ -29,6 +29,7 @@ import { FilterSelectComponent } from '@home/components/filter/filter-select.com
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
import { WidgetSettingsComponent } from '@home/components/widget/config/widget-settings.component';
import { TimewindowConfigPanelComponent } from '@home/components/widget/config/timewindow-config-panel.component';
import { WidgetSettingsCommonModule } from '@home/components/widget/lib/settings/common/widget-settings-common.module';
@NgModule({
declarations:
@ -48,7 +49,8 @@ import { TimewindowConfigPanelComponent } from '@home/components/widget/config/t
imports: [
CommonModule,
SharedModule,
WidgetSettingsModule
WidgetSettingsModule,
WidgetSettingsCommonModule
],
exports: [
AlarmAssigneeSelectComponent,
@ -61,7 +63,8 @@ import { TimewindowConfigPanelComponent } from '@home/components/widget/config/t
EntityAliasSelectComponent,
FilterSelectComponent,
TimewindowConfigPanelComponent,
WidgetSettingsComponent
WidgetSettingsComponent,
WidgetSettingsCommonModule
]
})
export class WidgetConfigComponentsModule { }

15
ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts

@ -585,10 +585,13 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
$event.stopPropagation();
}
const target = $event.target || $event.srcElement || $event.currentTarget;
const config = new OverlayConfig();
config.backdropClass = 'cdk-overlay-transparent-backdrop';
config.panelClass = 'tb-filter-panel';
config.hasBackdrop = true;
const config = new OverlayConfig({
panelClass: 'tb-filter-panel',
backdropClass: 'cdk-overlay-transparent-backdrop',
hasBackdrop: true,
height: 'fit-content',
maxHeight: '75vh'
});
const connectedPosition: ConnectedPosition = {
originX: 'end',
originY: 'bottom',
@ -630,7 +633,11 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
const injector = Injector.create({parent: this.viewContainerRef.injector, providers});
const componentRef = overlayRef.attach(new ComponentPortal(AlarmFilterConfigComponent,
this.viewContainerRef, injector));
const resizeWindows = this.utils.updateOverlayMaxHeigth(overlayRef, componentRef.location);
componentRef.onDestroy(() => {
resizeWindows.unsubscribe();
if (componentRef.instance.panelResult) {
const result = componentRef.instance.panelResult;
const alarmFilter = this.entityService.resolveAlarmFilter(result, false);

2
ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts

@ -28,7 +28,7 @@ import {
iconStyle,
overlayStyle,
textStyle
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { valueCardDefaultSettings, ValueCardLayout, ValueCardWidgetSettings } from './value-card-widget.models';
import { WidgetComponent } from '@home/components/widget/widget.component';

2
ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts

@ -21,7 +21,7 @@ import {
constantColor,
cssUnit, DateFormatSettings,
Font, lastUpdateAgoDateFormat
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
export enum ValueCardLayout {
square = 'square',

4
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss

@ -92,8 +92,8 @@
}
.dot {
height: 25px;
width: 25px;
height: 12px;
width: 12px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts

@ -30,7 +30,7 @@ import {
DateFormatProcessor,
DateFormatSettings,
getLabel
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
@Component({
selector: 'tb-value-card-widget-settings',

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts

@ -22,7 +22,7 @@ import {
BackgroundSettings,
BackgroundType,
backgroundTypeTranslations, ComponentStyle
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts

@ -22,7 +22,7 @@ import {
BackgroundType,
ComponentStyle,
overlayStyle
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service';
import {

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings-panel.component.ts

@ -21,7 +21,7 @@ import {
ColorSettings,
ColorType,
colorTypeTranslations
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component';
import {
AbstractControl,

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/color-settings.component.ts

@ -16,7 +16,7 @@
import { Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ColorSettings, ColorType, ComponentStyle } from '@home/components/widget/config/widget-settings.models';
import { ColorSettings, ColorType, ComponentStyle } from '@shared/models/widget-settings.models';
import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service';
import {

4
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.html

@ -16,7 +16,9 @@
-->
<mat-form-field appearance="outline" subscriptSizing="dynamic" style="width: 100%;">
<mat-select [formControl]="cssUnitFormControl">
<mat-select [formControl]="cssUnitFormControl" placeholder="{{ 'widget-config.set' | translate }}">
<mat-option *ngIf="allowEmpty" [value]="null">
</mat-option>
<mat-option *ngFor="let cssUnit of cssUnitsList" [value]="cssUnit">{{ cssUnit }}</mat-option>
</mat-select>
</mat-form-field>

7
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-unit-select.component.ts

@ -16,7 +16,8 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormControl } from '@angular/forms';
import { cssUnit, cssUnits } from '@home/components/widget/config/widget-settings.models';
import { cssUnit, cssUnits } from '@shared/models/widget-settings.models';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-css-unit-select',
@ -35,6 +36,10 @@ export class CssUnitSelectComponent implements OnInit, ControlValueAccessor {
@Input()
disabled: boolean;
@Input()
@coerceBoolean()
allowEmpty = false;
cssUnitsList = cssUnits;
cssUnitFormControl: UntypedFormControl;

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts

@ -20,7 +20,7 @@ import {
compareDateFormats,
dateFormats,
DateFormatSettings
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
import { MatButton } from '@angular/material/button';

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-settings-panel.component.ts

@ -16,7 +16,7 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { DateFormatSettings } from '@home/components/widget/config/widget-settings.models';
import { DateFormatSettings } from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { UntypedFormControl, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';

16
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.html

@ -51,7 +51,9 @@
<div class="tb-form-row no-border no-padding">
<div class="fixed-title-width" translate>widgets.widget-font.font-weight</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="weight">
<mat-select formControlName="weight" placeholder="{{ 'widget-config.set' | translate }}">
<mat-option [value]="null">
</mat-option>
<mat-option *ngFor="let weight of fontWeightsList" [value]="weight">
{{ fontWeightTranslationsMap.has(weight) ? (fontWeightTranslationsMap.get(weight) | translate) : weight }}
</mat-option>
@ -61,7 +63,9 @@
<div class="tb-form-row no-border no-padding">
<div class="fixed-title-width" translate>widgets.widget-font.font-style</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="style">
<mat-select formControlName="style" placeholder="{{ 'widget-config.set' | translate }}">
<mat-option [value]="null">
</mat-option>
<mat-option *ngFor="let style of fontStylesList" [value]="style">
{{ fontStyleTranslationsMap.get(style) | translate }}
</mat-option>
@ -74,6 +78,14 @@
<div class="preview-text" fxFlex [style]="previewStyle">{{ previewText }}</div>
</div>
<div class="tb-font-settings-panel-buttons">
<button *ngIf="clearButton"
mat-button
type="button"
(click)="clearFont()"
[disabled]="clearDisabled()">
{{ 'action.clear' | translate }}
</button>
<span *ngIf="clearButton" fxFlex></span>
<button mat-button
color="primary"
type="button"

43
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings-panel.component.ts

@ -32,15 +32,16 @@ import {
fontStyles,
fontStyleTranslations,
fontWeights,
fontWeightTranslations,
fontWeightTranslations, isFontPartiallySet,
textStyle
} from '@home/components/widget/config/widget-settings.models';
} from '@shared/models/widget-settings.models';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Observable } from 'rxjs';
import { map, startWith, tap } from 'rxjs/operators';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-font-settings-panel',
@ -57,6 +58,13 @@ export class FontSettingsPanelComponent extends PageComponent implements OnInit
@Input()
previewText = 'AaBbCcDd';
@Input()
initialPreviewStyle: ComponentStyle;
@Input()
@coerceBoolean()
clearButton = false;
@Input()
popover: TbPopoverComponent<FontSettingsPanelComponent>;
@ -89,19 +97,17 @@ export class FontSettingsPanelComponent extends PageComponent implements OnInit
ngOnInit(): void {
this.fontFormGroup = this.fb.group(
{
size: [this.font?.size, [Validators.required, Validators.min(0)]],
sizeUnit: [this.font?.sizeUnit, [Validators.required]],
family: [this.font?.family, [Validators.required]],
weight: [this.font?.weight, [Validators.required]],
style: [this.font?.style, [Validators.required]]
size: [this.font?.size, [Validators.min(0)]],
sizeUnit: [(this.font?.sizeUnit || 'px'), []],
family: [this.font?.family, []],
weight: [this.font?.weight, []],
style: [this.font?.style, []]
}
);
if (this.font) {
this.previewStyle = textStyle(this.font, '1');
}
this.fontFormGroup.valueChanges.subscribe((value: Font) => {
this.updatePreviewStyle(this.font);
this.fontFormGroup.valueChanges.subscribe((font: Font) => {
if (this.fontFormGroup.valid) {
this.previewStyle = textStyle(value, '1');
this.updatePreviewStyle(font);
setTimeout(() => {this.popover?.updatePosition();}, 0);
}
});
@ -130,4 +136,17 @@ export class FontSettingsPanelComponent extends PageComponent implements OnInit
this.fontApplied.emit(font);
}
clearDisabled(): boolean {
return !isFontPartiallySet(this.fontFormGroup.value);
}
clearFont() {
this.fontFormGroup.reset({sizeUnit: 'px'});
this.fontFormGroup.markAsDirty();
}
private updatePreviewStyle(font: Font) {
this.previewStyle = {...(this.initialPreviewStyle || {}), ...textStyle(font, '1')};
}
}

14
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/font-settings.component.ts

@ -16,11 +16,12 @@
import { Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Font } from '@home/components/widget/config/widget-settings.models';
import { ComponentStyle, Font } from '@shared/models/widget-settings.models';
import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service';
import { FontSettingsPanelComponent } from '@home/components/widget/lib/settings/common/font-settings-panel.component';
import { isDefinedAndNotNull } from '@core/utils';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-font-settings',
@ -42,6 +43,13 @@ export class FontSettingsComponent implements OnInit, ControlValueAccessor {
@Input()
previewText: string | (() => string);
@Input()
initialPreviewStyle: ComponentStyle;
@Input()
@coerceBoolean()
clearButton = false;
private modelValue: Font;
private propagateChange = null;
@ -77,7 +85,9 @@ export class FontSettingsComponent implements OnInit, ControlValueAccessor {
this.popoverService.hidePopover(trigger);
} else {
const ctx: any = {
font: this.modelValue
font: this.modelValue,
initialPreviewStyle: this.initialPreviewStyle,
clearButton: this.clearButton
};
if (isDefinedAndNotNull(this.previewText)) {
const previewText = typeof this.previewText === 'string' ? this.previewText : this.previewText();

84
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts

@ -0,0 +1,84 @@
///
/// Copyright © 2016-2023 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared/shared.module';
import { SharedHomeComponentsModule } from '@home/components/shared-home-components.module';
import { WidgetFontComponent } from '@home/components/widget/lib/settings/common/widget-font.component';
import { ValueSourceComponent } from '@home/components/widget/lib/settings/common/value-source.component';
import { LegendConfigComponent } from '@home/components/widget/lib/settings/common/legend-config.component';
import {
ImageCardsSelectComponent,
ImageCardsSelectOptionDirective
} from '@home/components/widget/lib/settings/common/image-cards-select.component';
import { FontSettingsComponent } from '@home/components/widget/lib/settings/common/font-settings.component';
import { FontSettingsPanelComponent } from '@home/components/widget/lib/settings/common/font-settings-panel.component';
import { ColorSettingsComponent } from '@home/components/widget/lib/settings/common/color-settings.component';
import {
ColorSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/color-settings-panel.component';
import { CssUnitSelectComponent } from '@home/components/widget/lib/settings/common/css-unit-select.component';
import { DateFormatSelectComponent } from '@home/components/widget/lib/settings/common/date-format-select.component';
import {
DateFormatSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/date-format-settings-panel.component';
import { BackgroundSettingsComponent } from '@home/components/widget/lib/settings/common/background-settings.component';
import {
BackgroundSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/background-settings-panel.component';
@NgModule({
declarations: [
ImageCardsSelectOptionDirective,
ImageCardsSelectComponent,
FontSettingsComponent,
FontSettingsPanelComponent,
ColorSettingsComponent,
ColorSettingsPanelComponent,
CssUnitSelectComponent,
DateFormatSelectComponent,
DateFormatSettingsPanelComponent,
BackgroundSettingsComponent,
BackgroundSettingsPanelComponent,
ValueSourceComponent,
LegendConfigComponent,
WidgetFontComponent
],
imports: [
CommonModule,
SharedModule,
SharedHomeComponentsModule
],
exports: [
ImageCardsSelectOptionDirective,
ImageCardsSelectComponent,
FontSettingsComponent,
FontSettingsPanelComponent,
ColorSettingsComponent,
ColorSettingsPanelComponent,
CssUnitSelectComponent,
DateFormatSelectComponent,
DateFormatSettingsPanelComponent,
BackgroundSettingsComponent,
BackgroundSettingsPanelComponent,
ValueSourceComponent,
LegendConfigComponent,
WidgetFontComponent
]
})
export class WidgetSettingsCommonModule {
}

54
ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts

@ -32,7 +32,6 @@ import {
import {
MarkdownWidgetSettingsComponent
} from '@home/components/widget/lib/settings/cards/markdown-widget-settings.component';
import { WidgetFontComponent } from '@home/components/widget/lib/settings/common/widget-font.component';
import { LabelWidgetLabelComponent } from '@home/components/widget/lib/settings/cards/label-widget-label.component';
import { LabelWidgetSettingsComponent } from '@home/components/widget/lib/settings/cards/label-widget-settings.component';
import {
@ -72,7 +71,6 @@ import {
import {
DigitalGaugeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component';
import { ValueSourceComponent } from '@home/components/widget/lib/settings/common/value-source.component';
import { FixedColorLevelComponent } from '@home/components/widget/lib/settings/gauge/fixed-color-level.component';
import { TickValueComponent } from '@home/components/widget/lib/settings/gauge/tick-value.component';
import { FlotWidgetSettingsComponent } from '@home/components/widget/lib/settings/chart/flot-widget-settings.component';
@ -271,29 +269,10 @@ import {
import {
QuickLinksWidgetSettingsComponent
} from '@home/components/widget/lib/settings/home-page/quick-links-widget-settings.component';
import { LegendConfigComponent } from '@home/components/widget/lib/settings/common/legend-config.component';
import {
ImageCardsSelectOptionDirective,
ImageCardsSelectComponent
} from '@home/components/widget/lib/settings/common/image-cards-select.component';
import { FontSettingsComponent } from '@home/components/widget/lib/settings/common/font-settings.component';
import { FontSettingsPanelComponent } from '@home/components/widget/lib/settings/common/font-settings-panel.component';
import { ColorSettingsComponent } from '@home/components/widget/lib/settings/common/color-settings.component';
import {
ColorSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/color-settings-panel.component';
import { CssUnitSelectComponent } from '@home/components/widget/lib/settings/common/css-unit-select.component';
import { DateFormatSelectComponent } from '@home/components/widget/lib/settings/common/date-format-select.component';
import {
DateFormatSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/date-format-settings-panel.component';
import { BackgroundSettingsComponent } from '@home/components/widget/lib/settings/common/background-settings.component';
import {
BackgroundSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/background-settings-panel.component';
import {
ValueCardWidgetSettingsComponent
} from '@home/components/widget/lib/settings/cards/value-card-widget-settings.component';
import { WidgetSettingsCommonModule } from '@home/components/widget/lib/settings/common/widget-settings-common.module';
@NgModule({
declarations: [
@ -302,7 +281,6 @@ import {
TimeseriesTableKeySettingsComponent,
TimeseriesTableLatestKeySettingsComponent,
MarkdownWidgetSettingsComponent,
WidgetFontComponent,
LabelWidgetLabelComponent,
LabelWidgetSettingsComponent,
SimpleCardWidgetSettingsComponent,
@ -318,8 +296,6 @@ import {
AnalogueLinearGaugeWidgetSettingsComponent,
AnalogueCompassWidgetSettingsComponent,
DigitalGaugeWidgetSettingsComponent,
ValueSourceComponent,
LegendConfigComponent,
FixedColorLevelComponent,
TickValueComponent,
FlotWidgetSettingsComponent,
@ -398,23 +374,13 @@ import {
TripAnimationWidgetSettingsComponent,
DocLinksWidgetSettingsComponent,
QuickLinksWidgetSettingsComponent,
ImageCardsSelectOptionDirective,
ImageCardsSelectComponent,
FontSettingsComponent,
FontSettingsPanelComponent,
ColorSettingsComponent,
ColorSettingsPanelComponent,
CssUnitSelectComponent,
DateFormatSelectComponent,
DateFormatSettingsPanelComponent,
BackgroundSettingsComponent,
BackgroundSettingsPanelComponent,
ValueCardWidgetSettingsComponent
],
imports: [
CommonModule,
SharedModule,
SharedHomeComponentsModule
SharedHomeComponentsModule,
WidgetSettingsCommonModule
],
exports: [
QrCodeWidgetSettingsComponent,
@ -422,7 +388,6 @@ import {
TimeseriesTableKeySettingsComponent,
TimeseriesTableLatestKeySettingsComponent,
MarkdownWidgetSettingsComponent,
WidgetFontComponent,
LabelWidgetLabelComponent,
LabelWidgetSettingsComponent,
SimpleCardWidgetSettingsComponent,
@ -438,8 +403,6 @@ import {
AnalogueLinearGaugeWidgetSettingsComponent,
AnalogueCompassWidgetSettingsComponent,
DigitalGaugeWidgetSettingsComponent,
ValueSourceComponent,
LegendConfigComponent,
FixedColorLevelComponent,
TickValueComponent,
FlotWidgetSettingsComponent,
@ -518,17 +481,6 @@ import {
TripAnimationWidgetSettingsComponent,
DocLinksWidgetSettingsComponent,
QuickLinksWidgetSettingsComponent,
ImageCardsSelectOptionDirective,
ImageCardsSelectComponent,
FontSettingsComponent,
FontSettingsPanelComponent,
ColorSettingsComponent,
ColorSettingsPanelComponent,
CssUnitSelectComponent,
DateFormatSelectComponent,
DateFormatSettingsPanelComponent,
BackgroundSettingsComponent,
BackgroundSettingsPanelComponent,
ValueCardWidgetSettingsComponent
]
})

20
ui-ngx/src/app/modules/home/components/widget/widget-config.component.html

@ -40,9 +40,20 @@
</mat-slide-toggle>
<div class="tb-form-row">
<div class="fixed-title-width" translate>widget-config.title</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="widgetSettings.get('title').value"
[initialPreviewStyle]="widgetSettings.get('titleStyle').value">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row">
<div class="fixed-title-width" translate>widget-config.title-tooltip</div>
@ -63,6 +74,7 @@
formControlName="titleIcon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
@ -88,12 +100,14 @@
<div class="tb-form-row space-between">
<div>{{ 'widget-config.text-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="color">
</tb-color-input>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.background-color' | translate }}</div>
<tb-color-input asBoxInput
colorClearButton
formControlName="backgroundColor">
</tb-color-input>
</div>

8
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

@ -212,6 +212,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
this.advancedSettings = this.fb.group({});
this.widgetSettings = this.fb.group({
title: [null, []],
titleFont: [null, []],
titleColor: [null, []],
showTitleIcon: [null, []],
titleIcon: [null, []],
iconColor: [null, []],
@ -473,6 +475,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
const displayWidgetTitle = isDefined(config.showTitle) ? config.showTitle : false;
this.widgetSettings.patchValue({
title: config.title,
titleFont: config.titleFont,
titleColor: config.titleColor,
showTitleIcon: isDefined(config.showTitleIcon) && displayWidgetTitle ? config.showTitleIcon : false,
titleIcon: isDefined(config.titleIcon) ? config.titleIcon : '',
iconColor: isDefined(config.iconColor) ? config.iconColor : 'rgba(0, 0, 0, 0.87)',
@ -580,11 +584,15 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
const showTitleIcon: boolean = this.widgetSettings.get('showTitleIcon').value;
if (showTitle) {
this.widgetSettings.get('title').enable({emitEvent: false});
this.widgetSettings.get('titleFont').enable({emitEvent: false});
this.widgetSettings.get('titleColor').enable({emitEvent: false});
this.widgetSettings.get('titleTooltip').enable({emitEvent: false});
this.widgetSettings.get('titleStyle').enable({emitEvent: false});
this.widgetSettings.get('showTitleIcon').enable({emitEvent: false});
} else {
this.widgetSettings.get('title').disable({emitEvent: false});
this.widgetSettings.get('titleFont').disable({emitEvent: false});
this.widgetSettings.get('titleColor').disable({emitEvent: false});
this.widgetSettings.get('titleTooltip').disable({emitEvent: false});
this.widgetSettings.get('titleStyle').disable({emitEvent: false});
this.widgetSettings.get('showTitleIcon').disable({emitEvent: false});

13
ui-ngx/src/app/modules/home/models/dashboard-component.models.ts

@ -33,6 +33,7 @@ import { IAliasController, IStateController } from '@app/core/api/widget-api.mod
import { enumerable } from '@shared/decorators/enumerable';
import { UtilsService } from '@core/services/utils.service';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { ComponentStyle, textStyle } from '@shared/models/widget-settings.models';
export interface WidgetsData {
widgets: Array<Widget>;
@ -334,11 +335,11 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
customTranslatedTitle: string;
titleTooltip: string;
showTitle: boolean;
titleStyle: {[klass: string]: any};
titleStyle: ComponentStyle;
titleIcon: string;
showTitleIcon: boolean;
titleIconStyle: {[klass: string]: any};
titleIconStyle: ComponentStyle;
dropShadow: boolean;
enableFullscreen: boolean;
@ -351,7 +352,7 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
onlyHistoryTimewindow: boolean;
style: {[klass: string]: any};
style: ComponentStyle;
showWidgetTitlePanel: boolean;
showWidgetActions: boolean;
@ -437,8 +438,10 @@ export class DashboardWidget implements GridsterItem, IDashboardWidget {
&& this.widgetContext.widgetTitleTooltip.length ? this.widgetContext.widgetTitleTooltip : this.widget.config.titleTooltip;
this.titleTooltip = this.dashboard.utils.customTranslation(this.titleTooltip, this.titleTooltip);
this.showTitle = isDefined(this.widget.config.showTitle) ? this.widget.config.showTitle : true;
this.titleStyle = this.widget.config.titleStyle ? this.widget.config.titleStyle : {};
this.titleStyle = {...(this.widget.config.titleStyle || {}), ...textStyle(this.widget.config.titleFont, '24px', '0.01em')};
if (this.widget.config.titleColor) {
this.titleStyle.color = this.widget.config.titleColor;
}
this.titleIcon = isDefined(this.widget.config.titleIcon) ? this.widget.config.titleIcon : '';
this.showTitleIcon = isDefined(this.widget.config.showTitleIcon) ? this.widget.config.showTitleIcon : false;
this.titleIconStyle = {};

30
ui-ngx/src/app/shared/components/color-input.component.ts

@ -60,29 +60,13 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro
@Input()
requiredText: string;
private colorClearButtonValue: boolean;
get colorClearButton(): boolean {
return this.colorClearButtonValue;
}
@Input()
set colorClearButton(value: boolean) {
const newVal = coerceBooleanProperty(value);
if (this.colorClearButtonValue !== newVal) {
this.colorClearButtonValue = newVal;
}
}
@coerceBoolean()
colorClearButton = false;
private openOnInputValue: boolean;
get openOnInput(): boolean {
return this.openOnInputValue;
}
@Input()
set openOnInput(value: boolean) {
const newVal = coerceBooleanProperty(value);
if (this.openOnInputValue !== newVal) {
this.openOnInputValue = newVal;
}
}
@coerceBoolean()
openOnInput = false;
private requiredValue: boolean;
get required(): boolean {
@ -167,7 +151,8 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro
showColorPicker($event: MouseEvent) {
$event.stopPropagation();
this.dialogs.colorPicker(this.colorFormGroup.get('color').value).subscribe(
this.dialogs.colorPicker(this.colorFormGroup.get('color').value,
this.colorClearButton).subscribe(
(color) => {
if (color) {
this.colorFormGroup.patchValue(
@ -190,7 +175,8 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro
const colorPickerPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, ColorPickerPanelComponent, 'left', true, null,
{
color: this.colorFormGroup.get('color').value
color: this.colorFormGroup.get('color').value,
colorClearButton: this.colorClearButton
},
{},
{}, {}, true);

8
ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.html

@ -19,6 +19,14 @@
<div class="tb-color-picker-title" translate>color.color</div>
<tb-color-picker [formControl]="colorPickerControl"></tb-color-picker>
<div class="tb-color-picker-panel-buttons">
<button *ngIf="colorClearButton"
mat-button
color="primary"
type="button"
(click)="clearColor()"
[disabled]="!colorPickerControl.value">
{{ 'action.clear' | translate }}
</button>
<button mat-raised-button
color="primary"
type="button"

9
ui-ngx/src/app/shared/components/color-picker/color-picker-panel.component.ts

@ -20,6 +20,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { UntypedFormControl } from '@angular/forms';
import { TbPopoverComponent } from '@shared/components/popover.component';
import { coerceBoolean } from '@shared/decorators/coercion';
@Component({
selector: 'tb-color-picker-panel',
@ -33,6 +34,10 @@ export class ColorPickerPanelComponent extends PageComponent implements OnInit {
@Input()
color: string;
@Input()
@coerceBoolean()
colorClearButton = false;
@Input()
popover: TbPopoverComponent<ColorPickerPanelComponent>;
@ -52,4 +57,8 @@ export class ColorPickerPanelComponent extends PageComponent implements OnInit {
selectColor() {
this.colorSelected.emit(this.colorPickerControl.value);
}
clearColor() {
this.colorSelected.emit(null);
}
}

1
ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.html

@ -23,6 +23,7 @@
<mat-icon>close</mat-icon>
</button>
<tb-color-picker-panel [color]="color"
[colorClearButton]="colorClearButton"
(colorSelected)="selectColor($event)">
</tb-color-picker-panel>
</div>

3
ui-ngx/src/app/shared/components/dialog/color-picker-dialog.component.ts

@ -23,6 +23,7 @@ import { DialogComponent } from '@shared/components/dialog.component';
export interface ColorPickerDialogData {
color: string;
colorClearButton: boolean;
}
@Component({
@ -33,6 +34,7 @@ export interface ColorPickerDialogData {
export class ColorPickerDialogComponent extends DialogComponent<ColorPickerDialogComponent, string> {
color: string;
colorClearButton: boolean;
constructor(protected store: Store<AppState>,
protected router: Router,
@ -40,6 +42,7 @@ export class ColorPickerDialogComponent extends DialogComponent<ColorPickerDialo
public dialogRef: MatDialogRef<ColorPickerDialogComponent, string>) {
super(store, router, dialogRef);
this.color = data.color;
this.colorClearButton = data.colorClearButton;
}
selectColor(color: string) {

1
ui-ngx/src/app/shared/models/public-api.ts

@ -54,6 +54,7 @@ export * from './settings.models';
export * from './tenant.model';
export * from './user.model';
export * from './user-settings.models';
export * from './widget-settings.models';
export * from './widget.models';
export * from './widgets-bundle.model';
export * from './window-message.model';

29
ui-ngx/src/app/modules/home/components/widget/config/widget-settings.models.ts → ui-ngx/src/app/shared/models/widget-settings.models.ts

@ -308,11 +308,30 @@ export const iconStyle = (size: number, sizeUnit: cssUnit): ComponentStyle => {
};
};
export const textStyle = (font: Font, lineHeight = '1.5', letterSpacing = '0.25px'): ComponentStyle => ({
font: font.style + ' normal ' + font.weight + ' ' + (font.size+font.sizeUnit) + '/' + lineHeight + ' ' + font.family +
(font.family !== 'Roboto' ? ', Roboto' : ''),
letterSpacing
});
export const textStyle = (font?: Font, lineHeight = '1.5', letterSpacing = '0.25px'): ComponentStyle => {
const style: ComponentStyle = {
lineHeight,
letterSpacing
};
if (font?.style) {
style.fontStyle = font.style;
}
if (font?.weight) {
style.fontWeight = font.weight;
}
if (font?.size) {
style.fontSize = (font.size + (font.sizeUnit || 'px'));
}
if (font?.family) {
style.fontFamily = font.family +
(font.family !== 'Roboto' ? ', Roboto' : '');
}
return style;
};
export const isFontSet = (font: Font): boolean => (!!font && !!font.style && !!font.weight && !!font.size && !!font.family);
export const isFontPartiallySet = (font: Font): boolean => (!!font && (!!font.style || !!font.weight || !!font.size || !!font.family));
export const backgroundStyle = (background: BackgroundSettings): ComponentStyle => {
if (background.type === BackgroundType.color) {

7
ui-ngx/src/app/shared/models/widget.models.ts

@ -40,6 +40,7 @@ import { Dashboard } from '@shared/models/dashboard.models';
import { IAliasController } from '@core/api/widget-api.models';
import { isEmptyStr } from '@core/utils';
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { ComponentStyle, Font } from '@shared/models/widget-settings.models';
export enum widgetType {
timeseries = 'timeseries',
@ -619,6 +620,8 @@ export enum WidgetConfigMode {
export interface WidgetConfig {
configMode?: WidgetConfigMode;
title?: string;
titleFont?: Font;
titleColor?: string;
titleIcon?: string;
showTitle?: boolean;
showTitleIcon?: boolean;
@ -639,9 +642,9 @@ export interface WidgetConfig {
padding?: string;
margin?: string;
borderRadius?: string;
widgetStyle?: {[klass: string]: any};
widgetStyle?: ComponentStyle;
widgetCss?: string;
titleStyle?: {[klass: string]: any};
titleStyle?: ComponentStyle;
units?: string;
decimals?: number;
noDataDisplayMessage?: string;

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -74,7 +74,8 @@
"reset": "Reset",
"show-more": "Show more",
"dont-show-again": "Do not show again",
"see-documentation": "See documentation"
"see-documentation": "See documentation",
"clear": "Clear"
},
"aggregation": {
"aggregation": "Aggregation",

2
ui-ngx/src/form.scss

@ -21,7 +21,7 @@
flex-direction: column;
align-items: stretch;
gap: 12px;
padding: 12px 12px 12px 16px;
padding: 12px 7px 12px 16px;
.mat-mdc-form-field, tb-unit-input {
width: auto;
&.medium-width {

Loading…
Cancel
Save