Browse Source

UI: Timeseries line chart config.

pull/8881/head
Igor Kulikov 3 years ago
parent
commit
ea56b2a168
  1. 14
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html
  2. 10
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.scss
  3. 8
      ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts
  4. 4
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.html
  5. 7
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/entities-table-basic-config.component.ts
  6. 4
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.html
  7. 7
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/simple-card-basic-config.component.ts
  8. 5
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.html
  9. 18
      ui-ngx/src/app/modules/home/components/widget/config/basic/cards/timeseries-table-basic-config.component.ts
  10. 113
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.html
  11. 167
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/flot-basic-config.component.ts
  12. 2
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html
  13. 3
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts
  14. 6
      ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts
  15. 20
      ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html
  16. 107
      ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.scss
  17. 2
      ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts
  18. 17
      ui-ngx/src/app/modules/home/components/widget/config/datasources.component.ts
  19. 11
      ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts
  20. 2
      ui-ngx/src/app/modules/home/components/widget/config/widget-units.component.html
  21. 8
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.html
  22. 14
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html
  23. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.html
  24. 8
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.html
  25. 20
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html
  26. 257
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html
  27. 1
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts
  28. 74
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html
  29. 62
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.scss
  30. 15
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts
  31. 496
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html
  32. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts
  33. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts
  34. 56
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html
  35. 57
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts
  36. 32
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  37. 38
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  38. 41
      ui-ngx/src/styles.scss

14
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html

@ -54,11 +54,13 @@
</button> </button>
</div> </div>
</tb-widget-config> </tb-widget-config>
<tb-widget-preview *ngIf="previewMode" class="widget-preview-section" <div *ngIf="previewMode" class="widget-preview-background">
[aliasController]="aliasController" <tb-widget-preview class="widget-preview-section"
[stateController]="stateController" [aliasController]="aliasController"
[widget]="widget" [stateController]="stateController"
[widgetConfig]="widgetFormGroup.get('widgetConfig').value.config"> [widget]="widget"
</tb-widget-preview> [widgetConfig]="widgetFormGroup.get('widgetConfig').value.config">
</tb-widget-preview>
</div>
</fieldset> </fieldset>
</form> </form>

10
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.scss

