Browse Source

UI: Improve time series bar width strategy: calculate width as percentage of time window.

pull/10329/head
Igor Kulikov 3 years ago
parent
commit
d39be08974
  1. 31
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html
  2. 31
      ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts
  3. 16
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts
  4. 40
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts
  5. 3
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts
  6. 31
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html
  7. 38
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts
  8. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts
  9. 75
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html
  10. 147
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts
  11. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts
  12. 6
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  13. 6
      ui-ngx/src/form.scss

31
ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html

@ -114,33 +114,10 @@
axisType="xAxis"> axisType="xAxis">
</tb-time-series-chart-axis-settings> </tb-time-series-chart-axis-settings>
</div> </div>
<div *ngIf="chartType === TimeSeriesChartType.default || chartType === TimeSeriesChartType.bar" <tb-time-series-no-aggregation-bar-width-settings
class="tb-form-panel" formGroupName="noAggregationBarWidthSettings"> *ngIf="chartType === TimeSeriesChartType.default || chartType === TimeSeriesChartType.bar"
<div fxLayout="row" fxLayoutAlign="space-between center"> formControlName="noAggregationBarWidthSettings">
<div fxFlex translate>widgets.time-series-chart.no-aggregation-bar-width-strategy</div> </tb-time-series-no-aggregation-bar-width-settings>
<tb-toggle-select formControlName="strategy" selectMediaBreakpoint="xs">
<tb-toggle-option *ngFor="let strategy of timeSeriesChartNoAggregationBarWidthStrategies" [value]="strategy">
{{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }}
</tb-toggle-option>
</tb-toggle-select>
</div>
<div *ngIf="timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings.strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.group"
class="tb-form-row space-between column-xs">
<div translate>widgets.time-series-chart.bar-group-interval-width</div>
<mat-form-field class="medium-width number" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" formControlName="groupIntervalWidth" min="100" step="1" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>ms</span>
</mat-form-field>
</div>
<div *ngIf="timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings.strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.separate"
class="tb-form-row space-between column-xs">
<div translate>widgets.time-series-chart.separate-bar-width</div>
<mat-form-field class="medium-width number" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" formControlName="separateBarWidth" min="100" step="1" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>ms</span>
</mat-form-field>
</div>
</div>
<div class="tb-form-panel tb-slide-toggle"> <div class="tb-form-panel tb-slide-toggle">
<mat-expansion-panel class="tb-settings" [expanded]="timeSeriesChartWidgetConfigForm.get('showLegend').value" <mat-expansion-panel class="tb-settings" [expanded]="timeSeriesChartWidgetConfigForm.get('showLegend').value"
[disabled]="!timeSeriesChartWidgetConfigForm.get('showLegend').value"> [disabled]="!timeSeriesChartWidgetConfigForm.get('showLegend').value">

31
ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts

