Add widgets help resources. Introduce datasources optional flag for widget type parameters.

This commit is contained in:
Igor Kulikov 2021-10-19 22:22:06 +03:00
parent c88a442603
commit 9bdc56f68c
31 changed files with 1047 additions and 21 deletions

View File

@ -19,8 +19,8 @@
"templateHtml": "<tb-alarms-table-widget \n [ctx]=\"ctx\">\n</tb-alarms-table-widget>",
"templateCss": "",
"controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.alarmsTableWidget.onDataUpdated();\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 };\n}\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms 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 \"enableFilter\": {\n \"title\": \"Enable alarm filter\",\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\": false\n },\n \"reserveSpaceForHiddenAction\": {\n \"title\": \"Hidden cell button actions display mode\",\n \"type\": \"string\",\n \"default\": \"true\"\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\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\": \"-createdTime\"\n },\n \"useRowStyleFunction\": {\n \"title\": \"Use row style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"rowStyleFunction\": {\n \"title\": \"Row style function: f(alarm, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableFilter\",\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 \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\",\n \"useRowStyleFunction\",\n {\n \"key\": \"rowStyleFunction\",\n \"type\": \"javascript\",\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, alarm, 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, alarm, 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 \"condition\": \"model.useCellStyleFunction === true\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\",\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}",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms 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 \"enableFilter\": {\n \"title\": \"Enable alarm filter\",\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\": false\n },\n \"reserveSpaceForHiddenAction\": {\n \"title\": \"Hidden cell button actions display mode\",\n \"type\": \"string\",\n \"default\": \"true\"\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\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\": \"-createdTime\"\n },\n \"useRowStyleFunction\": {\n \"title\": \"Use row style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"rowStyleFunction\": {\n \"title\": \"Row style function: f(alarm, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableFilter\",\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 \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\",\n \"useRowStyleFunction\",\n {\n \"key\": \"rowStyleFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/alarm/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, alarm, 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, alarm, 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/alarm/cell_style_fn\",\n \"condition\": \"model.useCellStyleFunction === true\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/alarm/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,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStickyAction\":false,\"enableFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{},\"alarmStatusList\":[],\"alarmSeverityList\":[],\"alarmTypeList\":[],\"searchPropagatedAlarms\":false}"
}
}

File diff suppressed because one or more lines are too long

View File

@ -323,6 +323,9 @@ export class AliasController implements IAliasController {
}
resolveDatasources(datasources: Array<Datasource>, singleEntity?: boolean): Observable<Array<Datasource>> {
if (!datasources || !datasources.length) {
return of([]);
}
const toResolve = singleEntity ? [datasources[0]] : datasources;
const observables = new Array<Observable<Datasource>>();
toResolve.forEach((datasource) => {

View File

@ -387,7 +387,7 @@ export class WidgetSubscription implements IWidgetSubscription {
}
private prepareDataSubscriptions(): Observable<any> {
if (this.hasDataPageLink) {
if (this.hasDataPageLink || !this.configuredDatasources || !this.configuredDatasources.length) {
this.hasResolvedData = true;
this.notifyDataLoaded();
return of(null);

View File

@ -873,6 +873,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
if (revert) {
this.dashboard = this.prevDashboard;
this.dashboardLogoCache = undefined;
this.dashboardConfiguration = this.dashboard.configuration;
}
} else {
this.resetHighlight();

View File

@ -19,7 +19,7 @@
import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models';
import * as moment_ from 'moment';
import { DataKeyType } from "@shared/models/telemetry/telemetry.models";
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { ComparisonDuration } from '@shared/models/time/time.models';
export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph';
@ -466,7 +466,7 @@ export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
schema.form.push({
key: 'tooltipValueFormatter',
type: 'javascript',
helpId: 'widget/lib/tooltip_value_format_fn'
helpId: 'widget/lib/flot/tooltip_value_format_fn'
});
schema.form.push('hideZeros');
schema.form.push('showTooltip');
@ -516,7 +516,8 @@ export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
},
{
key: 'yaxis.ticksFormatter',
type: 'javascript'
type: 'javascript',
helpId: 'widget/lib/flot/ticks_formatter_fn'
}
]
});
@ -531,11 +532,11 @@ export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
schema.form.push(chartSettingsSchemaForComparison.form, chartSettingsSchemaForCustomLegend.form);
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Comparison Settings'
GroupTitle: 'Comparison Settings'
});
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Custom Legend Settings'
GroupTitle: 'Custom Legend Settings'
});
}
return schema;
@ -981,13 +982,15 @@ export function flotDatakeySettingsSchema(defaultShowLines: boolean, chartType:
},
{
key: 'pointShapeFormatter',
type: 'javascript'
type: 'javascript',
helpId: 'widget/lib/flot/point_shape_format_fn'
},
'showPointsLineWidth',
'showPointsRadius',
{
key: 'tooltipValueFormatter',
type: 'javascript'
type: 'javascript',
helpId: 'widget/lib/flot/tooltip_value_format_fn'
},
'showSeparateAxis',
'axisMin',
@ -1012,7 +1015,8 @@ export function flotDatakeySettingsSchema(defaultShowLines: boolean, chartType:
},
{
key: 'axisTicksFormatter',
type: 'javascript'
type: 'javascript',
helpId: 'widget/lib/flot/ticks_formatter_fn'
}
]
};

