1108 lines
26 KiB
TypeScript
Raw Normal View History

///
2021-01-11 13:42:16 +02:00
/// Copyright © 2016-2021 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.
///
2019-12-23 14:36:44 +02:00
// tslint:disable-next-line:no-reference
/// <reference path="../../../../../../../src/typings/jquery.flot.typings.d.ts" />
import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models';
2020-02-24 17:16:02 +02:00
import * as moment_ from 'moment';
import { DataKeyType } from "@shared/models/telemetry/telemetry.models";
2021-03-18 19:45:45 +02:00
import { ComparisonDuration } from '@shared/models/time/time.models';
export declare type ChartType = 'line' | 'pie' | 'bar' | 'state' | 'graph';
export declare type TbFlotSettings = TbFlotBaseSettings & TbFlotGraphSettings & TbFlotBarSettings & TbFlotPieSettings;
export declare type TooltipValueFormatFunction = (value: any) => string;
export declare type TbFlotTicksFormatterFunction = (t: number, a?: TbFlotPlotAxis) => string;
export interface TbFlotSeries extends DatasourceData, JQueryPlotSeriesOptions {
dataKey: TbFlotDataKey;
2020-02-24 17:16:02 +02:00
xaxisIndex?: number;
yaxisIndex?: number;
yaxis?: number;
}
export interface TbFlotDataKey extends DataKey {
settings?: TbFlotKeySettings;
tooltipValueFormatFunction?: TooltipValueFormatFunction;
}
export interface TbFlotPlotAxis extends JQueryPlotAxis, TbFlotAxisOptions {
options: TbFlotAxisOptions;
}
export interface TbFlotAxisOptions extends JQueryPlotAxisOptions {
tickUnits?: string;
hidden?: boolean;
keysInfo?: Array<{hidden: boolean}>;
ticksFormatterFunction?: TbFlotTicksFormatterFunction;
}
export interface TbFlotPlotDataSeries extends JQueryPlotDataSeries {
2020-02-24 17:16:02 +02:00
datasource?: Datasource;
dataKey?: TbFlotDataKey;
percent?: number;
}
export interface TbFlotPlotItem extends jquery.flot.item {
series: TbFlotPlotDataSeries;
}
export interface TbFlotHoverInfo {
seriesHover: Array<TbFlotSeriesHoverInfo>;
time?: any;
}
export interface TbFlotSeriesHoverInfo {
hoverIndex: number;
units: string;
decimals: number;
label: string;
color: string;
index: number;
tooltipValueFormatFunction: TooltipValueFormatFunction;
value: any;
time: any;
distance: number;
}
2020-02-26 18:15:04 +02:00
export interface TbFlotThresholdMarking {
lineWidth?: number;
color?: string;
[key: string]: any;
}
export interface TbFlotThresholdKeySettings {
yaxis: number;
lineWidth: number;
color: string;
}
export interface TbFlotGridSettings {
color: string;
backgroundColor: string;
tickColor: string;
outlineWidth: number;
verticalLines: boolean;
horizontalLines: boolean;
minBorderMargin: number;
margin: number;
}
export interface TbFlotXAxisSettings {
showLabels: boolean;
title: string;
color: boolean;
}
2020-02-24 17:16:02 +02:00
export interface TbFlotSecondXAxisSettings {
axisPosition: TbFlotXAxisPosition;
showLabels: boolean;
title: string;
}
export interface TbFlotYAxisSettings {
min: number;
max: number;
showLabels: boolean;
title: string;
color: string;
ticksFormatter: string;
tickDecimals: number;
tickSize: number;
}
export interface TbFlotBaseSettings {
stack: boolean;
shadowSize: number;
fontColor: string;
fontSize: number;
tooltipIndividual: boolean;
tooltipCumulative: boolean;
tooltipValueFormatter: string;
2020-02-24 17:16:02 +02:00
hideZeros: boolean;
grid: TbFlotGridSettings;
xaxis: TbFlotXAxisSettings;
yaxis: TbFlotYAxisSettings;
}
2020-02-24 17:16:02 +02:00
export interface TbFlotComparisonSettings {
comparisonEnabled: boolean;
2021-03-18 19:45:45 +02:00
timeForComparison: ComparisonDuration;
2020-02-24 17:16:02 +02:00
xaxisSecond: TbFlotSecondXAxisSettings;
}
2020-02-26 18:15:04 +02:00
export interface TbFlotThresholdsSettings {
thresholdsLineWidth: number;
}
export interface TbFlotCustomLegendSettings {
customLegendEnabled: boolean;
dataKeysListForLabels: Array<TbFlotLabelPatternSettings>;
}
export interface TbFlotLabelPatternSettings {
name: string;
type: DataKeyType;
settings?: any;
}
export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
smoothLines: boolean;
}
2020-02-26 18:15:04 +02:00
export declare type BarAlignment = 'left' | 'right' | 'center';
export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
defaultBarWidth: number;
2020-02-26 18:15:04 +02:00
barAlignment: BarAlignment;
}
export interface TbFlotPieSettings {
radius: number;
innerRadius: number;
tilt: number;
animatedPie: boolean;
stroke: {
color: string;
width: number;
};
showTooltip: boolean,
showLabels: boolean;
fontColor: string;
fontSize: number;
}
export declare type TbFlotYAxisPosition = 'left' | 'right';
2020-02-24 17:16:02 +02:00
export declare type TbFlotXAxisPosition = 'top' | 'bottom';
2020-02-26 18:15:04 +02:00
export declare type TbFlotThresholdValueSource = 'predefinedValue' | 'entityAttribute';
export interface TbFlotKeyThreshold {
thresholdValueSource: TbFlotThresholdValueSource;
thresholdEntityAlias: string;
thresholdAttribute: string;
thresholdValue: number;
lineWidth: number;
color: string;
}
export interface TbFlotKeyComparisonSettings {
showValuesForComparison: boolean;
comparisonValuesLabel: string;
color: string;
}
export interface TbFlotKeySettings {
2020-02-24 17:16:02 +02:00
excludeFromStacking: boolean;
2020-02-25 12:30:38 +02:00
hideDataByDefault: boolean;
disableDataHiding: boolean;
removeFromLegend: boolean;
showLines: boolean;
fillLines: boolean;
showPoints: boolean;
2020-02-24 17:16:02 +02:00
showPointShape: string;
pointShapeFormatter: string;
showPointsLineWidth: number;
showPointsRadius: number;
lineWidth: number;
tooltipValueFormatter: string;
showSeparateAxis: boolean;
axisMin: number;
axisMax: number;
axisTitle: string;
axisTickDecimals: number;
axisTickSize: number;
axisPosition: TbFlotYAxisPosition;
axisTicksFormatter: string;
2020-02-26 18:15:04 +02:00
thresholds: TbFlotKeyThreshold[];
comparisonSettings: TbFlotKeyComparisonSettings;
}
export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
const schema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
}
}
};
const properties: any = schema.schema.properties;
properties.stack = {
title: 'Stacking',
type: 'boolean',
default: false
};
if (chartType === 'graph') {
properties.smoothLines = {
title: 'Display smooth (curved) lines',
type: 'boolean',
default: false
};
}
if (chartType === 'bar') {
properties.defaultBarWidth = {
title: 'Default bar width for non-aggregated data (milliseconds)',
type: 'number',
default: 600
};
2020-02-26 18:15:04 +02:00
properties.barAlignment = {
title: 'Bar alignment',
type: 'string',
default: 'left'
};
}
if (chartType === 'graph' || chartType === 'bar') {
properties.thresholdsLineWidth = {
title: 'Default line width for all thresholds',
type: 'number'
};
}
properties.shadowSize = {
title: 'Shadow size',
type: 'number',
default: 4
};
properties.fontColor = {
title: 'Font color',
type: 'string',
default: '#545454'
};
properties.fontSize = {
title: 'Font size',
type: 'number',
default: 10
};
properties.tooltipIndividual = {
title: 'Hover individual points',
type: 'boolean',
default: false
};
properties.tooltipCumulative = {
title: 'Show cumulative values in stacking mode',
type: 'boolean',
default: false
};
properties.tooltipValueFormatter = {
title: 'Tooltip value format function, f(value)',
type: 'string',
default: ''
};
2020-02-24 17:16:02 +02:00
properties.hideZeros = {
title: 'Hide zero/false values from tooltip',
type: 'boolean',
default: false
};
properties.showTooltip = {
title: 'Show tooltip',
2021-08-19 18:13:37 +03:00
type: 'boolean',
2021-08-20 10:53:44 +03:00
default: true
2021-08-19 18:13:37 +03:00
};
properties.grid = {
title: 'Grid settings',
type: 'object',
properties: {
color: {
title: 'Primary color',
type: 'string',
default: '#545454'
},
backgroundColor: {
title: 'Background color',
type: 'string',
default: null
},
tickColor: {
title: 'Ticks color',
type: 'string',
default: '#DDDDDD'
},
outlineWidth: {
title: 'Grid outline/border width (px)',
type: 'number',
default: 1
},
verticalLines: {
title: 'Show vertical lines',
type: 'boolean',
default: true
},
horizontalLines: {
title: 'Show horizontal lines',
type: 'boolean',
default: true
}
}
};
properties.xaxis = {
title: 'X axis settings',
type: 'object',
properties: {
showLabels: {
title: 'Show labels',
type: 'boolean',
default: true
},
title: {
title: 'Axis title',
type: 'string',
default: null
},
color: {
title: 'Ticks color',
type: 'string',
default: null
}
}
};
properties.yaxis = {
title: 'Y axis settings',
type: 'object',
properties: {
min: {
title: 'Minimum value on the scale',
type: 'number',
default: null
},
max: {
title: 'Maximum value on the scale',
type: 'number',
default: null
},
showLabels: {
title: 'Show labels',
type: 'boolean',
default: true
},
title: {
title: 'Axis title',
type: 'string',
default: null
},
color: {
title: 'Ticks color',
type: 'string',
default: null
},
ticksFormatter: {
title: 'Ticks formatter function, f(value)',
type: 'string',
default: ''
},
tickDecimals: {
title: 'The number of decimals to display',
type: 'number',
default: 0
},
tickSize: {
title: 'Step size between ticks',
type: 'number',
default: null
}
}
};
schema.schema.required = [];
schema.form = ['stack'];
if (chartType === 'graph') {
schema.form.push('smoothLines');
}
if (chartType === 'bar') {
schema.form.push('defaultBarWidth');
2020-02-26 18:15:04 +02:00
schema.form.push({
key: 'barAlignment',
type: 'rc-select',
multiple: false,
items: [
{
value: 'left',
label: 'Left'
},
{
value: 'right',
label: 'Right'
},
{
value: 'center',
label: 'Center'
}
]
});
}
if (chartType === 'graph' || chartType === 'bar') {
schema.form.push('thresholdsLineWidth');
}
schema.form.push('shadowSize');
schema.form.push({
key: 'fontColor',
type: 'color'
});
schema.form.push('fontSize');
schema.form.push('tooltipIndividual');
schema.form.push('tooltipCumulative');
schema.form.push({
key: 'tooltipValueFormatter',
type: 'javascript'
});
2020-02-24 17:16:02 +02:00
schema.form.push('hideZeros');
schema.form.push('showTooltip');
schema.form.push({
key: 'grid',
items: [
{
key: 'grid.color',
type: 'color'
},
{
key: 'grid.backgroundColor',
type: 'color'
},
{
key: 'grid.tickColor',
type: 'color'
},
'grid.outlineWidth',
'grid.verticalLines',
'grid.horizontalLines'
]
});
schema.form.push({
key: 'xaxis',
items: [
'xaxis.showLabels',
'xaxis.title',
{
key: 'xaxis.color',
type: 'color'
}
]
});
schema.form.push({
key: 'yaxis',
items: [
'yaxis.min',
'yaxis.max',
'yaxis.tickDecimals',
'yaxis.tickSize',
'yaxis.showLabels',
'yaxis.title',
{
key: 'yaxis.color',
type: 'color'
},
{
key: 'yaxis.ticksFormatter',
type: 'javascript'
}
]
});
2020-02-24 17:16:02 +02:00
if (chartType === 'graph' || chartType === 'bar') {
schema.groupInfoes = [{
formIndex: 0,
GroupTitle: 'Common Settings'
}];
schema.form = [schema.form];
schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties, ...chartSettingsSchemaForCustomLegend.schema.properties};
schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required, chartSettingsSchemaForCustomLegend.schema.required);
schema.form.push(chartSettingsSchemaForComparison.form, chartSettingsSchemaForCustomLegend.form);
2020-02-24 17:16:02 +02:00
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Comparison Settings'
});
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle:'Custom Legend Settings'
});
2020-02-24 17:16:02 +02:00
}
return schema;
}
2020-02-24 17:16:02 +02:00
const chartSettingsSchemaForComparison: JsonSettingsSchema = {
schema: {
title: 'Comparison Settings',
type: 'object',
properties: {
comparisonEnabled: {
title: 'Enable comparison',
type: 'boolean',
default: false
},
timeForComparison: {
title: 'Time to show historical data',
type: 'string',
2021-03-18 19:45:45 +02:00
default: 'previousInterval'
2020-02-24 17:16:02 +02:00
},
xaxisSecond: {
title: 'Second X axis',
type: 'object',
properties: {
axisPosition: {
title: 'Axis position',
type: 'string',
default: 'top'
},
showLabels: {
title: 'Show labels',
type: 'boolean',
default: true
},
title: {
title: 'Axis title',
type: 'string',
default: null
}
}
}
},
required: []
},
form: [
'comparisonEnabled',
{
key: 'timeForComparison',
type: 'rc-select',
multiple: false,
items: [
2021-03-18 19:45:45 +02:00
{
value: 'previousInterval',
label: 'Previous interval (default)'
},
2020-02-24 17:16:02 +02:00
{
value: 'days',
label: 'Day ago'
},
{
value: 'weeks',
label: 'Week ago'
},
{
value: 'months',
2021-03-18 19:45:45 +02:00
label: 'Month ago'
2020-02-24 17:16:02 +02:00
},
{
value: 'years',
label: 'Year ago'
}
]
},
{
key: 'xaxisSecond',
items: [
{
key: 'xaxisSecond.axisPosition',
type: 'rc-select',
multiple: false,
items: [
{
value: 'top',
label: 'Top (default)'
},
{
value: 'bottom',
label: 'Bottom'
}
]
},
'xaxisSecond.showLabels',
'xaxisSecond.title',
]
}
]
};
const chartSettingsSchemaForCustomLegend: JsonSettingsSchema = {
schema: {
title: 'Custom Legend Settings',
type: 'object',
properties: {
customLegendEnabled: {
title: 'Enable custom legend (this will allow you to use attribute/timeseries values in key labels)',
type: 'boolean',
default: false
},
dataKeysListForLabels: {
title: 'Datakeys list to use in labels',
type: 'array',
items: {
type: 'object',
properties: {
name: {
title: 'Key name',
type: 'string'
},
type: {
title: 'Key type',
type: 'string',
default: 'attribute'
}
},
required: [
'name'
]
}
}
},
required: []
},
form: [
'customLegendEnabled',
{
key: 'dataKeysListForLabels',
condition: 'model.customLegendEnabled === true',
items: [
{
key: 'dataKeysListForLabels[].type',
type: 'rc-select',
multiple: false,
items: [
{
value: 'attribute',
label: 'Attribute'
},
{
value: 'timeseries',
label: 'Timeseries'
}
]
},
'dataKeysListForLabels[].name'
]
}
]
};
export const flotPieSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
radius: {
title: 'Radius',
type: 'number',
default: 1
},
innerRadius: {
title: 'Inner radius',
type: 'number',
default: 0
},
tilt: {
title: 'Tilt',
type: 'number',
default: 1
},
animatedPie: {
title: 'Enable pie animation (experimental)',
type: 'boolean',
default: false
},
stroke: {
title: 'Stroke',
type: 'object',
properties: {
color: {
title: 'Color',
type: 'string',
default: ''
},
width: {
title: 'Width (pixels)',
type: 'number',
default: 0
}
}
},
showTooltip: {
title: 'Show Tooltip',
type: 'boolean',
default: true,
},
showLabels: {
title: 'Show labels',
type: 'boolean',
default: false
},
fontColor: {
title: 'Font color',
type: 'string',
default: '#545454'
},
fontSize: {
title: 'Font size',
type: 'number',
default: 10
}
},
required: []
},
form: [
'radius',
'innerRadius',
'animatedPie',
'tilt',
{
key: 'stroke',
items: [
{
key: 'stroke.color',
type: 'color'
},
'stroke.width'
]
},
'showTooltip',
'showLabels',
{
key: 'fontColor',
type: 'color'
},
'fontSize'
]
2019-12-23 14:36:44 +02:00
};
2020-02-25 12:30:38 +02:00
export const flotPieDatakeySettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'DataKeySettings',
properties: {
hideDataByDefault: {
title: 'Data is hidden by default',
type: 'boolean',
default: false
},
disableDataHiding: {
title: 'Disable data hiding',
type: 'boolean',
default: false
},
removeFromLegend: {
title: 'Remove datakey from legend',
type: 'boolean',
default: false
}
},
required: []
},
form: [
'hideDataByDefault',
'disableDataHiding',
'removeFromLegend'
]
};
2020-02-24 17:16:02 +02:00
export function flotDatakeySettingsSchema(defaultShowLines: boolean, chartType: ChartType): JsonSettingsSchema {
const schema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'DataKeySettings',
properties: {
2020-02-24 17:16:02 +02:00
excludeFromStacking: {
title: 'Exclude from stacking(available in "Stacking" mode)',
type: 'boolean',
default: false
},
2020-02-25 12:30:38 +02:00
hideDataByDefault: {
title: 'Data is hidden by default',
type: 'boolean',
default: false
},
disableDataHiding: {
title: 'Disable data hiding',
type: 'boolean',
default: false
},
removeFromLegend: {
title: 'Remove datakey from legend',
type: 'boolean',
default: false
},
showLines: {
title: 'Show lines',
type: 'boolean',
default: defaultShowLines
},
fillLines: {
title: 'Fill lines',
type: 'boolean',
default: false
},
showPoints: {
title: 'Show points',
type: 'boolean',
default: false
},
2020-02-24 17:16:02 +02:00
showPointShape: {
title: 'Select point shape:',
type: 'string',
default: 'circle'
},
pointShapeFormatter: {
title: 'Point shape format function, f(ctx, x, y, radius, shadow)',
type: 'string',
default: 'var size = radius * Math.sqrt(Math.PI) / 2;\n' +
'ctx.moveTo(x - size, y - size);\n' +
'ctx.lineTo(x + size, y + size);\n' +
'ctx.moveTo(x - size, y + size);\n' +
'ctx.lineTo(x + size, y - size);'
},
showPointsLineWidth: {
title: 'Line width of points',
type: 'number',
2020-02-24 17:16:02 +02:00
default: 5
},
showPointsRadius: {
title: 'Radius of points',
type: 'number',
default: 3
},
tooltipValueFormatter: {
title: 'Tooltip value format function, f(value)',
type: 'string',
default: ''
},
showSeparateAxis: {
title: 'Show separate axis',
type: 'boolean',
default: false
},
axisMin: {
title: 'Minimum value on the axis scale',
type: 'number',
default: null
},
axisMax: {
title: 'Maximum value on the axis scale',
type: 'number',
default: null
},
axisTitle: {
title: 'Axis title',
type: 'string',
default: ''
},
axisTickDecimals: {
title: 'Axis tick number of digits after floating point',
type: 'number',
default: null
},
axisTickSize: {
title: 'Axis step size between ticks',
type: 'number',
default: null
},
axisPosition: {
title: 'Axis position',
type: 'string',
default: 'left'
},
axisTicksFormatter: {
title: 'Ticks formatter function, f(value)',
type: 'string',
default: ''
}
},
required: ['showLines', 'fillLines', 'showPoints']
},
form: [
2020-02-25 12:30:38 +02:00
'hideDataByDefault',
'disableDataHiding',
'removeFromLegend',
2020-02-24 17:16:02 +02:00
'excludeFromStacking',
'showLines',
'fillLines',
'showPoints',
2020-02-24 17:16:02 +02:00
{
key: 'showPointShape',
type: 'rc-select',
multiple: false,
items: [
{
value: 'circle',
label: 'Circle'
},
{
value: 'cross',
label: 'Cross'
},
{
value: 'diamond',
label: 'Diamond'
},
{
value: 'square',
label: 'Square'
},
{
value: 'triangle',
label: 'Triangle'
},
{
value: 'custom',
label: 'Custom function'
}
]
},
{
key: 'pointShapeFormatter',
type: 'javascript'
},
'showPointsLineWidth',
'showPointsRadius',
{
key: 'tooltipValueFormatter',
type: 'javascript'
},
'showSeparateAxis',
'axisMin',
'axisMax',
'axisTitle',
'axisTickDecimals',
'axisTickSize',
{
key: 'axisPosition',
type: 'rc-select',
multiple: false,
items: [
{
value: 'left',
label: 'Left'
},
{
value: 'right',
label: 'Right'
}
]
},
{
key: 'axisTicksFormatter',
type: 'javascript'
}
]
};
2020-02-24 17:16:02 +02:00
const properties = schema.schema.properties;
if (chartType === 'graph' || chartType === 'bar') {
2020-02-26 18:15:04 +02:00
properties.thresholds = {
title: 'Thresholds',
type: 'array',
items: {
title: 'Threshold',
type: 'object',
properties: {
thresholdValueSource: {
title: 'Threshold value source',
type: 'string',
default: 'predefinedValue'
},
thresholdEntityAlias: {
title: 'Thresholds source entity alias',
type: 'string'
},
thresholdAttribute: {
title: 'Threshold source entity attribute',
type: 'string'
},
thresholdValue: {
title: 'Threshold value (if predefined value is selected)',
type: 'number'
},
lineWidth: {
title: 'Line width',
type: 'number'
},
color: {
title: 'Color',
type: 'string'
}
}
},
required: []
};
schema.form.push({
key: 'thresholds',
items: [
{
key: 'thresholds[].thresholdValueSource',
type: 'rc-select',
multiple: false,
items: [
{
value: 'predefinedValue',
label: 'Predefined value (Default)'
},
{
value: 'entityAttribute',
label: 'Value taken from entity attribute'
}
]
},
'thresholds[].thresholdValue',
'thresholds[].thresholdEntityAlias',
'thresholds[].thresholdAttribute',
{
key: 'thresholds[].color',
type: 'color'
},
'thresholds[].lineWidth'
]
});
2020-02-24 17:16:02 +02:00
properties.comparisonSettings = {
title: 'Comparison Settings',
type: 'object',
properties: {
showValuesForComparison: {
title: 'Show historical values for comparison',
type: 'boolean',
default: true
},
comparisonValuesLabel: {
title: 'Historical values label',
type: 'string',
default: ''
},
color: {
title: 'Color',
type: 'string',
default: ''
}
},
required: ['showValuesForComparison']
};
schema.form.push({
key: 'comparisonSettings',
items: [
'comparisonSettings.showValuesForComparison',
'comparisonSettings.comparisonValuesLabel',
{
key: 'comparisonSettings.color',
type: 'color'
}
]
});
}
return schema;
}