diff --git a/application/src/main/data/json/system/widget_bundles/cards.json b/application/src/main/data/json/system/widget_bundles/cards.json
index 7a83eb1fe1..4930219741 100644
--- a/application/src/main/data/json/system/widget_bundles/cards.json
+++ b/application/src/main/data/json/system/widget_bundles/cards.json
@@ -135,9 +135,11 @@
"templateHtml": "\n",
"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",
- "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}",
- "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}",
- "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;\"}]}]}"
+ "settingsSchema": "",
+ "dataKeySettingsSchema": "",
+ "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}]}]}"
}
},
{
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.html
new file mode 100644
index 0000000000..8714a5b820
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.html
@@ -0,0 +1,95 @@
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.ts
new file mode 100644
index 0000000000..9ec2482de8
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-key-settings.component.ts
@@ -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,
+ 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});
+ }
+
+}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.html
new file mode 100644
index 0000000000..e58f083bea
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.html
@@ -0,0 +1,116 @@
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.ts
new file mode 100644
index 0000000000..3d40a01484
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/entities-table-widget-settings.component.ts
@@ -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,
+ 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});
+ }
+
+}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/timeseries-table-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/timeseries-table-key-settings.component.html
index bf568fc3eb..f8a2b852d2 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/timeseries-table-key-settings.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/timeseries-table-key-settings.component.html
@@ -31,7 +31,8 @@
-
-
-
-
-