View File

@ -96,6 +96,8 @@ export class MarkdownWidgetComponent extends PageComponent implements OnInit {
data: []
}
];
} else {
initialData = [];
}
let markdownText: string;
if (initialData) {

View File

@ -491,6 +491,9 @@ export class WidgetComponentService {
if (isUndefined(result.typeParameters.dataKeysOptional)) {
result.typeParameters.dataKeysOptional = false;
}
if (isUndefined(result.typeParameters.datasourcesOptional)) {
result.typeParameters.datasourcesOptional = false;
}
if (isUndefined(result.typeParameters.stateData)) {
result.typeParameters.stateData = false;
}

View File

@ -894,7 +894,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
};
}
} else if (this.widgetType !== widgetType.static && this.modelValue.isDataEnabled) {
if (!config.datasources || !config.datasources.length) {
if (!this.modelValue.typeParameters.datasourcesOptional && (!config.datasources || !config.datasources.length)) {
return {
datasources: {
valid: false

View File

@ -152,6 +152,7 @@ export interface WidgetTypeParameters {
useCustomDatasources?: boolean;
maxDatasources?: number;
maxDataKeys?: number;
datasourcesOptional?: boolean;
dataKeysOptional?: boolean;
stateData?: boolean;
hasDataPageLink?: boolean;

View File

@ -57,3 +57,6 @@ var index = Math.floor((time/3 % 14000) / 1000);
return lats[index];
{:copy-code}
```
<br>
<br>

View File

@ -54,3 +54,6 @@ if (prevOrigValue) {
}
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,52 @@
#### Cell content function
<div class="divider"></div>
<br/>
*function (value, alarm, ctx): string*
A JavaScript function used to compute alarm cell content HTML depending on alarm field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An alarm field value displayed in the cell.
</li>
<li><b>alarm:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a> object
presenting basic alarm properties (ex. <code>type</code>, <code>severity</code>, <code>originator</code>, etc.) and <br> provides access to other alarm or originator entity fields/attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return string value presenting cell content HTML.
<div class="divider"></div>
##### Examples
* Format alarm start time using date/time pattern:
```javascript
var startTime = value;
return startTime ? ctx.date.transform(startTime, 'yyyy-MM-dd HH:mm:ss') : '';
{:copy-code}
```
* Styled cell content for originator alarm field:
```javascript
var originator = value;
return '<div style="border: 2px solid #0072ff; ' +
'border-radius: 10px; padding: 5px; ' +
'background-color: #e0e1ff; ' +
'text-align: center;">' + originator + '</div>';
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,62 @@
#### Cell style function
<div class="divider"></div>
<br/>
*function (value, alarm, ctx): {[key: string]: string}*
A JavaScript function used to compute alarm cell style depending on alarm field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An alarm field value displayed in the cell.
</li>
<li><b>alarm:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a> object
presenting basic alarm properties (ex. <code>type</code>, <code>severity</code>, <code>originator</code>, etc.) and <br> provides access to other alarm or originator entity fields/attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set color depending on alarm severity:
```javascript
var severity = value;
var color = 'black';
switch (severity) {
case 'CRITICAL':
color = 'red';
break;
case 'MAJOR':
color = 'orange';
break;
case 'MINOR':
color = '#ffca3d';
break;
case 'WARNING':
color = '#abab00';
break;
case 'INDETERMINATE':
color = 'green';
break;
}
return {
fontWeight: 'bold',
color: color
};
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,59 @@
#### Row style function
<div class="divider"></div>
<br/>
*function (alarm, ctx): {[key: string]: string}*
A JavaScript function used to compute alarm row style depending on alarm value.
**Parameters:**
<ul>
<li><b>alarm:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/shared/models/alarm.models.ts#L108" target="_blank">AlarmDataInfo</a> object
presenting basic alarm properties (ex. <code>type</code>, <code>severity</code>, <code>originator</code>, etc.) and <br> provides access to other alarm or originator entity fields/attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set row background color depending on alarm severity:
```javascript
var severity = alarm.severity;
var color = '#fff';
switch (severity) {
case 'CRITICAL':
color = 'red';
break;
case 'MAJOR':
color = 'orange';
break;
case 'MINOR':
color = '#ffca3d';
break;
case 'WARNING':
color = '#abab00';
break;
case 'INDETERMINATE':
color = 'green';
break;
}
return {
backgroundColor: color
};
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,40 @@
#### Node disabled function
<div class="divider"></div>
<br/>
*function (nodeCtx): boolean*
A JavaScript function evaluating whether current node should be disabled (not selectable).
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
`true` if node should be disabled (not selectable), `false` otherwise.
<div class="divider"></div>
##### Examples
* Disable current node according to the value of example `nodeDisabled` attribute:
```javascript
var data = nodeCtx.data;
if (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {
return data['nodeDisabled'] === 'true';
} else {
return false;
}
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,47 @@
#### Node has children function
<div class="divider"></div>
<br/>
*function (nodeCtx): boolean*
A JavaScript function evaluating whether current node has children (whether it can be expanded).
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
`true` if node should have children, `false` otherwise.
<div class="divider"></div>
##### Examples
* Restrict entities hierarchy expansion up to third level:
```javascript
return nodeCtx.level <= 2;
{:copy-code}
```
* Restrict entities expansion according to the value of example `nodeHasChildren` attribute:
```javascript
var data = nodeCtx.data;
if (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {
return data['nodeHasChildren'] === 'true';
} else {
return true;
}
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,53 @@
#### Node icon function
<div class="divider"></div>
<br/>
*function (nodeCtx): {iconUrl?: string, materialIcon?: string} | 'default'*
A JavaScript function used to compute node icon info.
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
Should return node icon info object with the following structure:
```typescript
{
iconUrl?: string,
materialIcon?: string
}
```
Resulting object should contain either `materialIcon` or `iconUrl` property.<br>
Where:
- `materialIcon` - name of the material icon to be used from the [Material Icons Library{:target="_blank"}](https://material.io/tools/icons);
- `iconUrl` - url of the external image to be used as node icon.
Function can return `default` string value. In this case default icons according to entity type will be used.
<div class="divider"></div>
##### Examples
* Use external image for devices which name starts with `Test` and use default icons for the rest of entities:
```javascript
var entity = nodeCtx.entity;
if (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {
return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};
} else {
return 'default';
}
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,35 @@
#### Node opened by default function
<div class="divider"></div>
<br/>
*function (nodeCtx): boolean*
A JavaScript function evaluating whether current node should be opened (expanded) when it first loaded.
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
`true` if node should be opened (expanded), `false` otherwise.
<div class="divider"></div>
##### Examples
* Open by default nodes up to third level:
```javascript
return nodeCtx.level <= 2;
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,49 @@
#### Node relations query function
<div class="divider"></div>
<br/>
*function (nodeCtx): [EntityRelationsQuery{:target="_blank"}](https://github.com/thingsboard/thingsboard/blob/dda61383933cac9aa6821a77ff9b19291e69db9f/ui-ngx/src/app/shared/models/relation.models.ts#L69) | 'default'*
A JavaScript function used to compute child nodes relations query for current node.
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
Should return [EntityRelationsQuery{:target="_blank"}](https://github.com/thingsboard/thingsboard/blob/dda61383933cac9aa6821a77ff9b19291e69db9f/ui-ngx/src/app/shared/models/relation.models.ts#L69) for current node used to fetch entity children.<br>
Function can return `default` string value. In this case default relations query will be used.
<div class="divider"></div>
##### Examples
* Fetch child entities having relations of type `Contains` from the current entity:
```javascript
var entity = nodeCtx.entity;
var query = {
parameters: {
rootId: entity.id.id,
rootType: entity.id.entityType,
direction: "FROM",
maxLevel: 1
},
filters: [{
relationType: "Contains",
entityTypes: []
}]
};
return query;
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,41 @@
#### Node text function
<div class="divider"></div>
<br/>
*function (nodeCtx): string*
A JavaScript function used to compute text or HTML code for the current node.
**Parameters:**
<ul>
<li><b>nodeCtx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a> object
containing <code>entity</code> field holding basic entity properties <br> (ex. <code>id</code>, <code>name</code>, <code>label</code>) and <code>data</code> field holding other entity attributes/timeseries declared in widget datasource configuration.
</li>
</ul>
**Returns:**
Should return string value presenting text or HTML for the current node.
<div class="divider"></div>
##### Examples
* Display entity name and optionally temperature value if it is present in entity attributes/timeseries:
```javascript
var data = nodeCtx.data;
var entity = nodeCtx.entity;
var text = entity.name;
if (data.hasOwnProperty('temperature') && data['temperature'] !== null) {
text += " <b>"+ data['temperature'] +" °C</b>";
}
return text;
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,44 @@
#### Nodes sort function
<div class="divider"></div>
<br/>
*function (nodeCtx1, nodeCtx2): number*
A JavaScript function used to compare nodes of the same level when sorting.
**Parameters:**
<ul>
<li><b>nodeCtx1:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - First
node object to be compared.
</li>
<li><b>nodeCtx2:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts#L35" target="_blank">HierarchyNodeContext</a></code> - Second
node object to be compared.
</li>
</ul>
**Returns:**
Should return integer value presenting nodes comparison result:
- **less than 0** - sort `nodeCtx1` to an index lower than `nodeCtx2`;
- **0** - leave `nodeCtx1` and `nodeCtx2` unchanged with respect to each other;
- **greater than 0** - sort `nodeCtx2` to an index lower than `nodeCtx1`;
<div class="divider"></div>
##### Examples
* Sort entities first by entity type in alphabetical order then by entity name in alphabetical order:
```javascript
var result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);
if (result === 0) {
result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);
}
return result;
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,61 @@
#### Cell content function
<div class="divider"></div>
<br/>
*function (value, entity, ctx): string*
A JavaScript function used to compute entity cell content HTML depending on entity field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An entity field value displayed in the cell.
</li>
<li><b>entity:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a> object
presenting basic entity properties (ex. <code>id</code>, <code>entityName</code>) and <br> provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return string value presenting cell content HTML.
<div class="divider"></div>
##### Examples
* Format entity created time using date/time pattern:
```javascript
var createdTime = value;
return createdTime ? ctx.date.transform(createdTime, 'yyyy-MM-dd HH:mm:ss') : '';
{:copy-code}
```
* Styled cell content for device type field:
```javascript
var deviceType = value;
var color = '#fff';
switch (deviceType) {
case 'thermostat':
color = 'orange';
break;
case 'default':
color = '#abab00';
break;
}
return '<div style="border: 2px solid #0072ff; ' +
'border-radius: 10px; padding: 5px; ' +
'background-color: '+ color +'; ' +
'text-align: center;">' + deviceType + '</div>';
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,52 @@
#### Cell style function
<div class="divider"></div>
<br/>
*function (value, entity, ctx): {[key: string]: string}*
A JavaScript function used to compute entity cell style depending on entity field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An entity field value displayed in the cell.
</li>
<li><b>entity:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a> object
presenting basic entity properties (ex. <code>id</code>, <code>entityName</code>) and <br> provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set color depending on device temperature value:
```javascript
var temperature = value;
var color = 'black';
if (temperature) {
if (temperature > 25) {
color = 'red';
} else {
color = 'green';
}
}
return {
fontWeight: 'bold',
color: color
};
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,50 @@
#### Row style function
<div class="divider"></div>
<br/>
*function (entity, ctx): {[key: string]: string}*
A JavaScript function used to compute entity row style depending on entity value.
**Parameters:**
<ul>
<li><b>entity:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a></code> - An
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/table-widget.models.ts#L61" target="_blank">EntityData</a> object
presenting basic entity properties (ex. <code>id</code>, <code>entityName</code>) and <br> provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set row background color depending on device type:
```javascript
var deviceType = entity.Type;
var color = '#fff';
switch (deviceType) {
case 'thermostat':
color = 'orange';
break;
case 'default':
color = '#abab00';
break;
}
return {
backgroundColor: color
};
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,111 @@
#### Point shape draw function
<div class="divider"></div>
<br/>
*function (ctx, x, y, radius, shadow): void*
A JavaScript function used to draw custom shapes for chart points when `Custom function` for point shape is selected.
**Parameters:**
<ul>
<li>
<b>ctx:</b> <code><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">CanvasRenderingContext2D</a></code> - A canvas drawing context.
</li>
<li>
<b>x</b> <code>number</code> - point center X coordinate.
</li>
<li>
<b>y</b> <code>number</code> - point center Y coordinate.
</li>
<li>
<b>radius</b> <code>number</code> - point radius.
</li>
<li>
<b>shadow</b> <code>boolean</code> - whether to draw shadow.
</li>
</ul>
<div class="divider"></div>
##### Examples
* Draw square:
```javascript
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.rect(x - size, y - size, size + size, size + size);
{:copy-code}
```
* Draw circle:
```javascript
ctx.moveTo(x + radius, y);
ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
{:copy-code}
```
* Draw diamond:
```javascript
var size = radius * Math.sqrt(Math.PI / 2);
ctx.moveTo(x - size, y);
ctx.lineTo(x, y - size);
ctx.lineTo(x + size, y);
ctx.lineTo(x, y + size);
ctx.lineTo(x - size, y);
ctx.lineTo(x, y - size);
{:copy-code}
```
* Draw triangle:
```javascript
var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
var height = size * Math.sin(Math.PI / 3);
ctx.moveTo(x - size / 2, y + height / 2);
ctx.lineTo(x + size / 2, y + height / 2);
if (!shadow) {
ctx.lineTo(x, y - height / 2);
ctx.lineTo(x - size / 2, y + height / 2);
ctx.lineTo(x + size / 2, y + height / 2);
}
{:copy-code}
```
* Draw cross:
```javascript
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.moveTo(x - size, y - size);
ctx.lineTo(x + size, y + size);
ctx.moveTo(x - size, y + size);
ctx.lineTo(x + size, y - size);
{:copy-code}
```
* Draw ellipse:
```javascript
if (!shadow) {
ctx.moveTo(x + radius, y);
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
}
{:copy-code}
```
* Draw plus:
```javascript
var size = radius * Math.sqrt(Math.PI / 2);
ctx.moveTo(x - size, y);
ctx.lineTo(x + size, y);
ctx.moveTo(x, y + size);
ctx.lineTo(x, y - size);
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,93 @@
#### Ticks formatter function
<div class="divider"></div>
<br/>
*function (value): string*
A JavaScript function used to format Y axis ticks.
**Parameters:**
<ul>
<li><b>value:</b> <code>number</code> - A tick value that should be formatted.
</li>
</ul>
**Returns:**
A string presenting the formatted value to be displayed as Y axis tick.
<div class="divider"></div>
##### Examples
* Display ticks as is:
```javascript
return value;
{:copy-code}
```
* Present ticks in Amperage (A) units and two decimal places:
```javascript
return value.toFixed(2) + ' A';
{:copy-code}
```
* Disable ticks:
```javascript
return '';
{:copy-code}
```
<ul>
<li>
To present axis ticks for true / false or 1 / 0 data.<br>
Display <code>On</code> when value > <code>0</code> and <= <code>1</code>,<br>
<code>Off</code> when value = <code>0</code>,<br>
disable for all other values.<br>
<strong>Note: </strong> To avoid duplicates among Y axis ticks it is recommended to set <strong><i>Steps size between ticks</i></strong> to <code>1</code>:
</li>
</ul>
```javascript
if (value > 0 && value <= 1) {
return 'On';
} else if (value === 0) {
return 'Off';
} else {
return '';
}
{:copy-code}
```
<ul>
<li>
To present axis ticks for state or level data.<br>
Display <code>High</code> when value >= <code>2</code>,<br>
<code>Medium</code> when value >= <code>1</code> and < <code>2</code>,<br>
<code>Low</code> when value >= <code>0</code> and < <code>1</code>,<br>
disable for all other values.<br>
<strong>Note: </strong> To avoid duplicates among Y axis ticks it is recommended to set <strong><i>Steps size between ticks</i></strong> to <code>1</code><br>
or other suitable value depending on your case:
</li>
</ul>
```javascript
if (value >= 2) {
return 'High';
} else if (value >= 1) {
return 'Medium';
} else if (value >= 0) {
return 'Low';
} else {
return '';
}
{:copy-code}
```
<br>
<br>

View File

@ -35,3 +35,6 @@ return value + ' °C';
return value.toFixed(2) + ' A';
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,53 @@
#### Cell content function
<div class="divider"></div>
<br/>
*function (value, rowData, ctx): string*
A JavaScript function used to compute timeseries cell content HTML depending on timeseries field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An entity field value displayed in the cell.
</li>
<li><b>rowData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a></code> - A
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a> object
presenting <code>formattedTs</code> (a string value of formatted timestamp) and <br> timeseries values for each column declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return string value presenting cell content HTML.
<div class="divider"></div>
##### Examples
* Styled cell content for temperature field:
```javascript
var temperature = value;
var color = '#fff';
if (temperature) {
if (temperature > 25) {
color = 'red';
} else {
color = 'green';
}
}
return '<div style="border: 2px solid #0072ff; ' +
'border-radius: 10px; padding: 5px; ' +
'color: #fff; ' +
'background-color: '+ color +'; ' +
'text-align: center;">' + temperature + '</div>';
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,52 @@
#### Cell style function
<div class="divider"></div>
<br/>
*function (value, rowData, ctx): {[key: string]: string}*
A JavaScript function used to compute timeseries cell style depending on timeseries field value.
**Parameters:**
<ul>
<li><b>value:</b> <code>any</code> - An timeseries field value displayed in the cell.
</li>
<li><b>rowData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a></code> - A
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a> object
presenting <code>formattedTs</code> (a string value of formatted timestamp) and <br> timeseries values for each column declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set color depending on temperature value:
```javascript
var temperature = value;
var color = 'black';
if (temperature) {
if (temperature > 25) {
color = 'red';
} else {
color = 'green';
}
}
return {
fontWeight: 'bold',
color: color
};
{:copy-code}
```
<br>
<br>

View File

@ -0,0 +1,49 @@
#### Row style function
<div class="divider"></div>
<br/>
*function (rowData, ctx): {[key: string]: string}*
A JavaScript function used to compute timeseries row style depending on row value.
**Parameters:**
<ul>
<li><b>rowData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a></code> - A
<a href="https://github.com/thingsboard/thingsboard/blob/e264f7b8ddff05bda85c4833bf497f47f447496e/ui-ngx/src/app/modules/home/components/widget/lib/timeseries-table-widget.component.ts#L80" target="_blank">TimeseriesRow</a> object
presenting <code>formattedTs</code> (a string value of formatted timestamp) and <br> timeseries values for each column declared in widget datasource configuration.
</li>
<li><b>ctx:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a></code> - A reference to <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/models/widget-component.models.ts#L107" target="_blank">WidgetContext</a> that has all necessary API
and data used by widget instance.
</li>
</ul>
**Returns:**
Should return key/value object presenting style attributes.
<div class="divider"></div>
##### Examples
* Set row background color depending on temperature value:
```javascript
var temperature = rowData.temperature;
var color = '#fff';
if (temperature) {
if (temperature > 25) {
color = 'red';
} else {
color = 'green';
}
}
return {
backgroundColor: color
};
{:copy-code}
```
<br>
<br>