@ -45,12 +45,7 @@ import {
TimeSeriesChartWidgetSettings TimeSeriesChartWidgetSettings
} from '@home/components/widget/lib/chart/time-series-chart-widget.models'; } from '@home/components/widget/lib/chart/time-series-chart-widget.models';
import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models'; import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models';
import { import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models';
timeSeriesChartNoAggregationBarWidthStrategies,
TimeSeriesChartNoAggregationBarWidthStrategy,
timeSeriesChartNoAggregationBarWidthStrategyTranslations,
TimeSeriesChartType
} from '@home/components/widget/lib/chart/time-series-chart.models';
@Component({ @Component({
selector: 'tb-time-series-chart-basic-config', selector: 'tb-time-series-chart-basic-config',
@ -76,12 +71,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon
legendPositionTranslationMap = legendPositionTranslationMap; legendPositionTranslationMap = legendPositionTranslationMap;
TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy;
timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies;
timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations;
timeSeriesChartWidgetConfigForm: UntypedFormGroup; timeSeriesChartWidgetConfigForm: UntypedFormGroup;
tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this);
@ -140,11 +129,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon
yAxis: [settings.yAxis, []], yAxis: [settings.yAxis, []],
xAxis: [settings.xAxis, []], xAxis: [settings.xAxis, []],
noAggregationBarWidthSettings: this.fb.group({ noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []],
strategy: [settings.noAggregationBarWidthSettings.strategy, []],
groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]],
separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]],
}),
showLegend: [settings.showLegend, []], showLegend: [settings.showLegend, []],
legendLabelFont: [settings.legendLabelFont, []], legendLabelFont: [settings.legendLabelFont, []],
@ -227,7 +212,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon
} }
protected validatorTriggers(): string[] { protected validatorTriggers(): string[] {
return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate'];
} }
protected updateValidators(emitEvent: boolean, trigger?: string) { protected updateValidators(emitEvent: boolean, trigger?: string) {
@ -236,8 +221,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon
const showLegend: boolean = this.timeSeriesChartWidgetConfigForm.get('showLegend').value; const showLegend: boolean = this.timeSeriesChartWidgetConfigForm.get('showLegend').value;
const showTooltip: boolean = this.timeSeriesChartWidgetConfigForm.get('showTooltip').value; const showTooltip: boolean = this.timeSeriesChartWidgetConfigForm.get('showTooltip').value;
const tooltipShowDate: boolean = this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').value;
const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy =
this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('strategy').value;
if (showTitle) { if (showTitle) {
this.timeSeriesChartWidgetConfigForm.get('title').enable(); this.timeSeriesChartWidgetConfigForm.get('title').enable();
@ -266,14 +249,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon
this.timeSeriesChartWidgetConfigForm.get('iconColor').disable(); this.timeSeriesChartWidgetConfigForm.get('iconColor').disable();
} }
if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) {
this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable();
this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable();
} else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) {
this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable();
this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable();
}
if (showLegend) { if (showLegend) {
this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').enable(); this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').enable();
this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').enable(); this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').enable();

16
ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts

@ -19,7 +19,6 @@ import { Interval, IntervalMath } from '@shared/models/time/time.models';
import { LabelFormatterCallback, SeriesLabelOption } from 'echarts/types/src/util/types'; import { LabelFormatterCallback, SeriesLabelOption } from 'echarts/types/src/util/types';
import { import {
TimeSeriesChartDataItem, TimeSeriesChartDataItem,
TimeSeriesChartNoAggregationBarWidthSettings,
TimeSeriesChartNoAggregationBarWidthStrategy TimeSeriesChartNoAggregationBarWidthStrategy
} from '@home/components/widget/lib/chart/time-series-chart.models'; } from '@home/components/widget/lib/chart/time-series-chart.models';
import { CustomSeriesRenderItemParams } from 'echarts'; import { CustomSeriesRenderItemParams } from 'echarts';
@ -38,7 +37,9 @@ export interface BarRenderContext {
barsCount?: number; barsCount?: number;
barIndex?: number; barIndex?: number;
noAggregation: boolean; noAggregation: boolean;
noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; noAggregationBarWidthStrategy: TimeSeriesChartNoAggregationBarWidthStrategy;
noAggregationWidthRelative?: boolean;
noAggregationWidth?: number;
timeInterval?: Interval; timeInterval?: Interval;
visualSettings?: BarVisualSettings; visualSettings?: BarVisualSettings;
labelOption?: SeriesLabelOption; labelOption?: SeriesLabelOption;
@ -54,16 +55,15 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C
let interval = end - start; let interval = end - start;
const ts = start ? start : time; const ts = start ? start : time;
const noAggregationGroup = renderCtx.noAggregation &&
renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group;
const separateBar = renderCtx.noAggregation && const separateBar = renderCtx.noAggregation &&
renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; renderCtx.noAggregationBarWidthStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate;
if (renderCtx.noAggregation) { if (renderCtx.noAggregation) {
if (noAggregationGroup) { if (renderCtx.noAggregationWidthRelative) {
interval = renderCtx.noAggregationBarWidthSettings.groupIntervalWidth; const scaleWidth = api.getWidth() / api.size([1,0])[0];
interval = scaleWidth * (renderCtx.noAggregationWidth / 100);
} else { } else {
interval = renderCtx.noAggregationBarWidthSettings.separateBarWidth; interval = renderCtx.noAggregationWidth;
} }
start = time - interval / 2; start = time - interval / 2;
end = time + interval / 2; end = time + interval / 2;

40
ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts

@ -391,10 +391,16 @@ export const timeSeriesChartNoAggregationBarWidthStrategyTranslations = new Map<
] ]
); );
export interface TimeSeriesChartBarWidth {
relative?: boolean;
relativeWidth?: number;
absoluteWidth?: number;
}
export interface TimeSeriesChartNoAggregationBarWidthSettings { export interface TimeSeriesChartNoAggregationBarWidthSettings {
strategy: TimeSeriesChartNoAggregationBarWidthStrategy; strategy: TimeSeriesChartNoAggregationBarWidthStrategy;
groupIntervalWidth?: number; groupWidth?: TimeSeriesChartBarWidth;
separateBarWidth?: number; barWidth?: TimeSeriesChartBarWidth;
} }
export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings {
@ -474,8 +480,16 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = {
}, },
noAggregationBarWidthSettings: { noAggregationBarWidthSettings: {
strategy: TimeSeriesChartNoAggregationBarWidthStrategy.group, strategy: TimeSeriesChartNoAggregationBarWidthStrategy.group,
groupIntervalWidth: 1000, groupWidth: {
separateBarWidth: 1000 relative: true,
relativeWidth: 2,
absoluteWidth: 1000
},
barWidth: {
relative: true,
relativeWidth: 2,
absoluteWidth: 1000
}
}, },
showTooltip: true, showTooltip: true,
tooltipTrigger: EChartsTooltipTrigger.axis, tooltipTrigger: EChartsTooltipTrigger.axis,
@ -757,12 +771,12 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting
export const generateChartData = (dataItems: TimeSeriesChartDataItem[], export const generateChartData = (dataItems: TimeSeriesChartDataItem[],
thresholdItems: TimeSeriesChartThresholdItem[], thresholdItems: TimeSeriesChartThresholdItem[],
timeInterval: Interval, timeInterval: Interval,
stack: boolean,
noAggregation: boolean, noAggregation: boolean,
noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings,
stack: boolean,
darkMode: boolean): Array<LineSeriesOption | CustomSeriesOption> => { darkMode: boolean): Array<LineSeriesOption | CustomSeriesOption> => {
let series = generateChartSeries(dataItems, timeInterval, let series = generateChartSeries(dataItems, timeInterval,
noAggregation, noAggregationBarWidthSettings, stack, darkMode); stack, noAggregation, noAggregationBarWidthSettings, darkMode);
if (thresholdItems.length) { if (thresholdItems.length) {
const thresholds = generateChartThresholds(thresholdItems, darkMode); const thresholds = generateChartThresholds(thresholdItems, darkMode);
series = series.concat(thresholds); series = series.concat(thresholds);
@ -874,9 +888,9 @@ const createThresholdData = (val: string | number, item: TimeSeriesChartThreshol
const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], const generateChartSeries = (dataItems: TimeSeriesChartDataItem[],
timeInterval: Interval, timeInterval: Interval,
stack: boolean,
noAggregation: boolean, noAggregation: boolean,
noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings,
stack: boolean,
darkMode: boolean): Array<LineSeriesOption | CustomSeriesOption> => { darkMode: boolean): Array<LineSeriesOption | CustomSeriesOption> => {
const series: Array<LineSeriesOption | CustomSeriesOption> = []; const series: Array<LineSeriesOption | CustomSeriesOption> = [];
const enabledDataItems = dataItems.filter(d => d.enabled); const enabledDataItems = dataItems.filter(d => d.enabled);
@ -895,7 +909,17 @@ const generateChartSeries = (dataItems: TimeSeriesChartDataItem[],
for (const item of enabledDataItems) { for (const item of enabledDataItems) {
if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) { if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) {
if (!item.barRenderContext) { if (!item.barRenderContext) {
item.barRenderContext = {noAggregation, noAggregationBarWidthSettings}; item.barRenderContext = {noAggregation,
noAggregationBarWidthStrategy: noAggregationBarWidthSettings.strategy};
const targetWidth = noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group ?
noAggregationBarWidthSettings.groupWidth : noAggregationBarWidthSettings.barWidth;
if (targetWidth.relative) {
item.barRenderContext.noAggregationWidthRelative = true;
item.barRenderContext.noAggregationWidth = targetWidth.relativeWidth;
} else {
item.barRenderContext.noAggregationWidthRelative = false;
item.barRenderContext.noAggregationWidth = targetWidth.absoluteWidth;
}
} }
item.barRenderContext.noAggregation = noAggregation; item.barRenderContext.noAggregation = noAggregation;
item.barRenderContext.barsCount = barsCount; item.barRenderContext.barsCount = barsCount;

3
ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts

@ -492,8 +492,9 @@ export class TbTimeSeriesChart {
private updateSeries(): Array<LineSeriesOption | CustomSeriesOption> { private updateSeries(): Array<LineSeriesOption | CustomSeriesOption> {
return generateChartData(this.dataItems, this.thresholdItems, return generateChartData(this.dataItems, this.thresholdItems,
this.ctx.timeWindow.interval, this.ctx.timeWindow.interval,
this.settings.stack,
this.noAggregation, this.noAggregation,
this.settings.noAggregationBarWidthSettings, this.settings.stack, this.darkMode); this.settings.noAggregationBarWidthSettings, this.darkMode);
} }
private updateAxes() { private updateAxes() {

31
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html

@ -48,33 +48,10 @@
axisType="xAxis"> axisType="xAxis">
</tb-time-series-chart-axis-settings> </tb-time-series-chart-axis-settings>
</div> </div>
<div *ngIf="chartType === TimeSeriesChartType.default || chartType === TimeSeriesChartType.bar" <tb-time-series-no-aggregation-bar-width-settings
class="tb-form-panel" formGroupName="noAggregationBarWidthSettings"> *ngIf="chartType === TimeSeriesChartType.default || chartType === TimeSeriesChartType.bar"
<div fxLayout="row" fxLayoutAlign="space-between center"> formControlName="noAggregationBarWidthSettings">
<div fxFlex translate>widgets.time-series-chart.no-aggregation-bar-width-strategy</div> </tb-time-series-no-aggregation-bar-width-settings>
<tb-toggle-select formControlName="strategy" selectMediaBreakpoint="xs">
<tb-toggle-option *ngFor="let strategy of timeSeriesChartNoAggregationBarWidthStrategies" [value]="strategy">
{{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }}
</tb-toggle-option>
</tb-toggle-select>
</div>
<div *ngIf="timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings.strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.group"
class="tb-form-row space-between column-xs">
<div translate>widgets.time-series-chart.bar-group-interval-width</div>
<mat-form-field class="medium-width number" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" formControlName="groupIntervalWidth" min="100" step="1" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>ms</span>
</mat-form-field>
</div>
<div *ngIf="timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings.strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.separate"
class="tb-form-row space-between column-xs">
<div translate>widgets.time-series-chart.separate-bar-width</div>
<mat-form-field class="medium-width number" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" formControlName="separateBarWidth" min="100" step="1" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>ms</span>
</mat-form-field>
</div>
</div>
<div class="tb-form-panel tb-slide-toggle"> <div class="tb-form-panel tb-slide-toggle">
<mat-expansion-panel class="tb-settings" [expanded]="timeSeriesChartWidgetSettingsForm.get('showLegend').value" <mat-expansion-panel class="tb-settings" [expanded]="timeSeriesChartWidgetSettingsForm.get('showLegend').value"
[disabled]="!timeSeriesChartWidgetSettingsForm.get('showLegend').value"> [disabled]="!timeSeriesChartWidgetSettingsForm.get('showLegend').value">

38
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts

@ -22,23 +22,17 @@ import {
WidgetSettings, WidgetSettings,
WidgetSettingsComponent WidgetSettingsComponent
} from '@shared/models/widget.models'; } from '@shared/models/widget.models';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { formatValue, isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { formatValue, isDefinedAndNotNull, mergeDeep } from '@core/utils';
import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models';
import {
barChartWithLabelsDefaultSettings
} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models';
import { EChartsTooltipTrigger } from '../../chart/echarts-widget.models'; import { EChartsTooltipTrigger } from '../../chart/echarts-widget.models';
import { import {
timeSeriesChartWidgetDefaultSettings, TimeSeriesChartWidgetSettings timeSeriesChartWidgetDefaultSettings,
TimeSeriesChartWidgetSettings
} from '@home/components/widget/lib/chart/time-series-chart-widget.models'; } from '@home/components/widget/lib/chart/time-series-chart-widget.models';
import { import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models';
timeSeriesChartNoAggregationBarWidthStrategies,
TimeSeriesChartNoAggregationBarWidthStrategy,
timeSeriesChartNoAggregationBarWidthStrategyTranslations, TimeSeriesChartType
} from '@home/components/widget/lib/chart/time-series-chart.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';
@Component({ @Component({
@ -65,12 +59,6 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon
legendPositionTranslationMap = legendPositionTranslationMap; legendPositionTranslationMap = legendPositionTranslationMap;
TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy;
timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies;
timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations;
timeSeriesChartWidgetSettingsForm: UntypedFormGroup; timeSeriesChartWidgetSettingsForm: UntypedFormGroup;
tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this);
@ -111,11 +99,7 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon
yAxis: [settings.yAxis, []], yAxis: [settings.yAxis, []],
xAxis: [settings.xAxis, []], xAxis: [settings.xAxis, []],
noAggregationBarWidthSettings: this.fb.group({ noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []],
strategy: [settings.noAggregationBarWidthSettings.strategy, []],
groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]],
separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]],
}),
showLegend: [settings.showLegend, []], showLegend: [settings.showLegend, []],
legendLabelFont: [settings.legendLabelFont, []], legendLabelFont: [settings.legendLabelFont, []],
@ -140,23 +124,13 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon
} }
protected validatorTriggers(): string[] { protected validatorTriggers(): string[] {
return ['showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; return ['showLegend', 'showTooltip', 'tooltipShowDate'];
} }
protected updateValidators(emitEvent: boolean) { protected updateValidators(emitEvent: boolean) {
const showLegend: boolean = this.timeSeriesChartWidgetSettingsForm.get('showLegend').value; const showLegend: boolean = this.timeSeriesChartWidgetSettingsForm.get('showLegend').value;
const showTooltip: boolean = this.timeSeriesChartWidgetSettingsForm.get('showTooltip').value; const showTooltip: boolean = this.timeSeriesChartWidgetSettingsForm.get('showTooltip').value;
const tooltipShowDate: boolean = this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').value;
const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy =
this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('strategy').value;
if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) {
this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable();
this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable();
} else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) {
this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable();
this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable();
}
if (showLegend) { if (showLegend) {
this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').enable(); this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').enable();

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts

@ -22,8 +22,6 @@ import {
TimeSeriesChartAxisSettings, TimeSeriesChartAxisSettings,
TimeSeriesChartYAxisSettings TimeSeriesChartYAxisSettings
} from '@home/components/widget/lib/chart/time-series-chart.models'; } from '@home/components/widget/lib/chart/time-series-chart.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { merge } from 'rxjs'; import { merge } from 'rxjs';
@Component({ @Component({
@ -60,8 +58,7 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu
public axisSettingsFormGroup: UntypedFormGroup; public axisSettingsFormGroup: UntypedFormGroup;
constructor(protected store: Store<AppState>, constructor(private fb: UntypedFormBuilder) {
private fb: UntypedFormBuilder) {
} }
ngOnInit(): void { ngOnInit(): void {

75
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html

@ -0,0 +1,75 @@
<!--
Copyright © 2016-2024 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.
-->
<div class="tb-form-panel" [formGroup]="barWidthSettingsFormGroup">
<div fxLayout="row" fxLayoutAlign="space-between center">
<div fxFlex translate>widgets.time-series-chart.no-aggregation-bar-width-strategy</div>
<tb-toggle-select formControlName="strategy" selectMediaBreakpoint="xs">
<tb-toggle-option *ngFor="let strategy of timeSeriesChartNoAggregationBarWidthStrategies" [value]="strategy">
{{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }}
</tb-toggle-option>
</tb-toggle-select>
</div>
<ng-container *ngIf="barWidthSettingsFormGroup.get('strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.group">
<ng-container
*ngTemplateOutlet="barWidth;
context: {
formGroup: barWidthSettingsFormGroup.get('groupWidth'),
label: 'widgets.time-series-chart.bar-group-width'
}">
</ng-container>
</ng-container>
<ng-container *ngIf="barWidthSettingsFormGroup.get('strategy').value === TimeSeriesChartNoAggregationBarWidthStrategy.separate">
<ng-container
*ngTemplateOutlet="barWidth;
context: {
formGroup: barWidthSettingsFormGroup.get('barWidth'),
label: 'widgets.time-series-chart.bar-width'
}">
</ng-container>
</ng-container>
</div>
<ng-template #barWidth let-label="label" let-formGroup="formGroup">
<div class="tb-form-row space-between column-lt-md" [formGroup]="formGroup">
<div translate>{{ label }}</div>
<div fxLayout="row" fxFlex.lt-md fxLayoutAlign="start center" fxLayoutGap="8px">
<mat-form-field class="medium-width" fxFlex.lt-md appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="relative">
<mat-select-trigger>
{{ (formGroup.get('relative').value ?
'widgets.time-series-chart.bar-width-relative' :
'widgets.time-series-chart.bar-width-absolute') | translate }}
</mat-select-trigger>
<mat-option [value]="true">
{{ 'widgets.time-series-chart.bar-width-relative' | translate }}
</mat-option>
<mat-option [value]="false">
{{ 'widgets.time-series-chart.bar-width-absolute' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="formGroup.get('relative').value" class="number fixed-width" appearance="outline" subscriptSizing="dynamic">
<input required matInput type="number" formControlName="relativeWidth" min="0.1" max="100" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>%</span>
</mat-form-field>
<mat-form-field *ngIf="!formGroup.get('relative').value" class="number fixed-width" appearance="outline" subscriptSizing="dynamic">
<input required matInput type="number" formControlName="absoluteWidth" min="100" step="1" placeholder="{{ 'widget-config.set' | translate }}"/>
<span matSuffix>ms</span>
</mat-form-field>
</div>
</div>
</ng-template>

147
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts

@ -0,0 +1,147 @@
///
/// Copyright © 2016-2024 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, forwardRef, Input, OnInit } from '@angular/core';
import {
ControlValueAccessor,
NG_VALUE_ACCESSOR,
UntypedFormBuilder,
UntypedFormGroup,
Validators
} from '@angular/forms';
import {
TimeSeriesChartNoAggregationBarWidthSettings,
timeSeriesChartNoAggregationBarWidthStrategies,
TimeSeriesChartNoAggregationBarWidthStrategy,
timeSeriesChartNoAggregationBarWidthStrategyTranslations
} from '@home/components/widget/lib/chart/time-series-chart.models';
import { merge } from 'rxjs';
@Component({
selector: 'tb-time-series-no-aggregation-bar-width-settings',
templateUrl: './time-series-no-aggregation-bar-width-settings.component.html',
styleUrls: ['./../../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TimeSeriesNoAggregationBarWidthSettingsComponent),
multi: true
}
]
})
export class TimeSeriesNoAggregationBarWidthSettingsComponent implements OnInit, ControlValueAccessor {
TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy;
timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies;
timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations;
@Input()
disabled: boolean;
private modelValue: TimeSeriesChartNoAggregationBarWidthSettings;
private propagateChange = null;
public barWidthSettingsFormGroup: UntypedFormGroup;
constructor(private fb: UntypedFormBuilder) {
}
ngOnInit(): void {
this.barWidthSettingsFormGroup = this.fb.group({
strategy: [null, []],
groupWidth: this.fb.group({
relative: [null, []],
relativeWidth: [null, [Validators.required, Validators.min(0.1), Validators.max(100)]],
absoluteWidth: [null, [Validators.required, Validators.min(100)]]
}),
barWidth: this.fb.group({
relative: [null, []],
relativeWidth: [null, [Validators.required, Validators.min(0.1), Validators.max(100)]],
absoluteWidth: [null, [Validators.required, Validators.min(100)]]
})
});
this.barWidthSettingsFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
merge(this.barWidthSettingsFormGroup.get('strategy').valueChanges,
this.barWidthSettingsFormGroup.get('groupWidth.relative').valueChanges,
this.barWidthSettingsFormGroup.get('barWidth.relative').valueChanges)
.subscribe(() => {
this.updateValidators();
});
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(_fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
this.barWidthSettingsFormGroup.disable({emitEvent: false});
} else {
this.barWidthSettingsFormGroup.enable({emitEvent: false});
this.updateValidators();
}
}
writeValue(value: TimeSeriesChartNoAggregationBarWidthSettings): void {
this.modelValue = value;
this.barWidthSettingsFormGroup.patchValue(
value, {emitEvent: false}
);
this.updateValidators();
}
private updateValidators() {
const strategy: TimeSeriesChartNoAggregationBarWidthStrategy =
this.barWidthSettingsFormGroup.get('strategy').value;
const groupWidthRelative: boolean = this.barWidthSettingsFormGroup.get('groupWidth.relative').value;
const barWidthRelative: boolean = this.barWidthSettingsFormGroup.get('barWidth.relative').value;
if (strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) {
this.barWidthSettingsFormGroup.get('groupWidth').enable({emitEvent: false});
this.barWidthSettingsFormGroup.get('barWidth').disable({emitEvent: false});
if (groupWidthRelative) {
this.barWidthSettingsFormGroup.get('groupWidth').get('relativeWidth').enable({emitEvent: false});
this.barWidthSettingsFormGroup.get('groupWidth').get('absoluteWidth').disable({emitEvent: false});
} else {
this.barWidthSettingsFormGroup.get('groupWidth').get('relativeWidth').disable({emitEvent: false});
this.barWidthSettingsFormGroup.get('groupWidth').get('absoluteWidth').enable({emitEvent: false});
}
} else if (strategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) {
this.barWidthSettingsFormGroup.get('groupWidth').disable({emitEvent: false});
this.barWidthSettingsFormGroup.get('barWidth').enable({emitEvent: false});
if (barWidthRelative) {
this.barWidthSettingsFormGroup.get('barWidth').get('relativeWidth').enable({emitEvent: false});
this.barWidthSettingsFormGroup.get('barWidth').get('absoluteWidth').disable({emitEvent: false});
} else {
this.barWidthSettingsFormGroup.get('barWidth').get('relativeWidth').disable({emitEvent: false});
this.barWidthSettingsFormGroup.get('barWidth').get('absoluteWidth').enable({emitEvent: false});
}
}
}
private updateModel() {
this.modelValue = this.barWidthSettingsFormGroup.getRawValue();
this.propagateChange(this.modelValue);
}
}

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts

@ -106,6 +106,9 @@ import { EntityAliasInputComponent } from '@home/components/widget/lib/settings/
import { import {
TimeSeriesChartThresholdSettingsPanelComponent TimeSeriesChartThresholdSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component'; } from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component';
import {
TimeSeriesNoAggregationBarWidthSettingsComponent
} from '@home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -146,6 +149,7 @@ import {
TimeSeriesChartThresholdsPanelComponent, TimeSeriesChartThresholdsPanelComponent,
TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdRowComponent,
TimeSeriesChartThresholdSettingsPanelComponent, TimeSeriesChartThresholdSettingsPanelComponent,
TimeSeriesNoAggregationBarWidthSettingsComponent,
DataKeyInputComponent, DataKeyInputComponent,
EntityAliasInputComponent EntityAliasInputComponent
], ],
@ -192,6 +196,7 @@ import {
TimeSeriesChartThresholdsPanelComponent, TimeSeriesChartThresholdsPanelComponent,
TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdRowComponent,
TimeSeriesChartThresholdSettingsPanelComponent, TimeSeriesChartThresholdSettingsPanelComponent,
TimeSeriesNoAggregationBarWidthSettingsComponent,
DataKeyInputComponent, DataKeyInputComponent,
EntityAliasInputComponent EntityAliasInputComponent
], ],

6
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -6629,8 +6629,10 @@
"no-aggregation-bar-width-strategy": "Bar width strategy for non-aggregated data", "no-aggregation-bar-width-strategy": "Bar width strategy for non-aggregated data",
"no-aggregation-bar-width-strategy-group": "Group", "no-aggregation-bar-width-strategy-group": "Group",
"no-aggregation-bar-width-strategy-separate": "Separate", "no-aggregation-bar-width-strategy-separate": "Separate",
"bar-group-interval-width": "Bar group interval width", "bar-group-width": "Bar group width",
"separate-bar-width": "Separate bar width", "bar-width": "Bar width",
"bar-width-relative": "Percentage of time window",
"bar-width-absolute": "Absolute (ms)",
"threshold": { "threshold": {
"thresholds": "Thresholds", "thresholds": "Thresholds",
"source": "Source", "source": "Source",

6
ui-ngx/src/form.scss

@ -29,9 +29,11 @@
@media #{$breakpoint} { @media #{$breakpoint} {
@include form-row-column; @include form-row-column;
.mat-mdc-form-field, tb-unit-input { .mat-mdc-form-field, tb-unit-input {
width: auto; &:not(.fixed-width) {
&.medium-width {
width: auto; width: auto;
&.medium-width {
width: auto;
}
} }
} }
} }

Loading…
Cancel
Save