@ -14,9 +14,17 @@
* limitations under the License. * limitations under the License.
*/ */
:host { :host {
.widget-preview-section { .widget-preview-background {
position: absolute; position: absolute;
top: 72px; top: 72px;
left: 0;
right: 0;
bottom: 0;
background: #fff;
}
.widget-preview-section {
position: absolute;
top: 0;
left: 16px; left: 16px;
right: 16px; right: 16px;
bottom: 16px; bottom: 16px;

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

@ -33,6 +33,8 @@ import { DataKeyRowComponent } from '@home/components/widget/config/basic/common
import { import {
TimeseriesTableBasicConfigComponent TimeseriesTableBasicConfigComponent
} from '@home/components/widget/config/basic/cards/timeseries-table-basic-config.component'; } 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';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -40,12 +42,14 @@ import {
SimpleCardBasicConfigComponent, SimpleCardBasicConfigComponent,
EntitiesTableBasicConfigComponent, EntitiesTableBasicConfigComponent,
TimeseriesTableBasicConfigComponent, TimeseriesTableBasicConfigComponent,
FlotBasicConfigComponent,
DataKeyRowComponent, DataKeyRowComponent,
DataKeysPanelComponent DataKeysPanelComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
SharedModule, SharedModule,
WidgetSettingsModule,
WidgetConfigComponentsModule WidgetConfigComponentsModule
], ],
exports: [ exports: [
@ -53,6 +57,7 @@ import {
SimpleCardBasicConfigComponent, SimpleCardBasicConfigComponent,
EntitiesTableBasicConfigComponent, EntitiesTableBasicConfigComponent,
TimeseriesTableBasicConfigComponent, TimeseriesTableBasicConfigComponent,
FlotBasicConfigComponent,
DataKeyRowComponent, DataKeyRowComponent,
DataKeysPanelComponent DataKeysPanelComponent
] ]
@ -63,5 +68,6 @@ export class BasicWidgetConfigModule {
export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetConfigComponent>} = { export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetConfigComponent>} = {
'tb-simple-card-basic-config': SimpleCardBasicConfigComponent, 'tb-simple-card-basic-config': SimpleCardBasicConfigComponent,
'tb-entities-table-basic-config': EntitiesTableBasicConfigComponent, 'tb-entities-table-basic-config': EntitiesTableBasicConfigComponent,
'tb-timeseries-table-basic-config': TimeseriesTableBasicConfigComponent 'tb-timeseries-table-basic-config': TimeseriesTableBasicConfigComponent,
'tb-flot-basic-config': FlotBasicConfigComponent
}; };

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

@ -40,7 +40,7 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div> <div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="showTitle"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }} {{ 'widget-config.card-title' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
@ -63,7 +63,7 @@
</div> </div>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widgets.table.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option> <mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option>
<mat-chip-option value="columnsToDisplay">{{ 'widgets.table.columns-to-display' | translate }}</mat-chip-option> <mat-chip-option value="columnsToDisplay">{{ 'widgets.table.columns-to-display' | translate }}</mat-chip-option>

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

@ -29,6 +29,7 @@ import {
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { isUndefined } from '@core/utils'; import { isUndefined } from '@core/utils';
import { getTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component';
@Component({ @Component({
selector: 'tb-entities-table-basic-config', selector: 'tb-entities-table-basic-config',
@ -74,11 +75,7 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
protected onConfigSet(configData: WidgetConfigComponentData) { protected onConfigSet(configData: WidgetConfigComponentData) {
this.entitiesTableWidgetConfigForm = this.fb.group({ this.entitiesTableWidgetConfigForm = this.fb.group({
timewindowConfig: [{ timewindowConfig: [getTimewindowConfig(configData.config), []],
useDashboardTimewindow: configData.config.useDashboardTimewindow,
displayTimewindow: configData.config.displayTimewindow,
timewindow: configData.config.timewindow
}, []],
datasources: [configData.config.datasources, []], datasources: [configData.config.datasources, []],
columns: [this.getColumns(configData.config.datasources), []], columns: [this.getColumns(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []], showTitle: [configData.config.showTitle, []],

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

@ -31,7 +31,7 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div> <div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<div translate>widgets.simple-card.label</div> <div class="fixed-title-width" translate>widgets.simple-card.label</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="label" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="label" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
@ -57,7 +57,7 @@
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widget-config.decimals-short</div> <div translate>widget-config.decimals-short</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>

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

@ -27,6 +27,7 @@ import {
} from '@shared/models/widget.models'; } from '@shared/models/widget.models';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { getTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component';
@Component({ @Component({
selector: 'tb-simple-card-basic-config', selector: 'tb-simple-card-basic-config',
@ -63,11 +64,7 @@ export class SimpleCardBasicConfigComponent extends BasicWidgetConfigComponent {
protected onConfigSet(configData: WidgetConfigComponentData) { protected onConfigSet(configData: WidgetConfigComponentData) {
this.simpleCardWidgetConfigForm = this.fb.group({ this.simpleCardWidgetConfigForm = this.fb.group({
timewindowConfig: [{ timewindowConfig: [getTimewindowConfig(configData.config), []],
useDashboardTimewindow: configData.config.useDashboardTimewindow,
displayTimewindow: configData.config.useDashboardTimewindow,
timewindow: configData.config.timewindow
}, []],
datasources: [configData.config.datasources, []], datasources: [configData.config.datasources, []],
label: [this.getDataKeyLabel(configData.config.datasources), []], label: [this.getDataKeyLabel(configData.config.datasources), []],
labelPosition: [configData.config.settings?.labelPosition, []], labelPosition: [configData.config.settings?.labelPosition, []],

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

@ -21,6 +21,7 @@
<tb-datasources <tb-datasources
[configMode]="basicMode" [configMode]="basicMode"
hideDataKeys hideDataKeys
forceSingleDatasource
formControlName="datasources"> formControlName="datasources">
</tb-datasources> </tb-datasources>
<tb-data-keys-panel <tb-data-keys-panel
@ -39,7 +40,7 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div> <div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="showTitle"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.card-title' | translate }} {{ 'widget-config.card-title' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
@ -62,7 +63,7 @@
</div> </div>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widgets.table.show-card-buttons</div> <div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons"> <mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option> <mat-chip-option value="search">{{ 'action.search' | translate }}</mat-chip-option>
<mat-chip-option value="columnsToDisplay">{{ 'widgets.table.columns-to-display' | translate }}</mat-chip-option> <mat-chip-option value="columnsToDisplay">{{ 'widgets.table.columns-to-display' | translate }}</mat-chip-option>

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

@ -20,15 +20,11 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models'; import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { import { DataKey, Datasource, WidgetConfig } from '@shared/models/widget.models';
DataKey,
Datasource,
datasourcesHasAggregation,
datasourcesHasOnlyComparisonAggregation, WidgetConfig
} from '@shared/models/widget.models';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { deepClone, isUndefined } from '@core/utils'; import { deepClone, isUndefined } from '@core/utils';
import { getTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component';
@Component({ @Component({
selector: 'tb-timeseries-table-basic-config', selector: 'tb-timeseries-table-basic-config',
@ -65,11 +61,7 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
protected onConfigSet(configData: WidgetConfigComponentData) { protected onConfigSet(configData: WidgetConfigComponentData) {
this.timeseriesTableWidgetConfigForm = this.fb.group({ this.timeseriesTableWidgetConfigForm = this.fb.group({
timewindowConfig: [{ timewindowConfig: [getTimewindowConfig(configData.config), []],
useDashboardTimewindow: configData.config.useDashboardTimewindow,
displayTimewindow: configData.config.displayTimewindow,
timewindow: configData.config.timewindow
}, []],
datasources: [configData.config.datasources, []], datasources: [configData.config.datasources, []],
columns: [this.getColumns(configData.config.datasources), []], columns: [this.getColumns(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []], showTitle: [configData.config.showTitle, []],
@ -92,11 +84,11 @@ export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigCompon
this.setColumns(config.columns, this.widgetConfig.config.datasources); this.setColumns(config.columns, this.widgetConfig.config.datasources);
this.widgetConfig.config.actions = config.actions; this.widgetConfig.config.actions = config.actions;
this.widgetConfig.config.showTitle = config.showTitle; this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {}; this.widgetConfig.config.title = config.title;
this.widgetConfig.config.settings.entitiesTitle = config.title;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon; this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon; this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor; this.widgetConfig.config.iconColor = config.iconColor;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.setCardButtons(config.cardButtons, this.widgetConfig.config);
this.widgetConfig.config.color = config.color; this.widgetConfig.config.color = config.color;
this.widgetConfig.config.backgroundColor = config.backgroundColor; this.widgetConfig.config.backgroundColor = config.backgroundColor;

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

@ -0,0 +1,113 @@
<!--
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.
-->
<ng-container [formGroup]="flotWidgetConfigForm">
<tb-timewindow-config-panel formControlName="timewindowConfig">
</tb-timewindow-config-panel>
<tb-datasources
[configMode]="basicMode"
hideDataKeys
forceSingleDatasource
formControlName="datasources">
</tb-datasources>
<tb-data-keys-panel
panelTitle="{{ 'widgets.chart.series' | translate }}"
addKeyTitle="{{ 'widgets.chart.add-series' | translate }}"
keySettingsTitle="{{ 'widgets.chart.series-settings' | translate }}"
removeKeyTitle="{{ 'widgets.chart.remove-series' | translate }}"
noKeysText="{{ 'widgets.chart.no-series' | translate }}"
requiredKeysText="{{ 'widgets.chart.no-series-error' | translate }}"
hideSourceSelection
[datasourceType]="datasource?.type"
[deviceId]="datasource?.deviceId"
[entityAliasId]="datasource?.entityAliasId"
formControlName="series">
</tb-data-keys-panel>
<div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-widget-config-row">
<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>
<div class="tb-widget-config-row space-between same-padding">
<mat-slide-toggle class="mat-slide" formControlName="showTitleIcon">
{{ 'widget-config.card-icon' | translate }}
</mat-slide-toggle>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<tb-material-icon-select asBoxInput
[color]="flotWidgetConfigForm.get('iconColor').value"
formControlName="titleIcon">
</tb-material-icon-select>
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="iconColor">
</tb-color-input>
</div>
</div>
<div class="tb-widget-config-row space-between">
<div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>
</mat-chip-listbox>
</div>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widget-config.background-color' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="backgroundColor">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.chart.chart-appearance</div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="verticalLines">
{{ 'widgets.chart.vertical-grid-lines' | translate }}
</mat-slide-toggle>
</div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="horizontalLines">
{{ 'widgets.chart.horizontal-grid-lines' | translate }}
</mat-slide-toggle>
</div>
<div class="tb-widget-config-panel tb-slide-toggle">
<mat-expansion-panel class="tb-settings" [expanded]="flotWidgetConfigForm.get('showLegend').value" [disabled]="!flotWidgetConfigForm.get('showLegend').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle class="mat-slide" formControlName="showLegend" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widget-config.legend' | translate }}
</mat-slide-toggle>
</mat-panel-title>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-legend-config formControlName="legendConfig">
</tb-legend-config>
</ng-template>
</mat-expansion-panel>
</div>
</div>
<tb-widget-actions-panel
formControlName="actions">
</tb-widget-actions-panel>
</ng-container>

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

@ -0,0 +1,167 @@
///
/// 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 { Component } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { DataKey, Datasource, WidgetConfig } from '@shared/models/widget.models';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { isUndefined } from '@core/utils';
import { getTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component';
@Component({
selector: 'tb-flot-basic-config',
templateUrl: './flot-basic-config.component.html',
styleUrls: ['../basic-config.scss']
})
export class FlotBasicConfigComponent extends BasicWidgetConfigComponent {
public get datasource(): Datasource {
const datasources: Datasource[] = this.flotWidgetConfigForm.get('datasources').value;
if (datasources && datasources.length) {
return datasources[0];
} else {
return null;
}
}
flotWidgetConfigForm: UntypedFormGroup;
constructor(protected store: Store<AppState>,
protected widgetConfigComponent: WidgetConfigComponent,
private fb: UntypedFormBuilder) {
super(store, widgetConfigComponent);
}
protected configForm(): UntypedFormGroup {
return this.flotWidgetConfigForm;
}
protected setupDefaults(configData: WidgetConfigComponentData) {
this.setupDefaultDatasource(configData,
[{ name: 'temperature', label: 'Temperature', type: DataKeyType.timeseries, units: '°C', decimals: 0 }]);
}
protected onConfigSet(configData: WidgetConfigComponentData) {
this.flotWidgetConfigForm = this.fb.group({
timewindowConfig: [getTimewindowConfig(configData.config), []],
datasources: [configData.config.datasources, []],
series: [this.getSeries(configData.config.datasources), []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
showTitleIcon: [configData.config.showTitleIcon, []],
titleIcon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
cardButtons: [this.getCardButtons(configData.config), []],
color: [configData.config.color, []],
backgroundColor: [configData.config.backgroundColor, []],
verticalLines: [configData.config.settings?.grid?.verticalLines, []],
horizontalLines: [configData.config.settings?.grid?.horizontalLines, []],
showLegend: [configData.config.settings?.showLegend, []],
legendConfig: [configData.config.settings?.legendConfig, []],
actions: [configData.config.actions || {}, []]
});
}
protected prepareOutputConfig(config: any): WidgetConfigComponentData {
this.widgetConfig.config.useDashboardTimewindow = config.timewindowConfig.useDashboardTimewindow;
this.widgetConfig.config.displayTimewindow = config.timewindowConfig.displayTimewindow;
this.widgetConfig.config.timewindow = config.timewindowConfig.timewindow;
this.widgetConfig.config.datasources = config.datasources;
this.setSeries(config.series, this.widgetConfig.config.datasources);
this.widgetConfig.config.actions = config.actions;
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.title = config.title;
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
this.widgetConfig.config.titleIcon = config.titleIcon;
this.widgetConfig.config.iconColor = config.iconColor;
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
this.widgetConfig.config.backgroundColor = config.backgroundColor;
this.widgetConfig.config.settings.grid = this.widgetConfig.config.settings.grid || {};
this.widgetConfig.config.settings.grid.verticalLines = config.verticalLines;
this.widgetConfig.config.settings.grid.horizontalLines = config.horizontalLines;
this.widgetConfig.config.settings.showLegend = config.showLegend;
this.widgetConfig.config.settings.legendConfig = config.legendConfig;
return this.widgetConfig;
}
protected validatorTriggers(): string[] {
return ['showTitle', 'showTitleIcon', 'showLegend'];
}
protected updateValidators(emitEvent: boolean, trigger?: string) {
const showTitle: boolean = this.flotWidgetConfigForm.get('showTitle').value;
const showTitleIcon: boolean = this.flotWidgetConfigForm.get('showTitleIcon').value;
const showLegend: boolean = this.flotWidgetConfigForm.get('showLegend').value;
if (showTitle) {
this.flotWidgetConfigForm.get('title').enable();
this.flotWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
if (showTitleIcon) {
this.flotWidgetConfigForm.get('titleIcon').enable();
this.flotWidgetConfigForm.get('iconColor').enable();
} else {
this.flotWidgetConfigForm.get('titleIcon').disable();
this.flotWidgetConfigForm.get('iconColor').disable();
}
} else {
this.flotWidgetConfigForm.get('title').disable();
this.flotWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
this.flotWidgetConfigForm.get('titleIcon').disable();
this.flotWidgetConfigForm.get('iconColor').disable();
}
if (showLegend) {
this.flotWidgetConfigForm.get('legendConfig').enable();
} else {
this.flotWidgetConfigForm.get('legendConfig').disable();
}
this.flotWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
this.flotWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});
this.flotWidgetConfigForm.get('legendConfig').updateValueAndValidity({emitEvent});
}
private getSeries(datasources?: Datasource[]): DataKey[] {
if (datasources && datasources.length) {
return datasources[0].dataKeys || [];
}
return [];
}
private setSeries(series: DataKey[], datasources?: Datasource[]) {
if (datasources && datasources.length) {
datasources[0].dataKeys = series;
}
}
private getCardButtons(config: WidgetConfig): string[] {
const buttons: string[] = [];
if (isUndefined(config.enableFullscreen) || config.enableFullscreen) {
buttons.push('fullscreen');
}
return buttons;
}
private setCardButtons(buttons: string[], config: WidgetConfig) {
config.enableFullscreen = buttons.includes('fullscreen');
}
}

2
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html

@ -153,7 +153,7 @@
</tb-widget-units> </tb-widget-units>
</div> </div>
<div class="tb-decimals-field"> <div class="tb-decimals-field">
<mat-form-field *ngIf="displayUnitsOrDigits" appearance="outline" class="tb-inline-field center number" subscriptSizing="dynamic"> <mat-form-field *ngIf="displayUnitsOrDigits" appearance="outline" class="tb-inline-field number" subscriptSizing="dynamic">
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>

3
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts

@ -154,8 +154,7 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
} }
get hasAdditionalLatestDataKeys(): boolean { get hasAdditionalLatestDataKeys(): boolean {
return this.widgetConfigComponent.widgetType === widgetType.timeseries && return this.dataKeysPanelComponent.hasAdditionalLatestDataKeys;
this.widgetConfigComponent.modelValue?.typeParameters?.hasAdditionalLatestDataKeys;
} }
get widget(): Widget { get widget(): Widget {

6
ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts

@ -100,6 +100,10 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
@coerceBoolean() @coerceBoolean()
hideDataKeyColor = false; hideDataKeyColor = false;
@Input()
@coerceBoolean()
hideSourceSelection = false;
dataKeyType: DataKeyType; dataKeyType: DataKeyType;
alarmKeys: Array<DataKey>; alarmKeys: Array<DataKey>;
functionTypeKeys: Array<DataKey>; functionTypeKeys: Array<DataKey>;
@ -117,7 +121,7 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
} }
get hasAdditionalLatestDataKeys(): boolean { get hasAdditionalLatestDataKeys(): boolean {
return this.widgetConfigComponent.widgetType === widgetType.timeseries && return !this.hideSourceSelection && this.widgetConfigComponent.widgetType === widgetType.timeseries &&
this.widgetConfigComponent.modelValue?.typeParameters?.hasAdditionalLatestDataKeys; this.widgetConfigComponent.modelValue?.typeParameters?.hasAdditionalLatestDataKeys;
} }

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

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<div class="tb-datakey-config" *ngIf="dataKeyConfigMode === dataKeyConfigModes.general; else advanced" <div *ngIf="dataKeyConfigMode === dataKeyConfigModes.general; else advanced"
[formGroup]="dataKeyFormGroup"> [formGroup]="dataKeyFormGroup">
<div class="mat-padding" fxLayout="column" style="gap: 16px;"> <div class="mat-padding" fxLayout="column" style="gap: 16px;">
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
@ -54,7 +54,7 @@
</div> </div>
<div class="tb-widget-config-row space-between" *ngIf="!hideDataKeyDecimals"> <div class="tb-widget-config-row space-between" *ngIf="!hideDataKeyDecimals">
<div translate>widget-config.decimals-short</div> <div translate>widget-config.decimals-short</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
@ -182,14 +182,12 @@
</div> </div>
</div> </div>
<ng-template #advanced> <ng-template #advanced>
<div class="tb-datakey-config" [formGroup]="dataKeySettingsFormGroup"> <div class="mat-padding" fxLayout="column" [formGroup]="dataKeySettingsFormGroup">
<div class="mat-padding" fxLayout="column"> <tb-widget-settings
<tb-widget-settings [dashboard]="dashboard"
[dashboard]="dashboard" [aliasController]="aliasController"
[aliasController]="aliasController" [widget]="widget"
[widget]="widget" formControlName="settings">
formControlName="settings"> </tb-widget-settings>
</tb-widget-settings>
</div>
</div> </div>
</ng-template> </ng-template>

107
ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.scss

@ -1,107 +0,0 @@
/**
* 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 '../../../../../../scss/constants';
:host {
.tb-datakey-config {
.fields-group {
padding: 0 16px 8px;
margin-bottom: 10px;
border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px;
legend {
color: rgba(0, 0, 0, .7);
width: fit-content;
}
legend + * {
display: block;
margin-top: 16px;
}
&.fields-group-slider {
padding: 0;
legend {
margin-left: 16px;
}
> .tb-settings {
margin-top: 0;
padding: 0 16px 8px;
}
}
}
.tb-hint.after-fields {
margin-top: -0.75em;
max-width: fit-content;
line-height: 15px;
}
}
}
:host ::ng-deep {
.tb-datakey-config {
.mat-expansion-panel {
&.tb-settings {
box-shadow: none;
.mat-content {
overflow: visible;
}
.mat-expansion-panel-header {
padding: 0;
color: rgba(0, 0, 0, 0.87);
&:hover {
background: none;
}
.mat-expansion-indicator {
padding: 2px;
}
}
&.comparison {
.mat-expansion-panel-header {
height: fit-content;
}
}
.mat-expansion-panel-header-description {
align-items: center;
}
> .mat-expansion-panel-content {
> .mat-expansion-panel-body {
padding: 0;
}
}
}
.mat-expansion-panel-content {
font: inherit;
}
}
.mat-slide {
margin: 8px 0;
}
}
}

2
ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts

@ -57,7 +57,7 @@ import { coerceBoolean } from '@shared/decorators/coercion';
@Component({ @Component({
selector: 'tb-data-key-config', selector: 'tb-data-key-config',
templateUrl: './data-key-config.component.html', templateUrl: './data-key-config.component.html',
styleUrls: ['./data-key-config.component.scss'], styleUrls: [],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

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

@ -69,7 +69,7 @@ export class DatasourcesComponent implements ControlValueAccessor, OnInit, Valid
} }
public get maxDatasources(): number { public get maxDatasources(): number {
return this.widgetConfigComponent.modelValue?.typeParameters?.maxDatasources; return this.forceSingleDatasource ? 1 : this.widgetConfigComponent.modelValue?.typeParameters?.maxDatasources;
} }
public get singleDatasource(): boolean { public get singleDatasource(): boolean {
@ -108,6 +108,10 @@ export class DatasourcesComponent implements ControlValueAccessor, OnInit, Valid
@coerceBoolean() @coerceBoolean()
hideDataKeys = false; hideDataKeys = false;
@Input()
@coerceBoolean()
forceSingleDatasource = false;
@Input() @Input()
configMode: WidgetConfigMode; configMode: WidgetConfigMode;
@ -175,13 +179,20 @@ export class DatasourcesComponent implements ControlValueAccessor, OnInit, Valid
this.datasourcesMode = this.detectDatasourcesMode(datasources); this.datasourcesMode = this.detectDatasourcesMode(datasources);
let changed = false; let changed = false;
if (datasources) { if (datasources) {
datasources.forEach((datasource) => { let length;
if (this.maxDatasources === -1) {
length = datasources.length;
} else {
length = Math.min(this.maxDatasources, datasources.length);
}
for (let i = 0; i < length; i++) {
const datasource = datasources[i];
if (this.basicMode && datasource.type !== this.datasourcesMode) { if (this.basicMode && datasource.type !== this.datasourcesMode) {
datasource.type = this.datasourcesMode; datasource.type = this.datasourcesMode;
changed = true; changed = true;
} }
this.datasourcesFormArray.push(this.fb.control(datasource, []), {emitEvent: false}); this.datasourcesFormArray.push(this.fb.control(datasource, []), {emitEvent: false});
}); }
} }
if (this.singleDatasource && !this.datasourcesFormArray.length) { if (this.singleDatasource && !this.datasourcesFormArray.length) {
this.addDatasource(false); this.addDatasource(false);

11
ui-ngx/src/app/modules/home/components/widget/config/timewindow-config-panel.component.ts

@ -17,10 +17,11 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { widgetType } from '@shared/models/widget.models'; import { WidgetConfig, widgetType } from '@shared/models/widget.models';
import { Timewindow } from '@shared/models/time/time.models'; import { Timewindow } from '@shared/models/time/time.models';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
import { isDefined } from '@core/utils';
export interface TimewindowConfigData { export interface TimewindowConfigData {
useDashboardTimewindow: boolean; useDashboardTimewindow: boolean;
@ -28,6 +29,14 @@ export interface TimewindowConfigData {
timewindow: Timewindow; timewindow: Timewindow;
} }
export const getTimewindowConfig = (config: WidgetConfig): TimewindowConfigData => ({
useDashboardTimewindow: isDefined(config.useDashboardTimewindow) ?
config.useDashboardTimewindow : true,
displayTimewindow: isDefined(config.displayTimewindow) ?
config.displayTimewindow : true,
timewindow: config.timewindow
});
@Component({ @Component({
selector: 'tb-timewindow-config-panel', selector: 'tb-timewindow-config-panel',
templateUrl: './timewindow-config-panel.component.html', templateUrl: './timewindow-config-panel.component.html',

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

@ -15,6 +15,6 @@
limitations under the License. limitations under the License.
--> -->
<mat-form-field appearance="outline" class="tb-inline-field center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="tb-inline-field" subscriptSizing="dynamic">
<input matInput [formControl]="unitsFormControl" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput [formControl]="unitsFormControl" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>

8
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.html

@ -19,20 +19,20 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div> <div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<div>{{ 'widgets.table.custom-title' | translate }}</div> <div class="fixed-title-width">{{ 'widgets.table.custom-title' | translate }}</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="customTitle" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="customTitle" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.column-width' | translate }}</div> <div>{{ 'widgets.table.column-width' | translate }}</div>
<mat-form-field appearance="outline" class="center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="columnWidth" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="columnWidth" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.default-column-visibility' | translate }}</div> <div>{{ 'widgets.table.default-column-visibility' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="defaultColumnVisibility"> <mat-select formControlName="defaultColumnVisibility">
<mat-option [value]="'visible'"> <mat-option [value]="'visible'">
{{ 'widgets.table.column-visibility-visible' | translate }} {{ 'widgets.table.column-visibility-visible' | translate }}
@ -48,7 +48,7 @@
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.column-selection-to-display' | translate }}</div> <div>{{ 'widgets.table.column-selection-to-display' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="columnSelectionToDisplay"> <mat-select formControlName="columnSelectionToDisplay">
<mat-option [value]="'enabled'"> <mat-option [value]="'enabled'">
{{ 'widgets.table.column-selection-to-display-enabled' | translate }} {{ 'widgets.table.column-selection-to-display-enabled' | translate }}

14
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html

@ -19,7 +19,7 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.table-header</div> <div class="tb-widget-config-panel-title" translate>widgets.table.table-header</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<div>{{ 'widgets.table.entities-table-title' | translate }}</div> <div class="fixed-title-width">{{ 'widgets.table.entities-table-title' | translate }}</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="entitiesTitle" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="entitiesTitle" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
@ -31,10 +31,10 @@
</div> </div>
<div class="tb-widget-config-panel stroked"> <div class="tb-widget-config-panel stroked">
<div class="tb-widget-config-panel-title" translate>widgets.table.header-buttons</div> <div class="tb-widget-config-panel-title" translate>widgets.table.header-buttons</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSearch"> <mat-slide-toggle class="mat-slide" formControlName="enableSearch">
{{ 'widgets.table.enable-search' | translate }} {{ 'widgets.table.enable-search' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSelectColumnDisplay"> <mat-slide-toggle class="mat-slide" formControlName="enableSelectColumnDisplay">
{{ 'widgets.table.enable-select-column-display' | translate }} {{ 'widgets.table.enable-select-column-display' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
@ -42,7 +42,7 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.columns</div> <div class="tb-widget-config-panel-title" translate>widgets.table.columns</div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="displayEntityName"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="displayEntityName">
{{ 'widgets.table.display-entity-name' | translate }} {{ 'widgets.table.display-entity-name' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
@ -50,7 +50,7 @@
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row"> <div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="displayEntityName"> <mat-slide-toggle class="mat-slide fixed-title-width" formControlName="displayEntityName">
{{ 'widgets.table.display-entity-label' | translate }} {{ 'widgets.table.display-entity-label' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
@ -85,12 +85,12 @@
</div> </div>
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.pagination</div> <div class="tb-widget-config-panel-title" translate>widgets.table.pagination</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="displayPagination"> <mat-slide-toggle class="mat-slide" formControlName="displayPagination">
{{ 'widgets.table.display-pagination' | translate }} {{ 'widgets.table.display-pagination' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widgets.table.default-page-size</div> <div translate>widgets.table.default-page-size</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="defaultPageSize" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="defaultPageSize" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>

4
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.html

@ -20,7 +20,7 @@
<div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div> <div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.default-column-visibility' | translate }}</div> <div>{{ 'widgets.table.default-column-visibility' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="defaultColumnVisibility"> <mat-select formControlName="defaultColumnVisibility">
<mat-option [value]="'visible'"> <mat-option [value]="'visible'">
{{ 'widgets.table.column-visibility-visible' | translate }} {{ 'widgets.table.column-visibility-visible' | translate }}
@ -36,7 +36,7 @@
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.column-selection-to-display' | translate }}</div> <div>{{ 'widgets.table.column-selection-to-display' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="columnSelectionToDisplay"> <mat-select formControlName="columnSelectionToDisplay">
<mat-option [value]="'enabled'"> <mat-option [value]="'enabled'">
{{ 'widgets.table.column-selection-to-display-enabled' | translate }} {{ 'widgets.table.column-selection-to-display-enabled' | translate }}

8
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.html

@ -18,18 +18,18 @@
<ng-container [formGroup]="timeseriesTableLatestKeySettingsForm"> <ng-container [formGroup]="timeseriesTableLatestKeySettingsForm">
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div> <div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="show"> <mat-slide-toggle class="mat-slide" formControlName="show">
{{ 'widgets.table.show-latest-data-column' | translate }} {{ 'widgets.table.show-latest-data-column' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between"> <div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
<div translate>widgets.table.latest-data-column-order</div> <div translate>widgets.table.latest-data-column-order</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="order" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="order" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between"> <div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.default-column-visibility' | translate }}</div> <div>{{ 'widgets.table.default-column-visibility' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="defaultColumnVisibility"> <mat-select formControlName="defaultColumnVisibility">
<mat-option [value]="'visible'"> <mat-option [value]="'visible'">
{{ 'widgets.table.column-visibility-visible' | translate }} {{ 'widgets.table.column-visibility-visible' | translate }}
@ -45,7 +45,7 @@
</div> </div>
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between"> <div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
<div>{{ 'widgets.table.column-selection-to-display' | translate }}</div> <div>{{ 'widgets.table.column-selection-to-display' | translate }}</div>
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="columnSelectionToDisplay"> <mat-select formControlName="columnSelectionToDisplay">
<mat-option [value]="'enabled'"> <mat-option [value]="'enabled'">
{{ 'widgets.table.column-selection-to-display-enabled' | translate }} {{ 'widgets.table.column-selection-to-display-enabled' | translate }}

20
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html

@ -18,25 +18,25 @@
<ng-container [formGroup]="timeseriesTableWidgetSettingsForm"> <ng-container [formGroup]="timeseriesTableWidgetSettingsForm">
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.table-header</div> <div class="tb-widget-config-panel-title" translate>widgets.table.table-header</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableStickyHeader"> <mat-slide-toggle class="mat-slide" formControlName="enableStickyHeader">
{{ 'widgets.table.enable-sticky-header' | translate }} {{ 'widgets.table.enable-sticky-header' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSearch"> <mat-slide-toggle class="mat-slide" formControlName="enableSearch">
{{ 'widgets.table.enable-search' | translate }} {{ 'widgets.table.enable-search' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSelectColumnDisplay"> <mat-slide-toggle class="mat-slide" formControlName="enableSelectColumnDisplay">
{{ 'widgets.table.enable-select-column-display' | translate }} {{ 'widgets.table.enable-select-column-display' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.columns</div> <div class="tb-widget-config-panel-title" translate>widgets.table.columns</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="showTimestamp"> <mat-slide-toggle class="mat-slide" formControlName="showTimestamp">
{{ 'widgets.table.display-timestamp' | translate }} {{ 'widgets.table.display-timestamp' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle class="mat-slide no-margin" formControlName="showMilliseconds"> <mat-slide-toggle class="mat-slide" formControlName="showMilliseconds">
{{ 'widgets.table.display-milliseconds' | translate }} {{ 'widgets.table.display-milliseconds' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableStickyAction"> <mat-slide-toggle class="mat-slide" formControlName="enableStickyAction">
{{ 'widgets.table.enable-sticky-action' | translate }} {{ 'widgets.table.enable-sticky-action' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex subscriptSizing="dynamic"> <mat-form-field fxFlex subscriptSizing="dynamic">
@ -53,25 +53,25 @@
</div> </div>
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.pagination</div> <div class="tb-widget-config-panel-title" translate>widgets.table.pagination</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="displayPagination"> <mat-slide-toggle class="mat-slide" formControlName="displayPagination">
{{ 'widgets.table.display-pagination' | translate }} {{ 'widgets.table.display-pagination' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widgets.table.default-page-size</div> <div translate>widgets.table.default-page-size</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="defaultPageSize" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="defaultPageSize" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>widgets.table.table-tabs</div> <div class="tb-widget-config-panel-title" translate>widgets.table.table-tabs</div>
<mat-slide-toggle class="mat-slide no-margin" formControlName="useEntityLabel"> <mat-slide-toggle class="mat-slide" formControlName="useEntityLabel">
{{ 'widgets.table.use-entity-label-tab-name' | translate }} {{ 'widgets.table.use-entity-label-tab-name' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
<div class="tb-widget-config-panel tb-slide-toggle"> <div class="tb-widget-config-panel tb-slide-toggle">
<div class="tb-widget-config-panel-title" style="padding-bottom: 16px;" translate>widgets.table.rows</div> <div class="tb-widget-config-panel-title" style="padding-bottom: 16px;" translate>widgets.table.rows</div>
<mat-slide-toggle class="mat-slide no-margin" style="padding-left: 16px;" formControlName="hideEmptyLines"> <mat-slide-toggle class="mat-slide" style="padding-left: 16px;" formControlName="hideEmptyLines">
{{ 'widgets.table.hide-empty-lines' | translate }} {{ 'widgets.table.hide-empty-lines' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableWidgetSettingsForm.get('useRowStyleFunction').value"> <mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableWidgetSettingsForm.get('useRowStyleFunction').value">

257
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.html

@ -15,81 +15,85 @@
limitations under the License. limitations under the License.
--> -->
<section class="tb-widget-settings" [formGroup]="flotKeySettingsFormGroup" fxLayout="column"> <ng-container [formGroup]="flotKeySettingsFormGroup">
<fieldset class="fields-group" fxLayout="column"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.common-settings</legend> <mat-slide-toggle class="mat-slide" formControlName="hideDataByDefault">
<mat-checkbox formControlName="hideDataByDefault">
{{ 'widgets.chart.data-is-hidden-by-default' | translate }} {{ 'widgets.chart.data-is-hidden-by-default' | translate }}
</mat-checkbox> </mat-slide-toggle>
<mat-checkbox formControlName="disableDataHiding"> <mat-slide-toggle class="mat-slide" formControlName="disableDataHiding">
{{ 'widgets.chart.disable-data-hiding' | translate }} {{ 'widgets.chart.disable-data-hiding' | translate }}
</mat-checkbox> </mat-slide-toggle>
<mat-checkbox formControlName="removeFromLegend"> <mat-slide-toggle class="mat-slide" formControlName="removeFromLegend">
{{ 'widgets.chart.remove-from-legend' | translate }} {{ 'widgets.chart.remove-from-legend' | translate }}
</mat-checkbox> </mat-slide-toggle>
<mat-checkbox formControlName="excludeFromStacking"> <mat-slide-toggle class="mat-slide" formControlName="excludeFromStacking">
{{ 'widgets.chart.exclude-from-stacking' | translate }} {{ 'widgets.chart.exclude-from-stacking' | translate }}
</mat-checkbox> </mat-slide-toggle>
</fieldset> </div>
<fieldset class="fields-group fields-group-slider"> <div class="tb-widget-config-panel tb-slide-toggle">
<legend class="group-title" translate>widgets.chart.line-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showLines').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showLines').value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="showLines" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="showLines" (click)="$event.stopPropagation()"
fxLayoutAlign="center"> fxLayoutAlign="center">
{{ 'widgets.chart.show-line' | translate }} {{ 'widgets.chart.show-line' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<section fxFlex fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center"> <div class="tb-widget-config-row space-between">
<mat-form-field fxFlex class="mat-block"> <div>{{ 'widgets.chart.line-width' | translate }}</div>
<mat-label translate>widgets.chart.line-width</mat-label> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput type="number" min="0" formControlName="lineWidth"> <input matInput formControlName="lineWidth" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
<span matSuffix>px</span>
</mat-form-field> </mat-form-field>
<mat-checkbox formControlName="fillLines"> </div>
{{ 'widgets.chart.fill-line' | translate }} <mat-slide-toggle class="mat-slide" formControlName="fillLines">
</mat-checkbox> {{ 'widgets.chart.fill-line' | translate }}
<mat-form-field fxFlex class="mat-block"> </mat-slide-toggle>
<mat-label translate>widgets.chart.fill-line-opacity</mat-label> <div [fxShow]="flotKeySettingsFormGroup.get('fillLines').value" class="tb-widget-config-row space-between">
<input matInput type="number" min="0" max="1" step="0.1" formControlName="fillLinesOpacity"> <div>{{ 'widgets.chart.fill-line-opacity' | translate }}</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="fillLinesOpacity" type="number" min="0" max="1" step="0.1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</section> </div>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
<fieldset class="fields-group fields-group-slider"> <div class="tb-widget-config-panel tb-slide-toggle">
<legend class="group-title" translate>widgets.chart.points-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showPoints').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('showPoints').value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="showPoints" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="showPoints" (click)="$event.stopPropagation()"
fxLayoutAlign="center"> fxLayoutAlign="center">
{{ 'widgets.chart.show-points' | translate }} {{ 'widgets.chart.show-points' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<section fxLayout="column"> <div class="tb-widget-config-row space-between">
<section fxFlex fxLayout="row" fxLayoutGap="8px"> <div>{{ 'widgets.chart.points-line-width' | translate }}</div>
<mat-form-field fxFlex class="mat-block"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<mat-label translate>widgets.chart.points-line-width</mat-label> <input matInput formControlName="showPointsLineWidth" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
<input matInput type="number" min="0" formControlName="showPointsLineWidth"> <span matSuffix>px</span>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.points-radius</mat-label> <div class="tb-widget-config-row space-between">
<input matInput type="number" min="0" formControlName="showPointsRadius"> <div>{{ 'widgets.chart.points-radius' | translate }}</div>
</mat-form-field> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
</section> <input matInput formControlName="showPointsRadius" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
<mat-form-field fxFlex class="mat-block"> <span matSuffix>px</span>
<mat-label translate>widgets.chart.point-shape</mat-label> </mat-form-field>
</div>
<div class="tb-widget-config-row space-between">
<div>{{ 'widgets.chart.point-shape' | translate }}</div>
<mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="showPointShape"> <mat-select formControlName="showPointShape">
<mat-option [value]="'circle'"> <mat-option [value]="'circle'">
{{ 'widgets.chart.point-shape-circle' | translate }} {{ 'widgets.chart.point-shape-circle' | translate }}
@ -111,19 +115,19 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<tb-js-func [fxShow]="flotKeySettingsFormGroup.get('showPointShape').value === 'custom'" </div>
formControlName="pointShapeFormatter" <tb-js-func [fxShow]="flotKeySettingsFormGroup.get('showPointShape').value === 'custom'"
[globalVariables]="functionScopeVariables" formControlName="pointShapeFormatter"
[functionArgs]="['ctx', 'x', 'y', 'radius', 'shadow']" [globalVariables]="functionScopeVariables"
functionTitle="{{ 'widgets.chart.point-shape-draw-function' | translate }}" [functionArgs]="['ctx', 'x', 'y', 'radius', 'shadow']"
helpId="widget/lib/flot/point_shape_format_fn"> functionTitle="{{ 'widgets.chart.point-shape-draw-function' | translate }}"
</tb-js-func> helpId="widget/lib/flot/point_shape_format_fn">
</section> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
<fieldset class="fields-group"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.tooltip-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.tooltip-settings</div>
<tb-js-func <tb-js-func
formControlName="tooltipValueFormatter" formControlName="tooltipValueFormatter"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
@ -131,49 +135,57 @@
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}" functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
helpId="widget/lib/flot/tooltip_value_format_fn"> helpId="widget/lib/flot/tooltip_value_format_fn">
</tb-js-func> </tb-js-func>
</fieldset> </div>
<fieldset class="fields-group"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.yaxis-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.vertical-axis</div>
<mat-slide-toggle formControlName="showSeparateAxis" class="slide-block"> <mat-slide-toggle class="mat-slide" formControlName="showSeparateAxis">
{{ 'widgets.chart.show-separate-axis' | translate }} {{ 'widgets.chart.show-separate-axis' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-form-field fxFlex class="mat-block"> <div class="tb-widget-config-row">
<mat-label translate>widgets.chart.axis-title</mat-label> <div class="fixed-title-width" translate>widgets.chart.axis-title</div>
<input matInput formControlName="axisTitle"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
</mat-form-field> <input matInput formControlName="axisTitle" placeholder="{{ 'widget-config.set' | translate }}">
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.min-scale-value</mat-label>
<input matInput type="number" formControlName="axisMin">
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.max-scale-value</mat-label> <div class="tb-widget-config-row space-between">
<input matInput type="number" formControlName="axisMax"> <div translate>widgets.chart.min-scale-value</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="axisMin" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</section> </div>
<mat-form-field fxFlex class="mat-block"> <div class="tb-widget-config-row space-between">
<mat-label translate>widgets.chart.axis-position</mat-label> <div translate>widgets.chart.max-scale-value</div>
<mat-select formControlName="axisPosition"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<mat-option [value]="'left'"> <input matInput formControlName="axisMax" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
{{ 'widgets.chart.axis-position-left' | translate }} </mat-form-field>
</mat-option> </div>
<mat-option [value]="'right'"> <div class="tb-widget-config-row space-between">
{{ 'widgets.chart.axis-position-right' | translate }} <div>{{ 'widgets.chart.axis-position' | translate }}</div>
</mat-option> <mat-form-field appearance="outline" subscriptSizing="dynamic">
</mat-select> <mat-select formControlName="axisPosition">
</mat-form-field> <mat-option [value]="'left'">
<fieldset class="fields-group"> {{ 'widgets.chart.axis-position-left' | translate }}
<legend class="group-title" translate>widgets.chart.yaxis-tick-labels-settings</legend> </mat-option>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px"> <mat-option [value]="'right'">
<mat-form-field fxFlex class="mat-block"> {{ 'widgets.chart.axis-position-right' | translate }}
<mat-label translate>widgets.chart.tick-step-size</mat-label> </mat-option>
<input matInput type="number" formControlName="axisTickSize"> </mat-select>
</mat-form-field>
</div>
<div class="tb-widget-config-panel stroked">
<div class="tb-widget-config-panel-title" translate>widgets.chart.ticks</div>
<div class="tb-widget-config-row space-between">
<div translate>widget-config.decimals-short</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="axisTickDecimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.number-of-decimals</mat-label> <div class="tb-widget-config-row space-between">
<input matInput type="number" min="0" formControlName="axisTickDecimals"> <div translate>widgets.chart.tick-step-size</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="axisTickSize" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</section> </div>
<tb-js-func <tb-js-func
formControlName="axisTicksFormatter" formControlName="axisTicksFormatter"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
@ -181,36 +193,31 @@
functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}" functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}"
helpId="widget/lib/flot/ticks_formatter_fn"> helpId="widget/lib/flot/ticks_formatter_fn">
</tb-js-func> </tb-js-func>
</fieldset> </div>
</fieldset> </div>
<fieldset class="fields-group"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.thresholds</legend> <div class="tb-widget-config-panel-title" fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="column"> <div translate>widgets.chart.thresholds</div>
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical" <button mat-stroked-button
(cdkDropListDropped)="thresholdDrop($event)"> color="primary"
<div cdkDrag class="tb-draggable" *ngFor="let thresholdControl of thresholdsFormArray().controls; trackBy: trackByThreshold; type="button" (click)="addThreshold()">
let $index = index; last as isLast;" <span translate>widgets.chart.add-threshold</span>
fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}"> </button>
<tb-flot-threshold [formControl]="thresholdControl" </div>
[expanded]="thresholdControl.new" <div *ngIf="thresholdsFormArray().length" class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
[aliasController]="aliasController" (cdkDropListDropped)="thresholdDrop($event)" fxLayout="column" fxLayoutGap="12px">
(removeThreshold)="removeThreshold($index)"> <div cdkDrag class="tb-draggable" *ngFor="let thresholdControl of thresholdsFormArray().controls; trackBy: trackByThreshold;
</tb-flot-threshold> let $index = index;">
</div> <tb-flot-threshold [formControl]="thresholdControl"
</div> [expanded]="thresholdControl.new"
<div *ngIf="!thresholdsFormArray().controls.length"> [aliasController]="aliasController"
<span translate fxLayoutAlign="center center" (removeThreshold)="removeThreshold($index)">
class="tb-prompt">widgets.chart.no-thresholds</span> </tb-flot-threshold>
</div>
<div style="padding-top: 16px;">
<button mat-raised-button color="primary"
type="button"
(click)="addThreshold()">
<span translate>widgets.chart.add-threshold</span>
</button>
</div> </div>
</div> </div>
</fieldset> </div>
</ng-container>
<section class="tb-widget-settings" [formGroup]="flotKeySettingsFormGroup" fxLayout="column">
<fieldset class="fields-group fields-group-slider" formGroupName="comparisonSettings" > <fieldset class="fields-group fields-group-slider" formGroupName="comparisonSettings" >
<legend class="group-title" translate>widgets.chart.comparison-settings</legend> <legend class="group-title" translate>widgets.chart.comparison-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('comparisonSettings.showValuesForComparison').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotKeySettingsFormGroup.get('comparisonSettings.showValuesForComparison').value">

1
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-key-settings.component.ts

@ -225,6 +225,7 @@ export class FlotKeySettingsComponent extends PageComponent implements OnInit, C
this.flotKeySettingsFormGroup.disable({emitEvent: false}); this.flotKeySettingsFormGroup.disable({emitEvent: false});
} else { } else {
this.flotKeySettingsFormGroup.enable({emitEvent: false}); this.flotKeySettingsFormGroup.enable({emitEvent: false});
this.updateValidators(false);
} }
} }

74
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.html

@ -15,44 +15,38 @@
limitations under the License. limitations under the License.
--> -->
<mat-expansion-panel class="flot-threshold" fxFlex [formGroup]="thresholdFormGroup" [(expanded)]="expanded"> <div class="tb-flot-threshold">
<mat-expansion-panel-header> <mat-expansion-panel class="tb-settings" fxFlex [formGroup]="thresholdFormGroup" [(expanded)]="expanded">
<div fxFlex fxLayout="row" fxLayoutAlign="start center"> <mat-expansion-panel-header class="fill-width">
<mat-panel-title> <div class="tb-threshold-header">
<div fxLayout="row" fxFlex fxLayoutAlign="start center"> <div class="tb-threshold-text">{{ thresholdText() }}</div>
<div>{{ thresholdText() }}</div> <mat-divider vertical></mat-divider>
<div class="tb-color-preview" style="margin-left: 6px;"> <tb-color-input asBoxInput
<div class="tb-color-result" [ngStyle]="{background: thresholdFormGroup.get('color').value}"></div> formControlName="color">
</div> </tb-color-input>
</div> <mat-divider vertical></mat-divider>
</mat-panel-title> </div>
<span fxFlex></span> </mat-expansion-panel-header>
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;" <ng-template matExpansionPanelContent>
type="button" <tb-value-source [aliasController]="aliasController" formControlName="valueSource"></tb-value-source>
(click)="removeThreshold.emit()" <section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
matTooltip="{{ 'action.remove' | translate }}" <mat-form-field fxFlex class="mat-block">
matTooltipPosition="above"> <mat-label translate>widgets.chart.line-width</mat-label>
<mat-icon>delete</mat-icon> <input type="number" min="0" matInput formControlName="lineWidth">
</button> </mat-form-field>
</div> <tb-color-input fxFlex
</mat-expansion-panel-header> formControlName="color"
<ng-template matExpansionPanelContent> icon="format_color_fill"
<div fxLayout="column" fxLayoutGap="0.5em"> label="{{ 'widgets.chart.color' | translate }}" openOnInput colorClearButton>
<mat-divider></mat-divider> </tb-color-input>
<section class="tb-widget-settings" fxLayout="column">
<tb-value-source [aliasController]="aliasController" formControlName="valueSource"></tb-value-source>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.line-width</mat-label>
<input type="number" min="0" matInput formControlName="lineWidth">
</mat-form-field>
<tb-color-input fxFlex
formControlName="color"
icon="format_color_fill"
label="{{ 'widgets.chart.color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</section>
</section> </section>
</div> </ng-template>
</ng-template> </mat-expansion-panel>
</mat-expansion-panel> <button *ngIf="!disabled" mat-icon-button
type="button"
(click)="removeThreshold.emit()"
matTooltip="{{ 'action.remove' | translate }}"
matTooltipPosition="above">
<mat-icon>delete</mat-icon>
</button>
</div>

62
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.scss

@ -13,28 +13,58 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
:host {
display: block; .tb-flot-threshold {
display: flex;
flex-direction: row;
align-items: start;
gap: 4px;
.mat-expansion-panel { .mat-expansion-panel {
box-shadow: none; box-shadow: none;
&.flot-threshold { border-radius: 6px;
border: 1px groove rgba(0, 0, 0, .25); border: 1px solid rgba(0, 0, 0, 0.12);
.mat-expansion-panel-header { .mat-expansion-panel-header {
padding: 0 24px 0 8px; height: 56px;
&.mat-expanded { border-radius: 0;
height: 48px; display: flex;
flex-direction: row;
align-items: stretch;
.tb-threshold-header {
flex: 1;
display: flex;
flex-direction: row;
gap: 16px;
align-items: center;
padding-left: 16px;
.mat-divider-vertical {
height: 100%;
} }
} }
.tb-threshold-text {
flex: 1;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 16px;
letter-spacing: 0.15px;
}
.mat-expansion-indicator {
margin-right: 22px;
margin-left: 22px;
margin-top: 12px;
}
} }
} .mat-expansion-panel-body {
} padding: 0 8px 8px;
}
:host ::ng-deep { &.mat-expanded {
.mat-expansion-panel { .mat-expansion-panel-header {
&.flot-threshold { border-bottom: 1px solid rgba(0, 0, 0, 0.12);
.mat-expansion-panel-body {
padding: 0 8px 8px;
} }
} }
} }
.mdc-icon-button {
margin-top: 4px;
color: rgba(0, 0, 0, 0.54);
}
} }

15
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-threshold.component.ts

@ -15,8 +15,14 @@
/// ///
import { ValueSourceProperty } from '@home/components/widget/lib/settings/common/value-source.component'; import { ValueSourceProperty } from '@home/components/widget/lib/settings/common/value-source.component';
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, forwardRef, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
ControlValueAccessor,
NG_VALUE_ACCESSOR,
UntypedFormBuilder,
UntypedFormGroup,
Validators
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@ -28,14 +34,15 @@ import { TbFlotKeyThreshold } from '@home/components/widget/lib/flot-widget.mode
@Component({ @Component({
selector: 'tb-flot-threshold', selector: 'tb-flot-threshold',
templateUrl: './flot-threshold.component.html', templateUrl: './flot-threshold.component.html',
styleUrls: ['./flot-threshold.component.scss', './../widget-settings.scss'], styleUrls: ['./flot-threshold.component.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FlotThresholdComponent), useExisting: forwardRef(() => FlotThresholdComponent),
multi: true multi: true
} }
] ],
encapsulation: ViewEncapsulation.None
}) })
export class FlotThresholdComponent extends PageComponent implements OnInit, ControlValueAccessor { export class FlotThresholdComponent extends PageComponent implements OnInit, ControlValueAccessor {

496
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html

@ -15,35 +15,33 @@
limitations under the License. limitations under the License.
--> -->
<section class="tb-widget-settings" [formGroup]="flotSettingsFormGroup" fxLayout="column"> <ng-container [formGroup]="flotSettingsFormGroup">
<fieldset class="fields-group"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.common-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.common-settings</div>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px" style="margin-bottom: 16px;"> <mat-slide-toggle class="mat-slide" formControlName="stack">
<mat-checkbox fxFlex formControlName="stack"> {{ 'widgets.chart.enable-stacking-mode' | translate }}
{{ 'widgets.chart.enable-stacking-mode' | translate }} </mat-slide-toggle>
</mat-checkbox> <mat-slide-toggle class="mat-slide" formControlName="enableSelection">
<mat-checkbox fxFlex formControlName="enableSelection"> {{ 'widgets.chart.enable-selection-mode' | translate }}
{{ 'widgets.chart.enable-selection-mode' | translate }} </mat-slide-toggle>
</mat-checkbox> <mat-slide-toggle *ngIf="chartType === 'graph'" class="mat-slide" formControlName="smoothLines">
</section> {{ 'widgets.chart.display-smooth-lines' | translate }}
<section *ngIf="chartType === 'graph'" fxLayout="column" fxLayout.gt-xs="row" </mat-slide-toggle>
fxLayoutGap.gt-xs="8px" fxLayoutAlign.gt-xs="start center"> <div *ngIf="chartType === 'graph'" class="tb-widget-config-row space-between">
<mat-form-field fxFlex class="mat-block"> <div translate>widgets.chart.line-shadow-size</div>
<mat-label translate>widgets.chart.line-shadow-size</mat-label> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput type="number" min="0" formControlName="shadowSize"> <input matInput formControlName="shadowSize" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<mat-checkbox fxFlex formControlName="smoothLines"> </div>
{{ 'widgets.chart.display-smooth-lines' | translate }} <div *ngIf="chartType === 'bar'" class="tb-widget-config-row space-between">
</mat-checkbox> <div translate>widgets.chart.default-bar-width</div>
</section> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<section *ngIf="chartType === 'bar'" fxLayout="column" fxLayout.gt-xs="row" <input matInput formControlName="defaultBarWidth" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
fxLayoutGap.gt-xs="8px" fxLayoutAlign.gt-xs="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.default-bar-width</mat-label>
<input matInput type="number" min="0" formControlName="defaultBarWidth">
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.bar-alignment</mat-label> <div *ngIf="chartType === 'bar'" class="tb-widget-config-row space-between">
<div>{{ 'widgets.chart.bar-alignment' | translate }}</div>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="barAlignment"> <mat-select formControlName="barAlignment">
<mat-option [value]="'left'"> <mat-option [value]="'left'">
{{ 'widgets.chart.bar-alignment-left' | translate }} {{ 'widgets.chart.bar-alignment-left' | translate }}
@ -56,211 +54,255 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</section> </div>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px"> <div *ngIf="chartType === 'graph' || chartType === 'bar'" class="tb-widget-config-row space-between">
<mat-form-field fxFlex class="mat-block"> <div translate>widgets.chart.thresholds-line-width</div>
<mat-label translate>widgets.chart.default-font-size</mat-label> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput type="number" min="0" formControlName="fontSize"> <input matInput formControlName="thresholdsLineWidth" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<tb-color-input fxFlex </div>
formControlName="fontColor" <div class="tb-widget-config-row space-between same-padding">
icon="format_color_fill" <div>{{ 'widgets.chart.default-font' | translate }}</div>
label="{{ 'widgets.chart.default-font-color' | translate }}" openOnInput colorClearButton> <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
</tb-color-input> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
</section> <input matInput formControlName="fontSize" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
<mat-form-field *ngIf="chartType === 'graph' || chartType === 'bar'" fxFlex class="mat-block"> <span matSuffix>px</span>
<mat-label translate>widgets.chart.thresholds-line-width</mat-label> </mat-form-field>
<input matInput type="number" min="0" formControlName="thresholdsLineWidth"> <mat-divider vertical></mat-divider>
</mat-form-field> <tb-color-input asBoxInput
</fieldset> formControlName="fontColor">
<fieldset *ngIf="chartType === 'graph' || chartType === 'bar'" class="fields-group fields-group-slider"> </tb-color-input>
<legend class="group-title" translate>widget-config.legend</legend> </div>
</div>
</div>
<div *ngIf="chartType === 'graph' || chartType === 'bar'" class="tb-widget-config-panel tb-slide-toggle">
<div class="tb-widget-config-panel-title" translate>widget-config.legend</div>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('showLegend').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('showLegend').value">
<mat-expansion-panel-header fxLayout="row" style="min-height: 48px;"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title fxFlex="60"> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="showLegend" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="showLegend" (click)="$event.stopPropagation()"
fxLayoutAlign="center" style="height: 100%;"> fxLayoutAlign="center">
{{ 'widget-config.display-legend' | translate }} {{ 'widget-config.legend' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxFlex="40" style="white-space: nowrap;" fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-legend-config formControlName="legendConfig"></tb-legend-config> <tb-legend-config formControlName="legendConfig">
</tb-legend-config>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
<fieldset class="fields-group fields-group-slider"> <div class="tb-widget-config-panel">
<legend class="group-title" translate>widgets.chart.tooltip-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.axis</div>
<div class="tb-widget-config-panel stroked" formGroupName="yaxis">
<div class="tb-widget-config-panel-title" translate>widgets.chart.vertical-axis</div>
<div class="tb-widget-config-row">
<div class="fixed-title-width" translate>widgets.chart.axis-title</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-widget-config-row space-between">
<div translate>widgets.chart.min-scale-value</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="min" type="number" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-widget-config-row space-between">
<div translate>widgets.chart.max-scale-value</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="max" type="number" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-widget-config-panel stroked tb-slide-toggle">
<div class="tb-widget-config-panel-title" translate>widgets.chart.ticks</div>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('yaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title fxFlex="60">
<mat-slide-toggle class="mat-slide" formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.ticks' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widget-config.color' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="color">
</tb-color-input>
</div>
</div>
<div class="tb-widget-config-row space-between">
<div translate>widget-config.decimals-short</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="tickDecimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-widget-config-row space-between">
<div translate>widgets.chart.tick-step-size</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="tickSize" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<tb-js-func
formControlName="ticksFormatter"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value']"
functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}"
helpId="widget/lib/flot/ticks_formatter_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</div>
</div>
<div class="tb-widget-config-panel stroked" formGroupName="xaxis">
<div class="tb-widget-config-panel-title" translate>widgets.chart.horizontal-axis</div>
<div class="tb-widget-config-row">
<div class="fixed-title-width" translate>widgets.chart.axis-title</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-widget-config-panel stroked tb-slide-toggle">
<div class="tb-widget-config-panel-title" translate>widgets.chart.ticks</div>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('xaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title fxFlex="60">
<mat-slide-toggle class="mat-slide" formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.ticks' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widget-config.color' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="color">
</tb-color-input>
</div>
</div>
</ng-template>
</mat-expansion-panel>
</div>
</div>
</div>
<div class="tb-widget-config-panel" formGroupName="grid">
<div class="tb-widget-config-panel-title" translate>widgets.chart.chart-background</div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="verticalLines">
{{ 'widgets.chart.vertical-grid-lines' | translate }}
</mat-slide-toggle>
</div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="horizontalLines">
{{ 'widgets.chart.horizontal-grid-lines' | translate }}
</mat-slide-toggle>
</div>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widgets.chart.grid-lines-color' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="tickColor">
</tb-color-input>
</div>
</div>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widgets.chart.border' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="outlineWidth" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
<span matSuffix>px</span>
</mat-form-field>
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="color">
</tb-color-input>
</div>
</div>
<div class="tb-widget-config-row space-between same-padding">
<div>{{ 'widgets.chart.background-color' | translate }}</div>
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px">
<mat-divider vertical></mat-divider>
<tb-color-input asBoxInput
formControlName="backgroundColor">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-widget-config-panel tb-slide-toggle">
<div class="tb-widget-config-panel-title" translate>widgets.chart.tooltip</div>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('showTooltip').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('showTooltip').value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="showTooltip" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="showTooltip" (click)="$event.stopPropagation()"
fxLayoutAlign="center"> fxLayoutAlign="center">
{{ 'widgets.chart.show-tooltip' | translate }} {{ 'widgets.chart.tooltip' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<section fxLayout="column"> <div class="tb-widget-config-row">
<mat-slide-toggle formControlName="tooltipIndividual" class="slide-block"> <mat-slide-toggle class="mat-slide" formControlName="tooltipIndividual">
{{ 'widgets.chart.hover-individual-points' | translate }} {{ 'widgets.chart.hover-individual-points' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle formControlName="tooltipCumulative" class="slide-block"> </div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="tooltipCumulative">
{{ 'widgets.chart.show-cumulative-values' | translate }} {{ 'widgets.chart.show-cumulative-values' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<mat-slide-toggle formControlName="hideZeros" class="slide-block"> </div>
<div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="hideZeros">
{{ 'widgets.chart.hide-zero-false-values' | translate }} {{ 'widgets.chart.hide-zero-false-values' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<tb-js-func </div>
formControlName="tooltipValueFormatter" <tb-js-func
[globalVariables]="functionScopeVariables" formControlName="tooltipValueFormatter"
[functionArgs]="['value', 'latestData']" [globalVariables]="functionScopeVariables"
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}" [functionArgs]="['value', 'latestData']"
helpId="widget/lib/flot/tooltip_value_format_fn"> functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
</tb-js-func> helpId="widget/lib/flot/tooltip_value_format_fn">
</section> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
<fieldset class="fields-group" formGroupName="grid"> <div *ngIf="chartType === 'graph' || chartType === 'bar'" class="tb-widget-config-panel tb-slide-toggle">
<legend class="group-title" translate>widgets.chart.grid-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.comparison-settings</div>
<mat-checkbox formControlName="verticalLines">
{{ 'widgets.chart.show-vertical-lines' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="horizontalLines">
{{ 'widgets.chart.show-horizontal-lines' | translate }}
</mat-checkbox>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.grid-outline-border-width</mat-label>
<input matInput type="number" min="0" formControlName="outlineWidth">
</mat-form-field>
<tb-color-input fxFlex
formControlName="color"
icon="format_color_fill"
label="{{ 'widgets.chart.primary-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<tb-color-input fxFlex
formControlName="backgroundColor"
icon="format_color_fill"
label="{{ 'widgets.chart.background-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<tb-color-input fxFlex
formControlName="tickColor"
icon="format_color_fill"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</fieldset>
<fieldset class="fields-group" formGroupName="xaxis">
<legend class="group-title" translate>widgets.chart.xaxis-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-title</mat-label>
<input matInput formControlName="title">
</mat-form-field>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.xaxis-tick-labels-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('xaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-color-input fxFlex
formControlName="color"
icon="format_color_fill"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</ng-template>
</mat-expansion-panel>
</fieldset>
</fieldset>
<fieldset class="fields-group" formGroupName="yaxis">
<legend class="group-title" translate>widgets.chart.yaxis-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-title</mat-label>
<input matInput formControlName="title">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.min-scale-value</mat-label>
<input matInput type="number" formControlName="min">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.max-scale-value</mat-label>
<input matInput type="number" formControlName="max">
</mat-form-field>
</section>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.yaxis-tick-labels-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('yaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-color-input fxFlex
formControlName="color"
icon="format_color_fill"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.tick-step-size</mat-label>
<input matInput type="number" formControlName="tickSize">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.number-of-decimals</mat-label>
<input matInput type="number" min="0" formControlName="tickDecimals">
</mat-form-field>
</section>
<tb-js-func
formControlName="ticksFormatter"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value']"
functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}"
helpId="widget/lib/flot/ticks_formatter_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</fieldset>
<fieldset *ngIf="chartType === 'graph' || chartType === 'bar'" class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.comparison-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('comparisonEnabled').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('comparisonEnabled').value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="comparisonEnabled" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="comparisonEnabled" (click)="$event.stopPropagation()"
fxLayoutAlign="center"> fxLayoutAlign="center">
{{ 'widgets.chart.enable-comparison' | translate }} {{ 'widgets.chart.enable-comparison' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<section fxLayout="column"> <div class="tb-widget-config-row space-between">
<mat-form-field fxFlex class="mat-block"> <div>{{ 'widgets.chart.time-for-comparison' | translate }}</div>
<mat-label translate>widgets.chart.time-for-comparison</mat-label> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="timeForComparison"> <mat-select formControlName="timeForComparison">
<mat-option [value]="'previousInterval'"> <mat-option [value]="'previousInterval'">
{{ 'widgets.chart.time-for-comparison-previous-interval' | translate }} {{ 'widgets.chart.time-for-comparison-previous-interval' | translate }}
@ -282,18 +324,29 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field [fxShow]="flotSettingsFormGroup.get('timeForComparison').value === 'customInterval'" fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.custom-interval-value</mat-label> <div [fxShow]="flotSettingsFormGroup.get('timeForComparison').value === 'customInterval'" class="tb-widget-config-row space-between">
<input matInput type="number" min="0" formControlName="comparisonCustomIntervalValue"> <div translate>widgets.chart.custom-interval-value</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="comparisonCustomIntervalValue" type="number" min="0" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<fieldset class="fields-group" formGroupName="xaxisSecond"> </div>
<legend class="group-title" translate>widgets.chart.comparison-x-axis-settings</legend> <div class="tb-widget-config-panel stroked" formGroupName="xaxisSecond">
<mat-form-field fxFlex class="mat-block"> <div class="tb-widget-config-panel-title" translate>widgets.chart.comparison-x-axis-settings</div>
<mat-label translate>widgets.chart.axis-title</mat-label> <div class="tb-widget-config-row">
<input matInput formControlName="title"> <div class="fixed-title-width" translate>widgets.chart.axis-title</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex class="mat-block"> </div>
<mat-label translate>widgets.chart.axis-position</mat-label> <div class="tb-widget-config-row">
<mat-slide-toggle class="mat-slide" formControlName="showLabels">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</div>
<div class="tb-widget-config-row space-between">
<div>{{ 'widgets.chart.axis-position' | translate }}</div>
<mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="axisPosition"> <mat-select formControlName="axisPosition">
<mat-option [value]="'top'"> <mat-option [value]="'top'">
{{ 'widgets.chart.axis-position-top' | translate }} {{ 'widgets.chart.axis-position-top' | translate }}
@ -303,31 +356,28 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-slide-toggle formControlName="showLabels" class="slide-block"> </div>
{{ 'widgets.chart.show-tick-labels' | translate }} </div>
</mat-slide-toggle>
</fieldset>
</section>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
<fieldset *ngIf="chartType === 'graph' || chartType === 'bar'" class="fields-group fields-group-slider"> <div *ngIf="chartType === 'graph' || chartType === 'bar'" class="tb-widget-config-panel tb-slide-toggle">
<legend class="group-title" translate>widgets.chart.custom-legend-settings</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.custom-legend-settings</div>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('customLegendEnabled').value"> <mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('customLegendEnabled').value">
<mat-expansion-panel-header fxLayout="row" style="height: max-content; min-height: 48px;"> <mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
<mat-panel-title fxFlex="60"> <mat-panel-title fxFlex="60">
<mat-slide-toggle formControlName="customLegendEnabled" (click)="$event.stopPropagation()" <mat-slide-toggle class="mat-slide" formControlName="customLegendEnabled" (click)="$event.stopPropagation()"
fxLayoutAlign="center" style="height: 100%;"> fxLayoutAlign="center">
{{ 'widgets.chart.enable-custom-legend' | translate }} {{ 'widgets.chart.enable-custom-legend' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
</mat-panel-title> </mat-panel-title>
<mat-panel-description fxFlex="40" style="white-space: nowrap;" fxLayoutAlign="end center" fxHide.xs translate> <mat-panel-description fxFlex="40" fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings widget-config.advanced-settings
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<fieldset class="fields-group"> <div class="tb-widget-config-panel stroked">
<legend class="group-title" translate>widgets.chart.label-keys-list</legend> <div class="tb-widget-config-panel-title" translate>widgets.chart.label-keys-list</div>
<div fxLayout="column"> <div fxLayout="column">
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical" <div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
(cdkDropListDropped)="labelDataKeyDrop($event)"> (cdkDropListDropped)="labelDataKeyDrop($event)">
@ -353,8 +403,8 @@
</button> </button>
</div> </div>
</div> </div>
</fieldset> </div>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
</fieldset> </div>
</section> </ng-container>

4
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts

@ -284,6 +284,7 @@ export class FlotWidgetSettingsComponent extends PageComponent implements OnInit
this.flotSettingsFormGroup.disable({emitEvent: false}); this.flotSettingsFormGroup.disable({emitEvent: false});
} else { } else {
this.flotSettingsFormGroup.enable({emitEvent: false}); this.flotSettingsFormGroup.enable({emitEvent: false});
this.updateValidators(false);
} }
} }
@ -379,9 +380,11 @@ export class FlotWidgetSettingsComponent extends PageComponent implements OnInit
} else { } else {
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent}); this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent});
} }
this.flotSettingsFormGroup.get('xaxisSecond').enable({emitEvent: false});
} else { } else {
this.flotSettingsFormGroup.get('timeForComparison').disable({emitEvent: false}); this.flotSettingsFormGroup.get('timeForComparison').disable({emitEvent: false});
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent}); this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent});
this.flotSettingsFormGroup.get('xaxisSecond').disable({emitEvent: false});
} }
if (customLegendEnabled) { if (customLegendEnabled) {
this.flotSettingsFormGroup.get('dataKeysListForLabels').enable({emitEvent}); this.flotSettingsFormGroup.get('dataKeysListForLabels').enable({emitEvent});
@ -392,6 +395,7 @@ export class FlotWidgetSettingsComponent extends PageComponent implements OnInit
this.flotSettingsFormGroup.get('legendConfig').updateValueAndValidity({emitEvent: false}); this.flotSettingsFormGroup.get('legendConfig').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('timeForComparison').updateValueAndValidity({emitEvent: false}); this.flotSettingsFormGroup.get('timeForComparison').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').updateValueAndValidity({emitEvent: false}); this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('xaxisSecond').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('dataKeysListForLabels').updateValueAndValidity({emitEvent: false}); this.flotSettingsFormGroup.get('dataKeysListForLabels').updateValueAndValidity({emitEvent: false});
} }
} }

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts

@ -47,7 +47,7 @@ export function labelDataKeyValidator(control: AbstractControl): ValidationError
@Component({ @Component({
selector: 'tb-label-data-key', selector: 'tb-label-data-key',
templateUrl: './label-data-key.component.html', templateUrl: './label-data-key.component.html',
styleUrls: ['./label-data-key.component.scss', './../widget-settings.scss'], styleUrls: ['./label-data-key.component.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

56
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html

@ -15,20 +15,21 @@
limitations under the License. limitations under the License.
--> -->
<form [formGroup]="legendConfigForm"> <ng-container [formGroup]="legendConfigForm">
<div fxLayout.xs="column" fxLayoutAlign.xs="center" fxLayout="row" fxLayoutAlign="start center" <div class="tb-widget-config-row space-between">
fxLayoutGap="8px"> <div>{{ 'legend.direction' | translate }}</div>
<mat-form-field fxFlex> <mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-label translate>legend.direction</mat-label> <mat-select formControlName="direction">
<mat-select matInput formControlName="direction">
<mat-option *ngFor="let direction of legendDirections" [value]="direction"> <mat-option *ngFor="let direction of legendDirections" [value]="direction">
{{ legendDirectionTranslations.get(legendDirection[direction]) | translate }} {{ legendDirectionTranslations.get(legendDirection[direction]) | translate }}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex> </div>
<mat-label translate>legend.position</mat-label> <div class="tb-widget-config-row space-between">
<mat-select matInput formControlName="position"> <div>{{ 'legend.position' | translate }}</div>
<mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="position">
<mat-option *ngFor="let pos of legendPositions" [value]="pos" <mat-option *ngFor="let pos of legendPositions" [value]="pos"
[disabled]="legendConfigForm.get('direction').value === legendDirection.row && [disabled]="legendConfigForm.get('direction').value === legendDirection.row &&
(pos === legendPosition.left || pos === legendPosition.right)"> (pos === legendPosition.left || pos === legendPosition.right)">
@ -37,28 +38,17 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> <div class="tb-widget-config-row space-between">
<mat-checkbox formControlName="showMin" fxFlex> <div translate>legend.show-values</div>
{{ 'legend.show-min' | translate }} <mat-chip-listbox multiple formControlName="showValues">
</mat-checkbox> <mat-chip-option value="min">{{ 'legend.min-option' | translate }}</mat-chip-option>
<mat-checkbox formControlName="showMax" fxFlex> <mat-chip-option value="max">{{ 'legend.max-option' | translate }}</mat-chip-option>
{{ 'legend.show-max' | translate }} <mat-chip-option value="average">{{ 'legend.average-option' | translate }}</mat-chip-option>
</mat-checkbox> <mat-chip-option value="total">{{ 'legend.total-option' | translate }}</mat-chip-option>
</div> <mat-chip-option value="latest">{{ 'legend.latest-option' | translate }}</mat-chip-option>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> </mat-chip-listbox>
<mat-checkbox formControlName="showAvg" fxFlex>
{{ 'legend.show-avg' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="showTotal" fxFlex>
{{ 'legend.show-total' | translate }}
</mat-checkbox>
</div>
<div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
<mat-checkbox formControlName="showLatest" fxFlex>
{{ 'legend.show-latest' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="sortDataKeys" fxFlex>
{{ 'legend.sort-legend' | translate }}
</mat-checkbox>
</div> </div>
</form> <mat-slide-toggle class="mat-slide" formControlName="sortDataKeys">
{{ 'legend.sort-legend' | translate }}
</mat-slide-toggle>
</ng-container>

57
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts

@ -15,7 +15,7 @@
/// ///
import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
import { ControlValueAccessor, UntypedFormBuilder, UntypedFormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { isDefined } from '@core/utils'; import { isDefined } from '@core/utils';
import { import {
LegendConfig, LegendConfig,
@ -30,7 +30,7 @@ import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'tb-legend-config', selector: 'tb-legend-config',
templateUrl: './legend-config.component.html', templateUrl: './legend-config.component.html',
styleUrls: [], styleUrls: ['./../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
@ -62,12 +62,8 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc
this.legendConfigForm = this.fb.group({ this.legendConfigForm = this.fb.group({
direction: [null, []], direction: [null, []],
position: [null, []], position: [null, []],
sortDataKeys: [null, []], showValues: [[], []],
showMin: [null, []], sortDataKeys: [null, []]
showMax: [null, []],
showAvg: [null, []],
showTotal: [null, []],
showLatest: [null, []]
}); });
this.legendSettingsFormDirectionChanges$ = this.legendConfigForm.get('direction').valueChanges this.legendSettingsFormDirectionChanges$ = this.legendConfigForm.get('direction').valueChanges
.subscribe((direction: LegendDirection) => { .subscribe((direction: LegendDirection) => {
@ -121,18 +117,49 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc
this.legendConfigForm.patchValue({ this.legendConfigForm.patchValue({
direction: legendConfig.direction, direction: legendConfig.direction,
position: legendConfig.position, position: legendConfig.position,
sortDataKeys: isDefined(legendConfig.sortDataKeys) ? legendConfig.sortDataKeys : false, showValues: this.getShowValues(legendConfig),
showMin: isDefined(legendConfig.showMin) ? legendConfig.showMin : false, sortDataKeys: isDefined(legendConfig.sortDataKeys) ? legendConfig.sortDataKeys : false
showMax: isDefined(legendConfig.showMax) ? legendConfig.showMax : false,
showAvg: isDefined(legendConfig.showAvg) ? legendConfig.showAvg : false,
showTotal: isDefined(legendConfig.showTotal) ? legendConfig.showTotal : false,
showLatest: isDefined(legendConfig.showLatest) ? legendConfig.showLatest : false
}, {emitEvent: false}); }, {emitEvent: false});
} }
this.onDirectionChanged(legendConfig.direction); this.onDirectionChanged(legendConfig.direction);
} }
private legendConfigUpdated() { private legendConfigUpdated() {
this.propagateChange(this.legendConfigForm.value); const configValue = this.legendConfigForm.value;
const legendConfig: Partial<LegendConfig> = {
direction: configValue.direction,
position: configValue.position,
sortDataKeys: configValue.sortDataKeys
};
this.setShowValues(configValue.showValues, legendConfig);
this.propagateChange(legendConfig);
}
private getShowValues(legendConfig: LegendConfig): string[] {
const showValues: string[] = [];
if (isDefined(legendConfig.showMin) && legendConfig.showMin) {
showValues.push('min');
}
if (isDefined(legendConfig.showMax) && legendConfig.showMax) {
showValues.push('max');
}
if (isDefined(legendConfig.showAvg) && legendConfig.showAvg) {
showValues.push('average');
}
if (isDefined(legendConfig.showTotal) && legendConfig.showTotal) {
showValues.push('total');
}
if (isDefined(legendConfig.showLatest) && legendConfig.showLatest) {
showValues.push('latest');
}
return showValues;
}
private setShowValues(showValues: string[], legendConfig: Partial<LegendConfig>) {
legendConfig.showMin = showValues.includes('min');
legendConfig.showMax = showValues.includes('max');
legendConfig.showAvg = showValues.includes('average');
legendConfig.showTotal = showValues.includes('total');
legendConfig.showLatest = showValues.includes('latest');
} }
} }

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

@ -36,14 +36,16 @@
<mat-slide-toggle class="mat-slide" formControlName="showTitle"> <mat-slide-toggle class="mat-slide" formControlName="showTitle">
{{ 'widget-config.display-title' | translate }} {{ 'widget-config.display-title' | translate }}
</mat-slide-toggle> </mat-slide-toggle>
<div fxLayout.xs="column" fxLayout="row" fxLayoutGap.gt-xs="8px"> <div class="tb-widget-config-row">
<mat-form-field fxFlex> <div class="fixed-title-width" translate>widget-config.title</div>
<mat-label translate>widget-config.title</mat-label> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title"> <input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex> </div>
<mat-label translate>widget-config.title-tooltip</mat-label> <div class="tb-widget-config-row">
<input matInput formControlName="titleTooltip"> <div class="fixed-title-width" translate>widget-config.title-tooltip</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="titleTooltip" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row space-between same-padding"> <div class="tb-widget-config-row space-between same-padding">
@ -55,7 +57,7 @@
[color]="widgetSettings.get('iconColor').value" [color]="widgetSettings.get('iconColor').value"
formControlName="titleIcon"> formControlName="titleIcon">
</tb-material-icon-select> </tb-material-icon-select>
<mat-form-field appearance="outline" subscriptSizing="dynamic" style="width: 60px;"> <mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="iconSize"> <input matInput formControlName="iconSize">
</mat-form-field> </mat-form-field>
<mat-divider vertical></mat-divider> <mat-divider vertical></mat-divider>
@ -102,13 +104,13 @@
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widget-config.padding' | translate }}</div> <div>{{ 'widget-config.padding' | translate }}</div>
<mat-form-field appearance="outline" class="center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div>{{ 'widget-config.margin' | translate }}</div> <div>{{ 'widget-config.margin' | translate }}</div>
<mat-form-field appearance="outline" class="center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="margin" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="margin" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
@ -166,13 +168,13 @@
<div class="tb-widget-config-panel"> <div class="tb-widget-config-panel">
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widget-config.order</div> <div translate>widget-config.order</div>
<mat-form-field appearance="outline" class="number center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="mobileOrder" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="mobileOrder" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widget-config.height</div> <div translate>widget-config.height</div>
<mat-form-field appearance="outline" class="number center" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="mobileHeight" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="mobileHeight" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
@ -241,7 +243,7 @@
<div class="tb-widget-config-panel-title" translate>widget-config.limits</div> <div class="tb-widget-config-panel-title" translate>widget-config.limits</div>
<div class="tb-widget-config-row space-between"> <div class="tb-widget-config-row space-between">
<div translate>widget-config.data-page-size</div> <div translate>widget-config.data-page-size</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="pageSize" type="number" min="1" step="1"> <input matInput formControlName="pageSize" type="number" min="1" step="1">
</mat-form-field> </mat-form-field>
</div> </div>
@ -258,12 +260,12 @@
</div> </div>
<div *ngIf="displayUnitsConfig" class="tb-widget-config-row space-between"> <div *ngIf="displayUnitsConfig" class="tb-widget-config-row space-between">
<div translate>widget-config.decimals</div> <div translate>widget-config.decimals</div>
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic"> <mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput formControlName="decimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field> </mat-form-field>
</div> </div>
<div *ngIf="displayNoDataDisplayMessageConfig" class="tb-widget-config-row"> <div *ngIf="displayNoDataDisplayMessageConfig" class="tb-widget-config-row">
<div translate>widget-config.no-data-display-message</div> <div class="fixed-title-width" translate>widget-config.no-data-display-message</div>
<mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic"> <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="noDataDisplayMessage" placeholder="{{ 'widget-config.set-message' | translate }}"> <input matInput formControlName="noDataDisplayMessage" placeholder="{{ 'widget-config.set-message' | translate }}">
</mat-form-field> </mat-form-field>

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

@ -2782,8 +2782,14 @@
"left-side": "Left side layout" "left-side": "Left side layout"
}, },
"legend": { "legend": {
"direction": "Legend direction", "direction": "Direction",
"position": "Legend position", "position": "Position",
"show-values": "Show values",
"min-option": "Min",
"max-option": "Max",
"average-option": "Average",
"total-option": "Total",
"latest-option": "Latest",
"sort-legend": "Sort datakeys in legend", "sort-legend": "Sort datakeys in legend",
"show-max": "Show max value", "show-max": "Show max value",
"show-min": "Show min value", "show-min": "Show min value",
@ -4250,7 +4256,10 @@
"text": "Text", "text": "Text",
"background": "Background", "background": "Background",
"advanced-widget-style": "Advanced widget style", "advanced-widget-style": "Advanced widget style",
"card-buttons": "Card buttons" "card-buttons": "Card buttons",
"show-card-buttons": "Show card buttons",
"card-appearance": "Card appearance",
"color": "Color"
}, },
"widget-type": { "widget-type": {
"import": "Import widget type", "import": "Import widget type",
@ -4273,10 +4282,12 @@
"bar-alignment-left": "Left", "bar-alignment-left": "Left",
"bar-alignment-right": "Right", "bar-alignment-right": "Right",
"bar-alignment-center": "Center", "bar-alignment-center": "Center",
"default-font": "Default font",
"default-font-size": "Default font size", "default-font-size": "Default font size",
"default-font-color": "Default font color", "default-font-color": "Default font color",
"thresholds-line-width": "Default line width for all thresholds", "thresholds-line-width": "Default line width for all thresholds",
"tooltip-settings": "Tooltip settings", "tooltip-settings": "Tooltip settings",
"tooltip": "Tooltip",
"show-tooltip": "Show tooltip", "show-tooltip": "Show tooltip",
"hover-individual-points": "Hover individual points", "hover-individual-points": "Hover individual points",
"show-cumulative-values": "Show cumulative values in stacking mode", "show-cumulative-values": "Show cumulative values in stacking mode",
@ -4351,7 +4362,7 @@
"axis-position-right": "Right", "axis-position-right": "Right",
"thresholds": "Thresholds", "thresholds": "Thresholds",
"no-thresholds": "No thresholds configured", "no-thresholds": "No thresholds configured",
"add-threshold": "Add new threshold", "add-threshold": "Add threshold",
"show-values-for-comparison": "Show historical values for comparison", "show-values-for-comparison": "Show historical values for comparison",
"comparison-values-label": "Historical values label", "comparison-values-label": "Historical values label",
"threshold-settings": "Threshold settings", "threshold-settings": "Threshold settings",
@ -4372,7 +4383,23 @@
"border-color": "Border color", "border-color": "Border color",
"legend-settings": "Legend settings", "legend-settings": "Legend settings",
"display-legend": "Display legend", "display-legend": "Display legend",
"labels-font-color": "Labels font color" "labels-font-color": "Labels font color",
"series": "Series",
"add-series": "Add series",
"series-settings": "Series settings",
"remove-series": "Remove series",
"no-series": "No series configured",
"no-series-error": "At least one series should be specified",
"chart-appearance": "Chart appearance",
"vertical-grid-lines": "Vertical grid lines",
"horizontal-grid-lines": "Horizontal grid lines",
"chart-background": "Chart background",
"grid-lines-color": "Grid lines color",
"border": "Border",
"axis": "Axis",
"vertical-axis": "Vertical axis",
"ticks": "Ticks",
"horizontal-axis": "Horizontal axis"
}, },
"dashboard-state": { "dashboard-state": {
"dashboard-state-settings": "Dashboard state settings", "dashboard-state-settings": "Dashboard state settings",
@ -5239,7 +5266,6 @@
"remove-column": "Remove column", "remove-column": "Remove column",
"add-column": "Add column", "add-column": "Add column",
"no-columns": "No columns configured", "no-columns": "No columns configured",
"show-card-buttons": "Show card buttons",
"columns-to-display": "Columns to display", "columns-to-display": "Columns to display",
"table-header": "Table header", "table-header": "Table header",
"header-buttons": "Header buttons", "header-buttons": "Header buttons",

41
ui-ngx/src/styles.scss

@ -1212,11 +1212,11 @@ mat-label {
&.tb-slide-toggle { &.tb-slide-toggle {
padding: 0; padding: 0;
gap: 0; gap: 0;
.tb-widget-config-panel-title { > .tb-widget-config-panel-title {
padding-top: 16px; padding-top: 16px;
padding-left: 16px; padding-left: 16px;
} }
.mat-expansion-panel { > .mat-expansion-panel {
padding: 16px; padding: 16px;
.mat-expansion-panel-header { .mat-expansion-panel-header {
height: 32px; height: 32px;
@ -1232,7 +1232,7 @@ mat-label {
.mat-content { .mat-content {
overflow: visible; overflow: visible;
} }
.mat-expansion-panel-header { > .mat-expansion-panel-header {
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
@ -1255,12 +1255,15 @@ mat-label {
padding: 2px; padding: 2px;
} }
} }
.mat-expansion-panel-header-description { > .mat-expansion-panel-header-description {
align-items: center; align-items: center;
} }
> .mat-expansion-panel-content { > .mat-expansion-panel-content {
> .mat-expansion-panel-body { > .mat-expansion-panel-body {
padding: 0; display: flex;
flex-direction: column;
gap: 16px;
padding: 16px 0 0 !important;
} }
} }
.tb-json-object-panel, .tb-css-content-panel { .tb-json-object-panel, .tb-css-content-panel {
@ -1272,9 +1275,9 @@ mat-label {
} }
} }
.mat-slide { .mat-slide {
margin: 8px 0; margin: 0;
&.no-margin { &.margin {
margin: 0; margin: 8px 0;
} }
.mdc-form-field>label { .mdc-form-field>label {
font-weight: 400; font-weight: 400;
@ -1313,7 +1316,13 @@ mat-label {
height: 56px; height: 56px;
} }
.mat-mdc-form-field { .mat-mdc-form-field {
width: 80px; width: 106px;
&.medium-width {
width: 220px;
}
}
.fixed-title-width {
min-width: 200px;
} }
} }
@ -1341,9 +1350,9 @@ mat-label {
} }
} }
.mat-mdc-form-field-infix { .mat-mdc-form-field-infix {
padding-top: 7px; padding-top: 8px;
padding-bottom: 7px; padding-bottom: 8px;
min-height: 38px; min-height: 40px;
width: auto; width: auto;
.mdc-text-field__input, .mat-mdc-select { .mdc-text-field__input, .mat-mdc-select {
font-weight: 400; font-weight: 400;
@ -1373,6 +1382,14 @@ mat-label {
} }
} }
} }
.mat-mdc-form-field-flex {
.mat-mdc-form-field-icon-suffix {
font-size: 14px;
line-height: 20px;
letter-spacing: 0.2px;
color: rgba(0, 0, 0, 0.38);
}
}
} }
} }

Loading…
Cancel
Save