UI: Timeseries table basic config
This commit is contained in:
parent
97831351a0
commit
987d41f329
@ -64,7 +64,9 @@
|
||||
"settingsDirective": "tb-timeseries-table-widget-settings",
|
||||
"dataKeySettingsDirective": "tb-timeseries-table-key-settings",
|
||||
"latestDataKeySettingsDirective": "tb-timeseries-table-latest-key-settings",
|
||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":null}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"displayTimewindow\":true}"
|
||||
"hasBasicMode": true,
|
||||
"basicModeDirective": "tb-timeseries-table-basic-config",
|
||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":null}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"displayTimewindow\":true,\"configMode\":\"basic\"}"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -1152,7 +1152,9 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
|
||||
this.widgetComponentService.getWidgetInfo(widget.bundleAlias, widget.typeAlias, widget.isSystemType).subscribe(
|
||||
(widgetTypeInfo) => {
|
||||
const config: WidgetConfig = this.dashboardUtils.widgetConfigFromWidgetType(widgetTypeInfo);
|
||||
if (!config.title) {
|
||||
config.title = 'New ' + widgetTypeInfo.widgetName;
|
||||
}
|
||||
let newWidget: Widget = {
|
||||
isSystemType: widget.isSystemType,
|
||||
bundleAlias: widget.bundleAlias,
|
||||
|
||||
@ -30,12 +30,16 @@ import {
|
||||
} from '@home/components/widget/config/basic/cards/entities-table-basic-config.component';
|
||||
import { DataKeysPanelComponent } from '@home/components/widget/config/basic/common/data-keys-panel.component';
|
||||
import { DataKeyRowComponent } from '@home/components/widget/config/basic/common/data-key-row.component';
|
||||
import {
|
||||
TimeseriesTableBasicConfigComponent
|
||||
} from '@home/components/widget/config/basic/cards/timeseries-table-basic-config.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
WidgetActionsPanelComponent,
|
||||
SimpleCardBasicConfigComponent,
|
||||
EntitiesTableBasicConfigComponent,
|
||||
TimeseriesTableBasicConfigComponent,
|
||||
DataKeyRowComponent,
|
||||
DataKeysPanelComponent
|
||||
],
|
||||
@ -48,6 +52,7 @@ import { DataKeyRowComponent } from '@home/components/widget/config/basic/common
|
||||
WidgetActionsPanelComponent,
|
||||
SimpleCardBasicConfigComponent,
|
||||
EntitiesTableBasicConfigComponent,
|
||||
TimeseriesTableBasicConfigComponent,
|
||||
DataKeyRowComponent,
|
||||
DataKeysPanelComponent
|
||||
]
|
||||
@ -57,5 +62,6 @@ export class BasicWidgetConfigModule {
|
||||
|
||||
export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetConfigComponent>} = {
|
||||
'tb-simple-card-basic-config': SimpleCardBasicConfigComponent,
|
||||
'tb-entities-table-basic-config': EntitiesTableBasicConfigComponent
|
||||
'tb-entities-table-basic-config': EntitiesTableBasicConfigComponent,
|
||||
'tb-timeseries-table-basic-config': TimeseriesTableBasicConfigComponent
|
||||
};
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
} 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';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-entities-table-basic-config',
|
||||
@ -75,7 +76,7 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
|
||||
this.entitiesTableWidgetConfigForm = this.fb.group({
|
||||
timewindowConfig: [{
|
||||
useDashboardTimewindow: configData.config.useDashboardTimewindow,
|
||||
displayTimewindow: configData.config.useDashboardTimewindow,
|
||||
displayTimewindow: configData.config.displayTimewindow,
|
||||
timewindow: configData.config.timewindow
|
||||
}, []],
|
||||
datasources: [configData.config.datasources, []],
|
||||
@ -155,13 +156,13 @@ export class EntitiesTableBasicConfigComponent extends BasicWidgetConfigComponen
|
||||
|
||||
private getCardButtons(config: WidgetConfig): string[] {
|
||||
const buttons: string[] = [];
|
||||
if (config.settings?.enableSearch) {
|
||||
if (isUndefined(config.settings?.enableSearch) || config.settings?.enableSearch) {
|
||||
buttons.push('search');
|
||||
}
|
||||
if (config.settings?.enableSelectColumnDisplay) {
|
||||
if (isUndefined(config.settings?.enableSelectColumnDisplay) || config.settings?.enableSelectColumnDisplay) {
|
||||
buttons.push('columnsToDisplay');
|
||||
}
|
||||
if (config.enableFullscreen) {
|
||||
if (isUndefined(config.enableFullscreen) || config.enableFullscreen) {
|
||||
buttons.push('fullscreen');
|
||||
}
|
||||
return buttons;
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
<!--
|
||||
|
||||
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]="timeseriesTableWidgetConfigForm">
|
||||
<tb-timewindow-config-panel formControlName="timewindowConfig">
|
||||
</tb-timewindow-config-panel>
|
||||
<tb-datasources
|
||||
[configMode]="basicMode"
|
||||
hideDataKeys
|
||||
formControlName="datasources">
|
||||
</tb-datasources>
|
||||
<tb-data-keys-panel
|
||||
panelTitle="{{ 'widgets.table.columns' | translate }}"
|
||||
addKeyTitle="{{ 'widgets.table.add-column' | translate }}"
|
||||
keySettingsTitle="{{ 'widgets.table.column-settings' | translate }}"
|
||||
removeKeyTitle="{{ 'widgets.table.remove-column' | translate }}"
|
||||
noKeysText="{{ 'widgets.table.no-columns' | translate }}"
|
||||
requiredKeysText="{{ 'widgets.table.timeseries-column-error' | translate }}"
|
||||
hideDataKeyColor
|
||||
[datasourceType]="datasource?.type"
|
||||
[deviceId]="datasource?.deviceId"
|
||||
[entityAliasId]="datasource?.entityAliasId"
|
||||
formControlName="columns">
|
||||
</tb-data-keys-panel>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widget-config.appearance</div>
|
||||
<div class="tb-widget-config-row">
|
||||
<mat-slide-toggle class="mat-slide" 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]="timeseriesTableWidgetConfigForm.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>widgets.table.show-card-buttons</div>
|
||||
<mat-chip-listbox multiple formControlName="cardButtons">
|
||||
<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="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>
|
||||
</mat-chip-listbox>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between same-padding">
|
||||
<div>{{ 'widget-config.text-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 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>
|
||||
<tb-widget-actions-panel
|
||||
formControlName="actions">
|
||||
</tb-widget-actions-panel>
|
||||
</ng-container>
|
||||
@ -0,0 +1,181 @@
|
||||
///
|
||||
/// 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,
|
||||
datasourcesHasAggregation,
|
||||
datasourcesHasOnlyComparisonAggregation, WidgetConfig
|
||||
} from '@shared/models/widget.models';
|
||||
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
|
||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||
import { deepClone, isUndefined } from '@core/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-timeseries-table-basic-config',
|
||||
templateUrl: './timeseries-table-basic-config.component.html',
|
||||
styleUrls: ['../basic-config.scss']
|
||||
})
|
||||
export class TimeseriesTableBasicConfigComponent extends BasicWidgetConfigComponent {
|
||||
|
||||
public get datasource(): Datasource {
|
||||
const datasources: Datasource[] = this.timeseriesTableWidgetConfigForm.get('datasources').value;
|
||||
if (datasources && datasources.length) {
|
||||
return datasources[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
timeseriesTableWidgetConfigForm: UntypedFormGroup;
|
||||
|
||||
constructor(protected store: Store<AppState>,
|
||||
protected widgetConfigComponent: WidgetConfigComponent,
|
||||
private fb: UntypedFormBuilder) {
|
||||
super(store, widgetConfigComponent);
|
||||
}
|
||||
|
||||
protected configForm(): UntypedFormGroup {
|
||||
return this.timeseriesTableWidgetConfigForm;
|
||||
}
|
||||
|
||||
protected setupDefaults(configData: WidgetConfigComponentData) {
|
||||
this.setupDefaultDatasource(configData,
|
||||
[{ name: 'temperature', label: 'Temperature', type: DataKeyType.timeseries, units: '°C', decimals: 0 }]);
|
||||
}
|
||||
|
||||
protected onConfigSet(configData: WidgetConfigComponentData) {
|
||||
this.timeseriesTableWidgetConfigForm = this.fb.group({
|
||||
timewindowConfig: [{
|
||||
useDashboardTimewindow: configData.config.useDashboardTimewindow,
|
||||
displayTimewindow: configData.config.displayTimewindow,
|
||||
timewindow: configData.config.timewindow
|
||||
}, []],
|
||||
datasources: [configData.config.datasources, []],
|
||||
columns: [this.getColumns(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, []],
|
||||
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.setColumns(config.columns, this.widgetConfig.config.datasources);
|
||||
this.widgetConfig.config.actions = config.actions;
|
||||
this.widgetConfig.config.showTitle = config.showTitle;
|
||||
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
|
||||
this.widgetConfig.config.settings.entitiesTitle = config.title;
|
||||
this.widgetConfig.config.showTitleIcon = config.showTitleIcon;
|
||||
this.widgetConfig.config.titleIcon = config.titleIcon;
|
||||
this.widgetConfig.config.iconColor = config.iconColor;
|
||||
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
|
||||
this.widgetConfig.config.color = config.color;
|
||||
this.widgetConfig.config.backgroundColor = config.backgroundColor;
|
||||
return this.widgetConfig;
|
||||
}
|
||||
|
||||
protected validatorTriggers(): string[] {
|
||||
return ['showTitle', 'showTitleIcon'];
|
||||
}
|
||||
|
||||
protected updateValidators(emitEvent: boolean, trigger?: string) {
|
||||
const showTitle: boolean = this.timeseriesTableWidgetConfigForm.get('showTitle').value;
|
||||
const showTitleIcon: boolean = this.timeseriesTableWidgetConfigForm.get('showTitleIcon').value;
|
||||
if (showTitle) {
|
||||
this.timeseriesTableWidgetConfigForm.get('title').enable();
|
||||
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').enable({emitEvent: false});
|
||||
if (showTitleIcon) {
|
||||
this.timeseriesTableWidgetConfigForm.get('titleIcon').enable();
|
||||
this.timeseriesTableWidgetConfigForm.get('iconColor').enable();
|
||||
} else {
|
||||
this.timeseriesTableWidgetConfigForm.get('titleIcon').disable();
|
||||
this.timeseriesTableWidgetConfigForm.get('iconColor').disable();
|
||||
}
|
||||
} else {
|
||||
this.timeseriesTableWidgetConfigForm.get('title').disable();
|
||||
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').disable({emitEvent: false});
|
||||
this.timeseriesTableWidgetConfigForm.get('titleIcon').disable();
|
||||
this.timeseriesTableWidgetConfigForm.get('iconColor').disable();
|
||||
}
|
||||
this.timeseriesTableWidgetConfigForm.get('title').updateValueAndValidity({emitEvent});
|
||||
this.timeseriesTableWidgetConfigForm.get('showTitleIcon').updateValueAndValidity({emitEvent: false});
|
||||
this.timeseriesTableWidgetConfigForm.get('titleIcon').updateValueAndValidity({emitEvent});
|
||||
this.timeseriesTableWidgetConfigForm.get('iconColor').updateValueAndValidity({emitEvent});
|
||||
}
|
||||
|
||||
private getColumns(datasources?: Datasource[]): DataKey[] {
|
||||
if (datasources && datasources.length) {
|
||||
const dataKeys = deepClone(datasources[0].dataKeys) || [];
|
||||
dataKeys.forEach(k => {
|
||||
(k as any).latest = false;
|
||||
});
|
||||
const latestDataKeys = deepClone(datasources[0].latestDataKeys) || [];
|
||||
latestDataKeys.forEach(k => {
|
||||
(k as any).latest = true;
|
||||
});
|
||||
return dataKeys.concat(latestDataKeys);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private setColumns(columns: DataKey[], datasources?: Datasource[]) {
|
||||
if (datasources && datasources.length) {
|
||||
const dataKeys = deepClone(columns.filter(c => !(c as any).latest));
|
||||
dataKeys.forEach(k => delete (k as any).latest);
|
||||
const latestDataKeys = deepClone(columns.filter(c => (c as any).latest));
|
||||
latestDataKeys.forEach(k => delete (k as any).latest);
|
||||
datasources[0].dataKeys = dataKeys;
|
||||
datasources[0].latestDataKeys = latestDataKeys;
|
||||
}
|
||||
}
|
||||
|
||||
private getCardButtons(config: WidgetConfig): string[] {
|
||||
const buttons: string[] = [];
|
||||
if (isUndefined(config.settings?.enableSearch) || config.settings?.enableSearch) {
|
||||
buttons.push('search');
|
||||
}
|
||||
if (isUndefined(config.settings?.enableSelectColumnDisplay) || config.settings?.enableSelectColumnDisplay) {
|
||||
buttons.push('columnsToDisplay');
|
||||
}
|
||||
if (isUndefined(config.enableFullscreen) || config.enableFullscreen) {
|
||||
buttons.push('fullscreen');
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
private setCardButtons(buttons: string[], config: WidgetConfig) {
|
||||
config.settings.enableSearch = buttons.includes('search');
|
||||
config.settings.enableSelectColumnDisplay = buttons.includes('columnsToDisplay');
|
||||
config.enableFullscreen = buttons.includes('fullscreen');
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,6 +16,12 @@
|
||||
|
||||
-->
|
||||
<div [formGroup]="keyRowFormGroup" class="tb-data-key-row">
|
||||
<mat-form-field *ngIf="hasAdditionalLatestDataKeys" class="tb-inline-field tb-source-field" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="latest">
|
||||
<mat-option [value]="false">{{ 'datakey.timeseries' | translate }}</mat-option>
|
||||
<mat-option [value]="true">{{ 'datakey.latest' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex class="tb-inline-field tb-key-field" subscriptSizing="dynamic">
|
||||
<mat-chip-grid #chipList>
|
||||
<mat-chip-row class="tb-datakey-chip" *ngIf="modelValue.type"
|
||||
|
||||
@ -43,6 +43,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tb-source-field {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.tb-color-field, .tb-units-field, .tb-decimals-field {
|
||||
width: 60px;
|
||||
display: flex;
|
||||
|
||||
@ -153,6 +153,11 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
return this.widgetConfigComponent.widgetConfigCallbacks;
|
||||
}
|
||||
|
||||
get hasAdditionalLatestDataKeys(): boolean {
|
||||
return this.widgetConfigComponent.widgetType === widgetType.timeseries &&
|
||||
this.widgetConfigComponent.modelValue?.typeParameters?.hasAdditionalLatestDataKeys;
|
||||
}
|
||||
|
||||
get widget(): Widget {
|
||||
return this.widgetConfigComponent.widget;
|
||||
}
|
||||
@ -165,7 +170,7 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
return this.widgetConfigComponent.aliasController;
|
||||
}
|
||||
|
||||
get datakeySettingsSchema(): JsonSettingsSchema {
|
||||
get dataKeySettingsSchema(): JsonSettingsSchema {
|
||||
return this.widgetConfigComponent.modelValue?.dataKeySettingsSchema;
|
||||
}
|
||||
|
||||
@ -173,6 +178,14 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
return this.widgetConfigComponent.modelValue?.dataKeySettingsDirective;
|
||||
}
|
||||
|
||||
get latestDataKeySettingsSchema(): JsonSettingsSchema {
|
||||
return this.widgetConfigComponent.modelValue?.latestDataKeySettingsSchema;
|
||||
}
|
||||
|
||||
get latestDataKeySettingsDirective(): string {
|
||||
return this.widgetConfigComponent.modelValue?.latestDataKeySettingsDirective;
|
||||
}
|
||||
|
||||
get isEntityDatasource(): boolean {
|
||||
return [DatasourceType.device, DatasourceType.entity].includes(this.datasourceType);
|
||||
}
|
||||
@ -193,6 +206,10 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
return this.dataKeysPanelComponent.dragEnabled;
|
||||
}
|
||||
|
||||
get isLatestDataKeys(): boolean {
|
||||
return this.hasAdditionalLatestDataKeys && this.keyRowFormGroup.get('latest').value === true;
|
||||
}
|
||||
|
||||
private propagateChange = (_val: any) => {};
|
||||
|
||||
constructor(private fb: UntypedFormBuilder,
|
||||
@ -212,6 +229,12 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
units: [null, []],
|
||||
decimals: [null, []],
|
||||
});
|
||||
if (this.hasAdditionalLatestDataKeys) {
|
||||
this.keyRowFormGroup.addControl('latest', this.fb.control(false));
|
||||
this.keyRowFormGroup.valueChanges.subscribe(
|
||||
() => this.clearKeySearchCache()
|
||||
);
|
||||
}
|
||||
this.keyRowFormGroup.valueChanges.subscribe(
|
||||
() => this.updateModel()
|
||||
);
|
||||
@ -286,6 +309,11 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
decimals: value?.decimals
|
||||
}, {emitEvent: false}
|
||||
);
|
||||
if (this.hasAdditionalLatestDataKeys) {
|
||||
this.keyRowFormGroup.patchValue({
|
||||
latest: (value as any)?.latest
|
||||
}, {emitEvent: false});
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
|
||||
@ -323,8 +351,8 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
data: {
|
||||
dataKey: deepClone(this.modelValue),
|
||||
dataKeyConfigMode: advanced ? DataKeyConfigMode.advanced : DataKeyConfigMode.general,
|
||||
dataKeySettingsSchema: this.datakeySettingsSchema,
|
||||
dataKeySettingsDirective: this.dataKeySettingsDirective,
|
||||
dataKeySettingsSchema: this.isLatestDataKeys ? this.latestDataKeySettingsSchema : this.dataKeySettingsSchema,
|
||||
dataKeySettingsDirective: this.isLatestDataKeys ? this.latestDataKeySettingsDirective : this.dataKeySettingsDirective,
|
||||
dashboard: this.dashboard,
|
||||
aliasController: this.aliasController,
|
||||
widget: this.widget,
|
||||
@ -399,7 +427,7 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
} else if (this.datasourceType === DatasourceType.entity && this.entityAliasId ||
|
||||
this.datasourceType === DatasourceType.device && this.deviceId) {
|
||||
const dataKeyTypes = [DataKeyType.timeseries];
|
||||
if (this.widgetType === widgetType.latest || this.widgetType === widgetType.alarm) {
|
||||
if (this.isLatestDataKeys || this.widgetType === widgetType.latest || this.widgetType === widgetType.alarm) {
|
||||
dataKeyTypes.push(DataKeyType.attribute);
|
||||
dataKeyTypes.push(DataKeyType.entityField);
|
||||
if (this.widgetType === widgetType.alarm) {
|
||||
@ -428,7 +456,7 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan
|
||||
}
|
||||
|
||||
private addKeyFromChipValue(chip: DataKey) {
|
||||
this.modelValue = this.callbacks.generateDataKey(chip.name, chip.type, this.datakeySettingsSchema);
|
||||
this.modelValue = this.callbacks.generateDataKey(chip.name, chip.type, this.dataKeySettingsSchema);
|
||||
if (!this.keyRowFormGroup.get('label').value) {
|
||||
this.keyRowFormGroup.get('label').patchValue(this.modelValue.label, {emitEvent: false});
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
<div class="tb-widget-config-panel-title">{{ panelTitle }}</div>
|
||||
<div class="tb-data-keys-table">
|
||||
<div class="tb-data-keys-header">
|
||||
<div *ngIf="hasAdditionalLatestDataKeys" class="tb-data-keys-header-cell tb-source-header" translate>datakey.source</div>
|
||||
<div class="tb-data-keys-header-cell" fxFlex translate>datakey.key</div>
|
||||
<div class="tb-data-keys-header-cell" fxFlex translate>datakey.label</div>
|
||||
<div *ngIf="!hideDataKeyColor" class="tb-data-keys-header-cell tb-color-header" translate>datakey.color</div>
|
||||
@ -52,6 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tb-error *ngIf="errorText" noMargin [error]="errorText" style="padding-left: 12px;"></tb-error>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" mat-stroked-button color="primary" (click)="addKey()">
|
||||
|
||||
@ -35,6 +35,9 @@
|
||||
line-height: 20px;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
&.tb-source-header {
|
||||
width: 140px;
|
||||
}
|
||||
&.tb-color-header, &.tb-units-header, &.tb-decimals-header {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
@ -84,6 +84,9 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
@Input()
|
||||
noKeysText: string;
|
||||
|
||||
@Input()
|
||||
requiredKeysText: string;
|
||||
|
||||
@Input()
|
||||
datasourceType: DatasourceType;
|
||||
|
||||
@ -103,6 +106,8 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
|
||||
keysListFormGroup: UntypedFormGroup;
|
||||
|
||||
errorText = '';
|
||||
|
||||
get widgetType(): widgetType {
|
||||
return this.widgetConfigComponent.widgetType;
|
||||
}
|
||||
@ -111,6 +116,11 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
return this.widgetConfigComponent.widgetConfigCallbacks;
|
||||
}
|
||||
|
||||
get hasAdditionalLatestDataKeys(): boolean {
|
||||
return this.widgetConfigComponent.widgetType === widgetType.timeseries &&
|
||||
this.widgetConfigComponent.modelValue?.typeParameters?.hasAdditionalLatestDataKeys;
|
||||
}
|
||||
|
||||
get datakeySettingsSchema(): JsonSettingsSchema {
|
||||
return this.widgetConfigComponent.modelValue?.dataKeySettingsSchema;
|
||||
}
|
||||
@ -119,6 +129,14 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
return this.keysFormArray().controls.length > 1;
|
||||
}
|
||||
|
||||
get noKeys(): boolean {
|
||||
let keys: DataKey[] = this.keysListFormGroup.get('keys').value;
|
||||
if (this.hasAdditionalLatestDataKeys) {
|
||||
keys = keys.filter(k => !(k as any).latest);
|
||||
}
|
||||
return keys.length === 0;
|
||||
}
|
||||
|
||||
private propagateChange = (_val: any) => {};
|
||||
|
||||
constructor(private fb: UntypedFormBuilder,
|
||||
@ -196,7 +214,13 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
}
|
||||
|
||||
public validate(c: UntypedFormControl) {
|
||||
return this.keysListFormGroup.valid ? null : {
|
||||
this.errorText = '';
|
||||
let valid = this.keysListFormGroup.valid;
|
||||
if (this.noKeys && this.requiredKeysText) {
|
||||
valid = false;
|
||||
this.errorText = this.requiredKeysText;
|
||||
}
|
||||
return valid ? null : {
|
||||
dataKeyRows: {
|
||||
valid: false,
|
||||
},
|
||||
@ -226,6 +250,9 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
|
||||
const dataKey = this.callbacks.generateDataKey('', null, this.datakeySettingsSchema);
|
||||
dataKey.label = '';
|
||||
dataKey.decimals = 0;
|
||||
if (this.hasAdditionalLatestDataKeys) {
|
||||
(dataKey as any).latest = false;
|
||||
}
|
||||
const keysArray = this.keysListFormGroup.get('keys') as UntypedFormArray;
|
||||
const keyControl = this.fb.control(dataKey, [dataKeyRowValidator]);
|
||||
keysArray.push(keyControl);
|
||||
|
||||
@ -15,18 +15,49 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<section class="tb-widget-settings" [formGroup]="timeseriesTableKeySettingsForm" fxLayout="column">
|
||||
<fieldset class="fields-group fields-group-slider">
|
||||
<legend class="group-title" translate>widgets.table.cell-style</legend>
|
||||
<ng-container [formGroup]="timeseriesTableKeySettingsForm">
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div>{{ 'widgets.table.default-column-visibility' | translate }}</div>
|
||||
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="defaultColumnVisibility">
|
||||
<mat-option [value]="'visible'">
|
||||
{{ 'widgets.table.column-visibility-visible' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden'">
|
||||
{{ 'widgets.table.column-visibility-hidden' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden-mobile'">
|
||||
{{ 'widgets.table.column-visibility-hidden-mobile' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div>{{ 'widgets.table.column-selection-to-display' | translate }}</div>
|
||||
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="columnSelectionToDisplay">
|
||||
<mat-option [value]="'enabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'disabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-widget-config-panel tb-slide-toggle">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableKeySettingsForm.get('useCellStyleFunction').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title>
|
||||
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
|
||||
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
|
||||
<mat-panel-title fxFlex="60">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
|
||||
fxLayoutAlign="center">
|
||||
{{ 'widgets.table.use-cell-style-function' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</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
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
@ -40,18 +71,17 @@
|
||||
</tb-js-func>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</fieldset>
|
||||
<fieldset class="fields-group fields-group-slider">
|
||||
<legend class="group-title" translate>widgets.table.cell-content</legend>
|
||||
</div>
|
||||
<div class="tb-widget-config-panel tb-slide-toggle">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableKeySettingsForm.get('useCellContentFunction').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title>
|
||||
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
|
||||
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
|
||||
<mat-panel-title fxFlex="60">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
|
||||
fxLayoutAlign="center">
|
||||
{{ 'widgets.table.use-cell-content-function' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</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
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
@ -65,30 +95,5 @@
|
||||
</tb-js-func>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</fieldset>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.default-column-visibility</mat-label>
|
||||
<mat-select formControlName="defaultColumnVisibility">
|
||||
<mat-option [value]="'visible'">
|
||||
{{ 'widgets.table.column-visibility-visible' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden'">
|
||||
{{ 'widgets.table.column-visibility-hidden' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden-mobile'">
|
||||
{{ 'widgets.table.column-visibility-hidden-mobile' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.column-selection-to-display</mat-label>
|
||||
<mat-select formControlName="columnSelectionToDisplay">
|
||||
<mat-option [value]="'enabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'disabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@ -15,25 +15,58 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<section class="tb-widget-settings" [formGroup]="timeseriesTableLatestKeySettingsForm" fxLayout="column">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="show">
|
||||
<ng-container [formGroup]="timeseriesTableLatestKeySettingsForm">
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.column-settings</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="show">
|
||||
{{ 'widgets.table.show-latest-data-column' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-form-field [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.latest-data-column-order</mat-label>
|
||||
<input matInput type="number" step="1" formControlName="order">
|
||||
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
|
||||
<div translate>widgets.table.latest-data-column-order</div>
|
||||
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="order" type="number" step="1" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
</mat-form-field>
|
||||
<fieldset [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="fields-group fields-group-slider">
|
||||
<legend class="group-title" translate>widgets.table.cell-style</legend>
|
||||
</div>
|
||||
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
|
||||
<div>{{ 'widgets.table.default-column-visibility' | translate }}</div>
|
||||
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="defaultColumnVisibility">
|
||||
<mat-option [value]="'visible'">
|
||||
{{ 'widgets.table.column-visibility-visible' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden'">
|
||||
{{ 'widgets.table.column-visibility-hidden' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden-mobile'">
|
||||
{{ 'widgets.table.column-visibility-hidden-mobile' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-row space-between">
|
||||
<div>{{ 'widgets.table.column-selection-to-display' | translate }}</div>
|
||||
<mat-form-field style="width: 220px;" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-select formControlName="columnSelectionToDisplay">
|
||||
<mat-option [value]="'enabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'disabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-panel tb-slide-toggle">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableLatestKeySettingsForm.get('useCellStyleFunction').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title>
|
||||
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
|
||||
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
|
||||
<mat-panel-title fxFlex="60">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
|
||||
fxLayoutAlign="center">
|
||||
{{ 'widgets.table.use-cell-style-function' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</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
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
@ -47,18 +80,17 @@
|
||||
</tb-js-func>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</fieldset>
|
||||
<fieldset [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="fields-group fields-group-slider">
|
||||
<legend class="group-title" translate>widgets.table.cell-content</legend>
|
||||
</div>
|
||||
<div [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="tb-widget-config-panel tb-slide-toggle">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableLatestKeySettingsForm.get('useCellContentFunction').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title>
|
||||
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
|
||||
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
|
||||
<mat-panel-title fxFlex="60">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
|
||||
fxLayoutAlign="center">
|
||||
{{ 'widgets.table.use-cell-content-function' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</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
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
@ -72,30 +104,6 @@
|
||||
</tb-js-func>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</fieldset>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.default-column-visibility</mat-label>
|
||||
<mat-select formControlName="defaultColumnVisibility">
|
||||
<mat-option [value]="'visible'">
|
||||
{{ 'widgets.table.column-visibility-visible' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden'">
|
||||
{{ 'widgets.table.column-visibility-hidden' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'hidden-mobile'">
|
||||
{{ 'widgets.table.column-visibility-hidden-mobile' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.column-selection-to-display</mat-label>
|
||||
<mat-select formControlName="columnSelectionToDisplay">
|
||||
<mat-option [value]="'enabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'disabled'">
|
||||
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@ -15,28 +15,31 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<section class="tb-widget-settings" [formGroup]="timeseriesTableWidgetSettingsForm" fxLayout="column">
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title" translate>widgets.table.common-table-settings</legend>
|
||||
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px">
|
||||
<section fxLayout="column" fxFlex>
|
||||
<mat-checkbox formControlName="enableSearch">
|
||||
{{ 'widgets.table.enable-search' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-checkbox formControlName="enableSelectColumnDisplay">
|
||||
{{ 'widgets.table.enable-select-column-display' | translate }}
|
||||
</mat-checkbox>
|
||||
</section>
|
||||
<section fxLayout="column" fxFlex>
|
||||
<mat-checkbox formControlName="enableStickyHeader">
|
||||
<ng-container [formGroup]="timeseriesTableWidgetSettingsForm">
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.table-header</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableStickyHeader">
|
||||
{{ 'widgets.table.enable-sticky-header' | translate }}
|
||||
</mat-checkbox>
|
||||
<mat-checkbox formControlName="enableStickyAction">
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSearch">
|
||||
{{ 'widgets.table.enable-search' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableSelectColumnDisplay">
|
||||
{{ 'widgets.table.enable-select-column-display' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.columns</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="showTimestamp">
|
||||
{{ 'widgets.table.display-timestamp' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="showMilliseconds">
|
||||
{{ 'widgets.table.display-milliseconds' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="enableStickyAction">
|
||||
{{ 'widgets.table.enable-sticky-action' | translate }}
|
||||
</mat-checkbox>
|
||||
</section>
|
||||
</section>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
</mat-slide-toggle>
|
||||
<mat-form-field fxFlex subscriptSizing="dynamic">
|
||||
<mat-label translate>widgets.table.hidden-cell-button-display-mode</mat-label>
|
||||
<mat-select formControlName="reserveSpaceForHiddenAction">
|
||||
<mat-option [value]="'true'">
|
||||
@ -47,41 +50,39 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<section fxLayout="column" fxLayoutGap="8px">
|
||||
<mat-slide-toggle formControlName="showTimestamp">
|
||||
{{ 'widgets.table.display-timestamp' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle formControlName="showMilliseconds">
|
||||
{{ 'widgets.table.display-milliseconds' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap="8px" fxLayoutAlign.gt-xs="start center">
|
||||
<mat-slide-toggle fxFlex formControlName="displayPagination">
|
||||
</div>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.pagination</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="displayPagination">
|
||||
{{ 'widgets.table.display-pagination' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.table.default-page-size</mat-label>
|
||||
<input matInput type="number" min="1" step="1" formControlName="defaultPageSize">
|
||||
<div class="tb-widget-config-row space-between">
|
||||
<div translate>widgets.table.default-page-size</div>
|
||||
<mat-form-field appearance="outline" class="center number" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="defaultPageSize" type="number" min="1" step="1" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
<mat-slide-toggle formControlName="useEntityLabel">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-widget-config-panel">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.table-tabs</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" formControlName="useEntityLabel">
|
||||
{{ 'widgets.table.use-entity-label-tab-name' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle formControlName="hideEmptyLines">
|
||||
</div>
|
||||
<div class="tb-widget-config-panel tb-slide-toggle" style="padding-bottom: 16px;">
|
||||
<div class="tb-widget-config-panel-title" translate>widgets.table.rows</div>
|
||||
<mat-slide-toggle class="mat-slide no-margin" style="padding-left: 16px;" formControlName="hideEmptyLines">
|
||||
{{ 'widgets.table.hide-empty-lines' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</section>
|
||||
</fieldset>
|
||||
<fieldset class="fields-group fields-group-slider">
|
||||
<legend class="group-title" translate>widgets.table.row-style</legend>
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableWidgetSettingsForm.get('useRowStyleFunction').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title>
|
||||
<mat-slide-toggle formControlName="useRowStyleFunction" (click)="$event.stopPropagation()"
|
||||
<mat-expansion-panel-header fxLayout="row wrap" class="fill-width">
|
||||
<mat-panel-title fxFlex="60">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="useRowStyleFunction" (click)="$event.stopPropagation()"
|
||||
fxLayoutAlign="center">
|
||||
{{ 'widgets.table.use-row-style-function' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</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
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
@ -95,5 +96,5 @@
|
||||
</tb-js-func>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</fieldset>
|
||||
</section>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@ -16,11 +16,12 @@
|
||||
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-error',
|
||||
template: `
|
||||
<div [@animation]="state" style="margin-top:0.5rem;font-size:.75rem">
|
||||
<div [@animation]="state" [ngStyle]="{marginTop: noMargin ? '0' : '0.5rem', fontSize: '.75rem'}">
|
||||
<mat-error >
|
||||
{{message}}
|
||||
</mat-error>
|
||||
@ -51,6 +52,10 @@ export class TbErrorComponent {
|
||||
state: any;
|
||||
message;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
noMargin = false;
|
||||
|
||||
@Input()
|
||||
set error(value) {
|
||||
if (value && !this.message) {
|
||||
|
||||
@ -1188,7 +1188,9 @@
|
||||
"delta-calculation-result": "Delta calculation result",
|
||||
"delta-calculation-result-previous-value": "Previous value",
|
||||
"delta-calculation-result-delta-absolute": "Delta (absolute)",
|
||||
"delta-calculation-result-delta-percent": "Delta (percent)"
|
||||
"delta-calculation-result-delta-percent": "Delta (percent)",
|
||||
"source": "Source",
|
||||
"latest": "Latest"
|
||||
},
|
||||
"datasource": {
|
||||
"type": "Datasource type",
|
||||
@ -5240,7 +5242,9 @@
|
||||
"table-header": "Table header",
|
||||
"header-buttons": "Header buttons",
|
||||
"pagination": "Pagination",
|
||||
"rows": "Rows"
|
||||
"rows": "Rows",
|
||||
"timeseries-column-error": "At least one timeseries column should be specified",
|
||||
"table-tabs": "Table tabs"
|
||||
},
|
||||
"value-source": {
|
||||
"value-source": "Value source",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user