UI: Add entities table widget and key settings form

This commit is contained in:
Igor Kulikov 2022-04-04 14:07:35 +03:00
parent 323c67ff2a
commit a735586f1e
10 changed files with 461 additions and 12 deletions

View File

@ -135,9 +135,11 @@
"templateHtml": "<tb-entities-table-widget \n [ctx]=\"ctx\">\n</tb-entities-table-widget>", "templateHtml": "<tb-entities-table-widget \n [ctx]=\"ctx\">\n</tb-entities-table-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n hasDataPageLink: true,\n warnOnPageDataOverflow: false,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true,\n hasShowCondition: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n },\n 'rowDoubleClick': {\n name: 'widget-action.row-double-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n hasDataPageLink: true,\n warnOnPageDataOverflow: false,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true,\n hasShowCondition: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n },\n 'rowDoubleClick': {\n name: 'widget-action.row-double-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"entitiesTitle\": {\n \"title\": \"Entities table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSearch\": {\n \"title\": \"Enable entities search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStickyHeader\": {\n \"title\": \"Always display header\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStickyAction\": {\n \"title\": \"Always display actions column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"reserveSpaceForHiddenAction\": {\n \"title\": \"Hidden cell button actions display mode\",\n \"type\": \"string\",\n \"default\": \"true\"\n },\n \"displayEntityName\": {\n \"title\": \"Display entity name column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"entityNameColumnTitle\": {\n \"title\": \"Entity name column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityLabel\": {\n \"title\": \"Display entity label column\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"entityLabelColumnTitle\": {\n \"title\": \"Entity label column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityType\": {\n \"title\": \"Display entity type column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"entityName\"\n },\n \"useRowStyleFunction\": {\n \"title\": \"Use row style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"rowStyleFunction\": {\n \"title\": \"Row style function: f(entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"entitiesTitle\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableStickyHeader\",\n \"enableStickyAction\",\n {\n \"key\": \"reserveSpaceForHiddenAction\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"true\",\n \"label\": \"Show empty space instead of hidden cell button action\"\n },\n {\n \"value\": \"false\",\n \"label\": \"Don't reserve space for hidden action buttons\"\n }\n ]\n },\n \"displayEntityName\",\n \"entityNameColumnTitle\",\n \"displayEntityLabel\",\n \"entityLabelColumnTitle\",\n \"displayEntityType\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\",\n \"useRowStyleFunction\",\n {\n \"key\": \"rowStyleFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/entity/row_style_fn\",\n \"condition\": \"model.useRowStyleFunction === true\"\n }\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value, entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"defaultColumnVisibility\": {\n \"title\": \"Default column visibility\",\n \"type\": \"string\",\n \"default\": \"visible\"\n },\n \"columnSelectionToDisplay\": {\n \"title\": \"Column selection in 'Columns to Display'\",\n \"type\": \"string\",\n \"default\": \"enabled\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/entity/cell_style_fn\",\n \"condition\": \"model.useCellStyleFunction === true\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/entity/cell_content_fn\",\n \"condition\": \"model.useCellContentFunction === true\"\n },\n {\n \"key\": \"defaultColumnVisibility\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"visible\",\n \"label\": \"Visible\"\n },\n {\n \"value\": \"hidden\",\n \"label\": \"Hidden\"\n } \n ]\n },\n {\n \"key\": \"columnSelectionToDisplay\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"enabled\",\n \"label\": \"Enabled\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n } \n ]\n }\n ]\n}", "dataKeySettingsSchema": "",
"defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}]}" "settingsDirective": "tb-entities-table-widget-settings",
"dataKeySettingsDirective": "tb-entities-table-key-settings",
"defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"entitiesTitle\":\"\",\"enableSearch\":true,\"enableSelectColumnDisplay\":true,\"enableStickyHeader\":true,\"enableStickyAction\":true,\"reserveSpaceForHiddenAction\":\"true\",\"displayEntityName\":true,\"entityNameColumnTitle\":\"\",\"displayEntityLabel\":false,\"displayEntityType\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"useRowStyleFunction\":false},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"useCellContentFunction\":false,\"defaultColumnVisibility\":\"visible\",\"columnSelectionToDisplay\":\"enabled\"},\"_hash\":0.6401141393938932,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}]}"
} }
}, },
{ {

View File

@ -0,0 +1,95 @@
<!--
Copyright © 2016-2022 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.
-->
<section class="tb-widget-settings" [formGroup]="entitiesTableKeySettingsForm" fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.column-width</mat-label>
<input matInput formControlName="columnWidth">
</mat-form-field>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="entitiesTableKeySettingsForm.get('useCellStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle 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>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'entity', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
helpId="widget/lib/entity/cell_style_fn">
</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>
<mat-expansion-panel class="tb-settings" [expanded]="entitiesTableKeySettingsForm.get('useCellContentFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle 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>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'entity', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"
helpId="widget/lib/entity/cell_content_fn">
</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-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>

View File

@ -0,0 +1,86 @@
///
/// Copyright © 2016-2022 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-entities-table-key-settings',
templateUrl: './entities-table-key-settings.component.html',
styleUrls: ['./widget-settings.scss']
})
export class EntitiesTableKeySettingsComponent extends WidgetSettingsComponent {
entitiesTableKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.entitiesTableKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
columnWidth: '0px',
useCellStyleFunction: false,
cellStyleFunction: '',
useCellContentFunction: false,
cellContentFunction: '',
defaultColumnVisibility: 'visible',
columnSelectionToDisplay: 'enabled'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.entitiesTableKeySettingsForm = this.fb.group({
columnWidth: [settings.columnWidth, []],
useCellStyleFunction: [settings.useCellStyleFunction, []],
cellStyleFunction: [settings.cellStyleFunction, [Validators.required]],
useCellContentFunction: [settings.useCellContentFunction, []],
cellContentFunction: [settings.cellContentFunction, [Validators.required]],
defaultColumnVisibility: [settings.defaultColumnVisibility, []],
columnSelectionToDisplay: [settings.columnSelectionToDisplay, []],
});
}
protected validatorTriggers(): string[] {
return ['useCellStyleFunction', 'useCellContentFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useCellStyleFunction: boolean = this.entitiesTableKeySettingsForm.get('useCellStyleFunction').value;
const useCellContentFunction: boolean = this.entitiesTableKeySettingsForm.get('useCellContentFunction').value;
if (useCellStyleFunction) {
this.entitiesTableKeySettingsForm.get('cellStyleFunction').enable();
} else {
this.entitiesTableKeySettingsForm.get('cellStyleFunction').disable();
}
if (useCellContentFunction) {
this.entitiesTableKeySettingsForm.get('cellContentFunction').enable();
} else {
this.entitiesTableKeySettingsForm.get('cellContentFunction').disable();
}
this.entitiesTableKeySettingsForm.get('cellStyleFunction').updateValueAndValidity({emitEvent});
this.entitiesTableKeySettingsForm.get('cellContentFunction').updateValueAndValidity({emitEvent});
}
}

