UI: Range chart widget config improvements.
This commit is contained in:
parent
2fb604e398
commit
ce3be06796
@ -30,116 +30,25 @@ import {
|
|||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
import {
|
import {
|
||||||
backgroundStyle,
|
backgroundStyle,
|
||||||
ColorRange,
|
|
||||||
ComponentStyle,
|
ComponentStyle,
|
||||||
filterIncludingColorRanges,
|
|
||||||
getDataKey,
|
getDataKey,
|
||||||
overlayStyle,
|
overlayStyle,
|
||||||
sortedColorRange,
|
|
||||||
textStyle
|
textStyle
|
||||||
} from '@shared/models/widget-settings.models';
|
} from '@shared/models/widget-settings.models';
|
||||||
import { isDefinedAndNotNull, isNumber } from '@core/utils';
|
import { isDefinedAndNotNull } from '@core/utils';
|
||||||
import { rangeChartDefaultSettings, RangeChartWidgetSettings } from './range-chart-widget.models';
|
import {
|
||||||
|
rangeChartDefaultSettings,
|
||||||
|
rangeChartTimeSeriesKeySettings,
|
||||||
|
rangeChartTimeSeriesSettings,
|
||||||
|
RangeChartWidgetSettings,
|
||||||
|
RangeItem,
|
||||||
|
toRangeItems
|
||||||
|
} from './range-chart-widget.models';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ImagePipe } from '@shared/pipe/image.pipe';
|
import { ImagePipe } from '@shared/pipe/image.pipe';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { DeepPartial } from '@shared/models/common';
|
|
||||||
import {
|
|
||||||
createTimeSeriesChartVisualMapPiece,
|
|
||||||
SeriesFillType,
|
|
||||||
TimeSeriesChartKeySettings,
|
|
||||||
TimeSeriesChartSettings,
|
|
||||||
TimeSeriesChartShape,
|
|
||||||
TimeSeriesChartThreshold,
|
|
||||||
TimeSeriesChartThresholdType, TimeSeriesChartVisualMapPiece
|
|
||||||
} from '@home/components/widget/lib/chart/time-series-chart.models';
|
|
||||||
import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart';
|
import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart';
|
||||||
|
|
||||||
interface RangeItem {
|
|
||||||
index: number;
|
|
||||||
from?: number;
|
|
||||||
to?: number;
|
|
||||||
color: string;
|
|
||||||
label: string;
|
|
||||||
visible: boolean;
|
|
||||||
enabled: boolean;
|
|
||||||
piece: TimeSeriesChartVisualMapPiece;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rangeItemLabel = (from?: number, to?: number): string => {
|
|
||||||
if (isNumber(from) && isNumber(to)) {
|
|
||||||
if (from === to) {
|
|
||||||
return `${from}`;
|
|
||||||
} else {
|
|
||||||
return `${from} - ${to}`;
|
|
||||||
}
|
|
||||||
} else if (isNumber(from)) {
|
|
||||||
return `≥ ${from}`;
|
|
||||||
} else if (isNumber(to)) {
|
|
||||||
return `< ${to}`;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const toRangeItems = (colorRanges: Array<ColorRange>): RangeItem[] => {
|
|
||||||
const rangeItems: RangeItem[] = [];
|
|
||||||
let counter = 0;
|
|
||||||
const ranges = sortedColorRange(filterIncludingColorRanges(colorRanges)).filter(r => isNumber(r.from) || isNumber(r.to));
|
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
|
||||||
const range = ranges[i];
|
|
||||||
let from = range.from;
|
|
||||||
const to = range.to;
|
|
||||||
if (i > 0) {
|
|
||||||
const prevRange = ranges[i - 1];
|
|
||||||
if (isNumber(prevRange.to) && isNumber(from) && from < prevRange.to) {
|
|
||||||
from = prevRange.to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rangeItems.push(
|
|
||||||
{
|
|
||||||
index: counter++,
|
|
||||||
color: range.color,
|
|
||||||
enabled: true,
|
|
||||||
visible: true,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
label: rangeItemLabel(from, to),
|
|
||||||
piece: createTimeSeriesChartVisualMapPiece(range.color, from, to)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!isNumber(from) || !isNumber(to)) {
|
|
||||||
const value = !isNumber(from) ? to : from;
|
|
||||||
rangeItems.push(
|
|
||||||
{
|
|
||||||
index: counter++,
|
|
||||||
color: 'transparent',
|
|
||||||
enabled: true,
|
|
||||||
visible: false,
|
|
||||||
label: '',
|
|
||||||
piece: { gt: value - 0.000000001, lt: value + 0.000000001, color: 'transparent'}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rangeItems;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getMarkPoints = (ranges: Array<RangeItem>): number[] => {
|
|
||||||
const points = new Set<number>();
|
|
||||||
for (const range of ranges) {
|
|
||||||
if (range.visible) {
|
|
||||||
if (isNumber(range.from)) {
|
|
||||||
points.add(range.from);
|
|
||||||
}
|
|
||||||
if (isNumber(range.to)) {
|
|
||||||
points.add(range.to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Array.from(points).sort();
|
|
||||||
};
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-range-chart-widget',
|
selector: 'tb-range-chart-widget',
|
||||||
templateUrl: './range-chart-widget.component.html',
|
templateUrl: './range-chart-widget.component.html',
|
||||||
@ -196,17 +105,7 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
this.units = dataKey.units;
|
this.units = dataKey.units;
|
||||||
}
|
}
|
||||||
if (dataKey) {
|
if (dataKey) {
|
||||||
dataKey.settings = {
|
dataKey.settings = rangeChartTimeSeriesKeySettings(this.settings);
|
||||||
type: 'line',
|
|
||||||
lineSettings: {
|
|
||||||
showLine: true,
|
|
||||||
smooth: false,
|
|
||||||
showPoints: false,
|
|
||||||
fillAreaSettings: {
|
|
||||||
type: this.settings.fillArea ? 'default' : SeriesFillType.none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} as DeepPartial<TimeSeriesChartKeySettings>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
|
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
|
||||||
@ -226,64 +125,7 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
const thresholds: DeepPartial<TimeSeriesChartThreshold>[] = getMarkPoints(this.rangeItems).map(item => ({
|
const settings = rangeChartTimeSeriesSettings(this.settings, this.rangeItems, this.decimals, this.units);
|
||||||
type: TimeSeriesChartThresholdType.constant,
|
|
||||||
yAxisId: 'default',
|
|
||||||
units: this.units,
|
|
||||||
decimals: this.decimals,
|
|
||||||
lineWidth: 1,
|
|
||||||
lineColor: '#37383b',
|
|
||||||
lineType: [3, 3],
|
|
||||||
startSymbol: TimeSeriesChartShape.circle,
|
|
||||||
startSymbolSize: 5,
|
|
||||||
endSymbol: TimeSeriesChartShape.arrow,
|
|
||||||
endSymbolSize: 7,
|
|
||||||
showLabel: true,
|
|
||||||
labelPosition: 'insideEndTop',
|
|
||||||
labelColor: '#37383b',
|
|
||||||
additionalLabelOption: {
|
|
||||||
backgroundColor: 'rgba(255,255,255,0.56)',
|
|
||||||
padding: [4, 5],
|
|
||||||
borderRadius: 4,
|
|
||||||
},
|
|
||||||
value: item
|
|
||||||
} as DeepPartial<TimeSeriesChartThreshold>));
|
|
||||||
const settings: DeepPartial<TimeSeriesChartSettings> = {
|
|
||||||
dataZoom: this.settings.dataZoom,
|
|
||||||
thresholds,
|
|
||||||
yAxes: {
|
|
||||||
default: {
|
|
||||||
show: true,
|
|
||||||
showLine: false,
|
|
||||||
showTicks: false,
|
|
||||||
showTickLabels: true,
|
|
||||||
showSplitLines: true,
|
|
||||||
decimals: this.decimals,
|
|
||||||
units: this.units
|
|
||||||
}
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
show: true,
|
|
||||||
showLine: true,
|
|
||||||
showTicks: true,
|
|
||||||
showTickLabels: true,
|
|
||||||
showSplitLines: false
|
|
||||||
},
|
|
||||||
visualMapSettings: {
|
|
||||||
outOfRangeColor: this.settings.outOfRangeColor,
|
|
||||||
pieces: this.rangeItems.map(item => item.piece)
|
|
||||||
},
|
|
||||||
showTooltip: this.settings.showTooltip,
|
|
||||||
tooltipValueFont: this.settings.tooltipValueFont,
|
|
||||||
tooltipValueColor: this.settings.tooltipValueColor,
|
|
||||||
tooltipShowDate: this.settings.tooltipShowDate,
|
|
||||||
tooltipDateInterval: this.settings.tooltipDateInterval,
|
|
||||||
tooltipDateFormat: this.settings.tooltipDateFormat,
|
|
||||||
tooltipDateFont: this.settings.tooltipDateFont,
|
|
||||||
tooltipDateColor: this.settings.tooltipDateColor,
|
|
||||||
tooltipBackgroundColor: this.settings.tooltipBackgroundColor,
|
|
||||||
tooltipBackgroundBlur: this.settings.tooltipBackgroundBlur,
|
|
||||||
};
|
|
||||||
this.timeSeriesChart = new TbTimeSeriesChart(this.ctx, settings, this.chartShape.nativeElement, this.renderer);
|
this.timeSeriesChart = new TbTimeSeriesChart(this.ctx, settings, this.chartShape.nativeElement, this.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,37 @@ import {
|
|||||||
BackgroundSettings,
|
BackgroundSettings,
|
||||||
BackgroundType,
|
BackgroundType,
|
||||||
ColorRange,
|
ColorRange,
|
||||||
|
filterIncludingColorRanges,
|
||||||
Font,
|
Font,
|
||||||
simpleDateFormat
|
simpleDateFormat,
|
||||||
|
sortedColorRange
|
||||||
} from '@shared/models/widget-settings.models';
|
} from '@shared/models/widget-settings.models';
|
||||||
import { LegendPosition } from '@shared/models/widget.models';
|
import { LegendPosition } from '@shared/models/widget.models';
|
||||||
import { EChartsTooltipWidgetSettings } from '@home/components/widget/lib/chart/echarts-widget.models';
|
import { EChartsTooltipWidgetSettings } from '@home/components/widget/lib/chart/echarts-widget.models';
|
||||||
|
import {
|
||||||
|
createTimeSeriesChartVisualMapPiece,
|
||||||
|
SeriesFillType,
|
||||||
|
TimeSeriesChartKeySettings,
|
||||||
|
TimeSeriesChartSeriesType,
|
||||||
|
TimeSeriesChartSettings,
|
||||||
|
TimeSeriesChartShape,
|
||||||
|
TimeSeriesChartThreshold,
|
||||||
|
TimeSeriesChartThresholdType,
|
||||||
|
TimeSeriesChartVisualMapPiece
|
||||||
|
} from '@home/components/widget/lib/chart/time-series-chart.models';
|
||||||
|
import { isNumber } from '@core/utils';
|
||||||
|
import { DeepPartial } from '@shared/models/common';
|
||||||
|
|
||||||
|
export interface RangeItem {
|
||||||
|
index: number;
|
||||||
|
from?: number;
|
||||||
|
to?: number;
|
||||||
|
color: string;
|
||||||
|
label: string;
|
||||||
|
visible: boolean;
|
||||||
|
enabled: boolean;
|
||||||
|
piece: TimeSeriesChartVisualMapPiece;
|
||||||
|
}
|
||||||
|
|
||||||
export interface RangeChartWidgetSettings extends EChartsTooltipWidgetSettings {
|
export interface RangeChartWidgetSettings extends EChartsTooltipWidgetSettings {
|
||||||
dataZoom: boolean;
|
dataZoom: boolean;
|
||||||
@ -94,3 +120,152 @@ export const rangeChartDefaultSettings: RangeChartWidgetSettings = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const rangeChartTimeSeriesSettings = (settings: RangeChartWidgetSettings, rangeItems: RangeItem[],
|
||||||
|
decimals: number, units: string): DeepPartial<TimeSeriesChartSettings> => {
|
||||||
|
const thresholds: DeepPartial<TimeSeriesChartThreshold>[] = getMarkPoints(rangeItems).map(item => ({
|
||||||
|
type: TimeSeriesChartThresholdType.constant,
|
||||||
|
yAxisId: 'default',
|
||||||
|
units,
|
||||||
|
decimals,
|
||||||
|
lineWidth: 1,
|
||||||
|
lineColor: '#37383b',
|
||||||
|
lineType: [3, 3],
|
||||||
|
startSymbol: TimeSeriesChartShape.circle,
|
||||||
|
startSymbolSize: 5,
|
||||||
|
endSymbol: TimeSeriesChartShape.arrow,
|
||||||
|
endSymbolSize: 7,
|
||||||
|
showLabel: true,
|
||||||
|
labelPosition: 'insideEndTop',
|
||||||
|
labelColor: '#37383b',
|
||||||
|
additionalLabelOption: {
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.56)',
|
||||||
|
padding: [4, 5],
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
value: item
|
||||||
|
} as DeepPartial<TimeSeriesChartThreshold>));
|
||||||
|
return {
|
||||||
|
dataZoom: settings.dataZoom,
|
||||||
|
thresholds,
|
||||||
|
yAxes: {
|
||||||
|
default: {
|
||||||
|
show: true,
|
||||||
|
showLine: false,
|
||||||
|
showTicks: false,
|
||||||
|
showTickLabels: true,
|
||||||
|
showSplitLines: true,
|
||||||
|
decimals,
|
||||||
|
units
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
show: true,
|
||||||
|
showLine: true,
|
||||||
|
showTicks: true,
|
||||||
|
showTickLabels: true,
|
||||||
|
showSplitLines: false
|
||||||
|
},
|
||||||
|
visualMapSettings: {
|
||||||
|
outOfRangeColor: settings.outOfRangeColor,
|
||||||
|
pieces: rangeItems.map(item => item.piece)
|
||||||
|
},
|
||||||
|
showTooltip: settings.showTooltip,
|
||||||
|
tooltipValueFont: settings.tooltipValueFont,
|
||||||
|
tooltipValueColor: settings.tooltipValueColor,
|
||||||
|
tooltipShowDate: settings.tooltipShowDate,
|
||||||
|
tooltipDateInterval: settings.tooltipDateInterval,
|
||||||
|
tooltipDateFormat: settings.tooltipDateFormat,
|
||||||
|
tooltipDateFont: settings.tooltipDateFont,
|
||||||
|
tooltipDateColor: settings.tooltipDateColor,
|
||||||
|
tooltipBackgroundColor: settings.tooltipBackgroundColor,
|
||||||
|
tooltipBackgroundBlur: settings.tooltipBackgroundBlur,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rangeChartTimeSeriesKeySettings = (settings: RangeChartWidgetSettings): DeepPartial<TimeSeriesChartKeySettings> => ({
|
||||||
|
type: TimeSeriesChartSeriesType.line,
|
||||||
|
lineSettings: {
|
||||||
|
showLine: true,
|
||||||
|
smooth: false,
|
||||||
|
showPoints: false,
|
||||||
|
fillAreaSettings: {
|
||||||
|
type: settings.fillArea ? SeriesFillType.opacity : SeriesFillType.none,
|
||||||
|
opacity: 0.7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const toRangeItems = (colorRanges: Array<ColorRange>): RangeItem[] => {
|
||||||
|
const rangeItems: RangeItem[] = [];
|
||||||
|
let counter = 0;
|
||||||
|
const ranges = sortedColorRange(filterIncludingColorRanges(colorRanges)).filter(r => isNumber(r.from) || isNumber(r.to));
|
||||||
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
|
const range = ranges[i];
|
||||||
|
let from = range.from;
|
||||||
|
const to = range.to;
|
||||||
|
if (i > 0) {
|
||||||
|
const prevRange = ranges[i - 1];
|
||||||
|
if (isNumber(prevRange.to) && isNumber(from) && from < prevRange.to) {
|
||||||
|
from = prevRange.to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rangeItems.push(
|
||||||
|
{
|
||||||
|
index: counter++,
|
||||||
|
color: range.color,
|
||||||
|
enabled: true,
|
||||||
|
visible: true,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
label: rangeItemLabel(from, to),
|
||||||
|
piece: createTimeSeriesChartVisualMapPiece(range.color, from, to)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (!isNumber(from) || !isNumber(to)) {
|
||||||
|
const value = !isNumber(from) ? to : from;
|
||||||
|
rangeItems.push(
|
||||||
|
{
|
||||||
|
index: counter++,
|
||||||
|
color: 'transparent',
|
||||||
|
enabled: true,
|
||||||
|
visible: false,
|
||||||
|
label: '',
|
||||||
|
piece: { gt: value - 0.000000001, lt: value + 0.000000001, color: 'transparent'}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rangeItems;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rangeItemLabel = (from?: number, to?: number): string => {
|
||||||
|
if (isNumber(from) && isNumber(to)) {
|
||||||
|
if (from === to) {
|
||||||
|
return `${from}`;
|
||||||
|
} else {
|
||||||
|
return `${from} - ${to}`;
|
||||||
|
}
|
||||||
|
} else if (isNumber(from)) {
|
||||||
|
return `≥ ${from}`;
|
||||||
|
} else if (isNumber(to)) {
|
||||||
|
return `< ${to}`;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMarkPoints = (ranges: Array<RangeItem>): number[] => {
|
||||||
|
const points = new Set<number>();
|
||||||
|
for (const range of ranges) {
|
||||||
|
if (range.visible) {
|
||||||
|
if (isNumber(range.from)) {
|
||||||
|
points.add(range.from);
|
||||||
|
}
|
||||||
|
if (isNumber(range.to)) {
|
||||||
|
points.add(range.to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(points).sort();
|
||||||
|
};
|
||||||
|
|||||||
@ -715,7 +715,7 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface SeriesFillSettings {
|
export interface SeriesFillSettings {
|
||||||
type: SeriesFillType | 'default';
|
type: SeriesFillType;
|
||||||
opacity: number;
|
opacity: number;
|
||||||
gradient: {
|
gradient: {
|
||||||
start: number;
|
start: number;
|
||||||
@ -1322,7 +1322,7 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem,
|
|||||||
borderWidth: barSettings.showBorder ? barSettings.borderWidth : 0,
|
borderWidth: barSettings.showBorder ? barSettings.borderWidth : 0,
|
||||||
borderRadius: barSettings.borderRadius
|
borderRadius: barSettings.borderRadius
|
||||||
};
|
};
|
||||||
if (barSettings.backgroundSettings.type === SeriesFillType.none || barSettings.backgroundSettings.type === 'default') {
|
if (barSettings.backgroundSettings.type === SeriesFillType.none) {
|
||||||
barVisualSettings.color = seriesColor;
|
barVisualSettings.color = seriesColor;
|
||||||
} else if (barSettings.backgroundSettings.type === SeriesFillType.opacity) {
|
} else if (barSettings.backgroundSettings.type === SeriesFillType.opacity) {
|
||||||
barVisualSettings.color = tinycolor(seriesColor).setAlpha(barSettings.backgroundSettings.opacity).toRgbString();
|
barVisualSettings.color = tinycolor(seriesColor).setAlpha(barSettings.backgroundSettings.opacity).toRgbString();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user