View File

@ -0,0 +1,116 @@
<!--
Copyright © 2016-2022 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.
-->
<section class="tb-widget-settings" [formGroup]="entitiesTableWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.table.common-table-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entities-table-title</mat-label>
<input matInput formControlName="entitiesTitle">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableSearch" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-search' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableSelectColumnDisplay" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-select-column-display' | translate }}
</mat-checkbox>
</section>
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableStickyHeader" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-header' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableStickyAction" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-action' | translate }}
</mat-checkbox>
</section>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.hidden-cell-button-display-mode</mat-label>
<mat-select formControlName="reserveSpaceForHiddenAction">
<mat-option [value]="'true'">
{{ 'widgets.table.show-empty-space-hidden-action' | translate }}
</mat-option>
<mat-option [value]="'false'">
{{ 'widgets.table.dont-reserve-space-hidden-action' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<section fxLayout="column" fxLayoutGap="8px">
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayEntityName">
{{ 'widgets.table.display-entity-name' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entity-name-column-title</mat-label>
<input matInput formControlName="entityNameColumnTitle">
</mat-form-field>
</section>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayEntityLabel">
{{ 'widgets.table.display-entity-label' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entity-label-column-title</mat-label>
<input matInput formControlName="entityLabelColumnTitle">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="displayEntityType">
{{ 'widgets.table.display-entity-type' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex 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">
</mat-form-field>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-sort-order</mat-label>
<input matInput formControlName="defaultSortOrder">
</mat-form-field>
</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]="entitiesTableWidgetSettingsForm.get('useRowStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle 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>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func required
formControlName="rowStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['entity', 'ctx']"
functionTitle="{{ 'widgets.table.row-style-function' | translate }}"
helpId="widget/lib/entity/row_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

View File

@ -0,0 +1,118 @@
///
/// Copyright © 2016-2022 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-entities-table-widget-settings',
templateUrl: './entities-table-widget-settings.component.html',
styleUrls: ['./widget-settings.scss']
})
export class EntitiesTableWidgetSettingsComponent extends WidgetSettingsComponent {
entitiesTableWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.entitiesTableWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
entitiesTitle: '',
enableSearch: true,
enableSelectColumnDisplay: true,
enableStickyHeader: true,
enableStickyAction: true,
reserveSpaceForHiddenAction: 'true',
displayEntityName: true,
entityNameColumnTitle: '',
displayEntityLabel: false,
entityLabelColumnTitle: '',
displayEntityType: true,
displayPagination: true,
defaultPageSize: 10,
defaultSortOrder: 'entityName',
useRowStyleFunction: false,
rowStyleFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.entitiesTableWidgetSettingsForm = this.fb.group({
entitiesTitle: [settings.entitiesTitle, []],
enableSearch: [settings.enableSearch, []],
enableSelectColumnDisplay: [settings.enableSelectColumnDisplay, []],
enableStickyHeader: [settings.enableStickyHeader, []],
enableStickyAction: [settings.enableStickyAction, []],
reserveSpaceForHiddenAction: [settings.reserveSpaceForHiddenAction, []],
displayEntityName: [settings.displayEntityName, []],
entityNameColumnTitle: [settings.entityNameColumnTitle, []],
displayEntityLabel: [settings.displayEntityLabel, []],
entityLabelColumnTitle: [settings.entityLabelColumnTitle, []],
displayEntityType: [settings.displayEntityType, []],
displayPagination: [settings.displayPagination, []],
defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]],
defaultSortOrder: [settings.defaultSortOrder, []],
useRowStyleFunction: [settings.useRowStyleFunction, []],
rowStyleFunction: [settings.rowStyleFunction, [Validators.required]]
});
}
protected validatorTriggers(): string[] {
return ['useRowStyleFunction', 'displayPagination', 'displayEntityName', 'displayEntityLabel'];
}
protected updateValidators(emitEvent: boolean) {
const useRowStyleFunction: boolean = this.entitiesTableWidgetSettingsForm.get('useRowStyleFunction').value;
const displayPagination: boolean = this.entitiesTableWidgetSettingsForm.get('displayPagination').value;
const displayEntityName: boolean = this.entitiesTableWidgetSettingsForm.get('displayEntityName').value;
const displayEntityLabel: boolean = this.entitiesTableWidgetSettingsForm.get('displayEntityLabel').value;
if (useRowStyleFunction) {
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').disable();
}
if (displayPagination) {
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').disable();
}
if (displayEntityName) {
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').disable();
}
if (displayEntityLabel) {
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').disable();
}
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').updateValueAndValidity({emitEvent});
}
}

View File

@ -31,7 +31,8 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-js-func formControlName="cellStyleFunction" <tb-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']" [functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}" functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
@ -55,7 +56,8 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-js-func formControlName="cellContentFunction" <tb-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']" [functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}" functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"

View File

@ -38,7 +38,8 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-js-func formControlName="cellStyleFunction" <tb-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']" [functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}" functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
@ -62,7 +63,8 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-js-func formControlName="cellContentFunction" <tb-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']" [functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}" functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"

View File

@ -83,7 +83,8 @@
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-js-func formControlName="rowStyleFunction" <tb-js-func required
formControlName="rowStyleFunction"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['rowData', 'ctx']" [functionArgs]="['rowData', 'ctx']"
functionTitle="{{ 'widgets.table.row-style-function' | translate }}" functionTitle="{{ 'widgets.table.row-style-function' | translate }}"

View File

@ -47,6 +47,12 @@ import {
import { import {
HtmlCardWidgetSettingsComponent HtmlCardWidgetSettingsComponent
} from '@home/components/widget/lib/settings/html-card-widget-settings.component'; } from '@home/components/widget/lib/settings/html-card-widget-settings.component';
import {
EntitiesTableWidgetSettingsComponent
} from '@home/components/widget/lib/settings/entities-table-widget-settings.component';
import {
EntitiesTableKeySettingsComponent
} from '@home/components/widget/lib/settings/entities-table-key-settings.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -61,7 +67,9 @@ import {
SimpleCardWidgetSettingsComponent, SimpleCardWidgetSettingsComponent,
DashboardStateWidgetSettingsComponent, DashboardStateWidgetSettingsComponent,
EntitiesHierarchyWidgetSettingsComponent, EntitiesHierarchyWidgetSettingsComponent,
HtmlCardWidgetSettingsComponent HtmlCardWidgetSettingsComponent,
EntitiesTableWidgetSettingsComponent,
EntitiesTableKeySettingsComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -80,7 +88,9 @@ import {
SimpleCardWidgetSettingsComponent, SimpleCardWidgetSettingsComponent,
DashboardStateWidgetSettingsComponent, DashboardStateWidgetSettingsComponent,
EntitiesHierarchyWidgetSettingsComponent, EntitiesHierarchyWidgetSettingsComponent,
HtmlCardWidgetSettingsComponent HtmlCardWidgetSettingsComponent,
EntitiesTableWidgetSettingsComponent,
EntitiesTableKeySettingsComponent
] ]
}) })
export class WidgetSettingsModule { export class WidgetSettingsModule {
@ -96,5 +106,7 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-simple-card-widget-settings': SimpleCardWidgetSettingsComponent, 'tb-simple-card-widget-settings': SimpleCardWidgetSettingsComponent,
'tb-dashboard-state-widget-settings': DashboardStateWidgetSettingsComponent, 'tb-dashboard-state-widget-settings': DashboardStateWidgetSettingsComponent,
'tb-entities-hierarchy-widget-settings': EntitiesHierarchyWidgetSettingsComponent, 'tb-entities-hierarchy-widget-settings': EntitiesHierarchyWidgetSettingsComponent,
'tb-html-card-widget-settings': HtmlCardWidgetSettingsComponent 'tb-html-card-widget-settings': HtmlCardWidgetSettingsComponent,
'tb-entities-table-widget-settings': EntitiesTableWidgetSettingsComponent,
'tb-entities-table-key-settings': EntitiesTableKeySettingsComponent
}; };

View File

@ -3456,7 +3456,22 @@
"use-cell-content-function": "Use cell content function", "use-cell-content-function": "Use cell content function",
"cell-content-function": "Cell content function", "cell-content-function": "Cell content function",
"show-latest-data-column": "Show latest data column", "show-latest-data-column": "Show latest data column",
"latest-data-column-order": "Latest data column order" "latest-data-column-order": "Latest data column order",
"entities-table-title": "Entities table title",
"enable-select-column-display": "Enable select columns to display",
"display-entity-name": "Display entity name column",
"entity-name-column-title": "Entity name column title",
"display-entity-label": "Display entity label column",
"entity-label-column-title": "Entity label column title",
"display-entity-type": "Display entity type column",
"default-sort-order": "Default sort order",
"column-width": "Column width (px or %)",
"default-column-visibility": "Default column visibility",
"column-visibility-visible": "Visible",
"column-visibility-hidden": "Hidden",
"column-selection-to-display": "Column selection in 'Columns to Display'",
"column-selection-to-display-enabled": "Enabled",
"column-selection-to-display-disabled": "Disabled"
} }
}, },
"icon": { "icon": {