Browse Source

UI: Bar chart with labels widget

pull/9960/head
Igor Kulikov 3 years ago
parent
commit
06e06797b3
  1. 4
      application/src/main/data/json/system/widget_bundles/charts.json
  2. 30
      application/src/main/data/json/system/widget_types/bar_chart_with_labels.json
  3. 2
      ui-ngx/src/app/core/services/time.service.ts
  4. 36
      ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html
  5. 105
      ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss
  6. 540
      ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts
  7. 112
      ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts
  8. 9
      ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

4
application/src/main/data/json/system/widget_bundles/charts.json

File diff suppressed because one or more lines are too long

30
application/src/main/data/json/system/widget_types/bar_chart_with_labels.json

File diff suppressed because one or more lines are too long

2
ui-ngx/src/app/core/services/time.service.ts

@ -38,7 +38,7 @@ export interface TimeInterval {
const MIN_INTERVAL = SECOND;
const MAX_INTERVAL = 365 * 20 * DAY;
const MIN_LIMIT = 7;
const MIN_LIMIT = 1;
const MAX_DATAPOINTS_LIMIT = 500;

36
ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.html

@ -0,0 +1,36 @@
<!--
Copyright © 2016-2023 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-bar-chart-panel" [style]="backgroundStyle$ | async">
<div class="tb-bar-chart-overlay" [style]="overlayStyle"></div>
<ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container>
<div class="tb-bar-chart-content" [class]="legendClass">
<div #chartShape class="tb-bar-chart-shape">
</div>
<div *ngIf="showLegend" class="tb-bar-chart-legend">
<div class="tb-bar-chart-legend-item" *ngFor="let legendItem of legendItems"
(mouseenter)="onLegendItemEnter(legendItem)"
(mouseleave)="onLegendItemLeave(legendItem)"
(click)="toggleLegendItem(legendItem)">
<div class="tb-bar-chart-legend-item-label">
<div class="tb-bar-chart-legend-item-label-circle" [style]="{background: legendItem.enabled ? legendItem.color : null}"></div>
<div [style]="legendItem.enabled ? legendLabelStyle : disabledLegendLabelStyle">{{ legendItem.label }}</div>
</div>
</div>
</div>
</div>
</div>

105
ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.scss

@ -0,0 +1,105 @@
/**
* Copyright © 2016-2023 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.
*/
.tb-bar-chart-panel {
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 24px 24px 24px;
> div:not(.tb-bar-chart-overlay) {
z-index: 1;
}
.tb-bar-chart-overlay {
position: absolute;
top: 12px;
left: 12px;
bottom: 12px;
right: 12px;
}
div.tb-widget-title {
padding: 0;
}
.tb-bar-chart-content {
flex: 1;
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
gap: 16px;
&.legend-top {
flex-direction: column-reverse;
}
&.legend-right {
flex-direction: row;
}
&.legend-left {
flex-direction: row-reverse;
}
.tb-bar-chart-shape {
flex: 1;
min-width: 0;
min-height: 0;
display: flex;
align-items: center;
justify-content: center;
}
.tb-bar-chart-legend {
display: flex;
justify-content: center;
align-items: center;
align-self: stretch;
flex-wrap: wrap;
column-gap: 24px;
row-gap: 8px;
.tb-bar-chart-legend-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
user-select: none;
cursor: pointer;
.tb-bar-chart-legend-item-label {
display: flex;
align-items: center;
gap: 4px;
color: #ccc;
.tb-bar-chart-legend-item-label-circle {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #ccc;
}
}
}
}
&.legend-right, &.legend-left {
gap: 24px;
.tb-bar-chart-legend {
flex-direction: column-reverse;
justify-content: flex-end;
align-items: stretch;
.tb-bar-chart-legend-item {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
}
}
}
}

540
ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts

@ -0,0 +1,540 @@
///
/// Copyright © 2016-2023 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 {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
Input,
OnDestroy,
OnInit,
Renderer2,
TemplateRef,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { WidgetContext } from '@home/models/widget-component.models';
import {
backgroundStyle,
ComponentStyle,
DateFormatProcessor,
overlayStyle,
textStyle
} from '@shared/models/widget-settings.models';
import { ResizeObserver } from '@juggle/resize-observer';
import * as echarts from 'echarts/core';
import { Axis } from 'echarts';
import { formatValue } from '@core/utils';
import { GridComponent, GridComponentOption, TooltipComponent, TooltipComponentOption } from 'echarts/components';
import { LabelLayout } from 'echarts/features';
import { BarChart, BarSeriesOption} from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import { DataKey, DataSet } from '@shared/models/widget.models';
import { Observable } from 'rxjs';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
import {
barChartWithLabelsDefaultSettings,
BarChartWithLabelsWidgetSettings
} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models';
import { LabelLayoutOptionCallback } from 'echarts/types/dist/shared';
import BarSeriesModel from 'echarts/types/src/chart/bar/BarSeries';
const axisGetBandWidth = Axis.prototype.getBandWidth;
Axis.prototype.getBandWidth = function(){
const series: any[] = this.model?.parentModel?.getSeries();
if (this.scale.type === 'time' && series?.length && series[0].type === 'series.bar') {
const barWidth = (series[0] as BarSeriesModel).getData().getLayout('size');
return barWidth * (series.length + 1);
} else {
return axisGetBandWidth.call(this);
}
};
echarts.use([
TooltipComponent,
GridComponent,
BarChart,
LabelLayout,
CanvasRenderer
]);
type EChartsOption = echarts.ComposeOption<
| TooltipComponentOption
| GridComponentOption
| BarSeriesOption
>;
type ECharts = echarts.ECharts;
type NamedDataSet = {name: string; value: [number, any]}[];
type BarLabelOption = NonNullable<BarSeriesOption['label']>;
interface BarChartDataItem {
id: string;
dataKey: DataKey;
data: NamedDataSet;
enabled: boolean;
}
interface BarChartLegendItem {
id: string;
color: string;
label: string;
enabled: boolean;
}
const toNamedData = (data: DataSet): NamedDataSet => {
if (!data?.length) {
return [];
} else {
return data.map(d => ({
name: d[0] + '',
value: d
}));
}
};
@Component({
selector: 'tb-bar-chart-with-labels-widget',
templateUrl: './bar-chart-with-labels-widget.component.html',
styleUrls: ['./bar-chart-with-labels-widget.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChild('chartShape', {static: false})
chartShape: ElementRef<HTMLElement>;
settings: BarChartWithLabelsWidgetSettings;
@Input()
ctx: WidgetContext;
@Input()
widgetTitlePanel: TemplateRef<any>;
showLegend: boolean;
legendClass: string;
backgroundStyle$: Observable<ComponentStyle>;
overlayStyle: ComponentStyle = {};
legendItems: BarChartLegendItem[];
legendLabelStyle: ComponentStyle;
disabledLegendLabelStyle: ComponentStyle;
private shapeResize$: ResizeObserver;
private decimals = 0;
private units = '';
private dataItems: BarChartDataItem[] = [];
private drawChartPending = false;
private barChart: ECharts;
private barChartOptions: EChartsOption;
private tooltipDateFormat: DateFormatProcessor;
private barLabelOptions: BarLabelOption;
private barLabelLayoutCallback: LabelLayoutOptionCallback;
constructor(private imagePipe: ImagePipe,
private sanitizer: DomSanitizer,
private renderer: Renderer2,
private cd: ChangeDetectorRef) {
}
ngOnInit(): void {
this.ctx.$scope.barChartWidget = this;
this.settings = {...barChartWithLabelsDefaultSettings, ...this.ctx.settings};
this.decimals = this.ctx.decimals;
this.units = this.ctx.units;
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
this.overlayStyle = overlayStyle(this.settings.background.overlay);
this.showLegend = this.settings.showLegend;
if (this.showLegend) {
this.legendItems = [];
this.legendClass = `legend-${this.settings.legendPosition}`;
this.legendLabelStyle = textStyle(this.settings.legendLabelFont);
this.disabledLegendLabelStyle = textStyle(this.settings.legendLabelFont);
this.legendLabelStyle.color = this.settings.legendLabelColor;
}
let counter = 0;
if (this.ctx.datasources.length) {
for (const datasource of this.ctx.datasources) {
const dataKeys = datasource.dataKeys;
for (const dataKey of dataKeys) {
const id = counter++;
const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === dataKey) : null;
const namedData = datasourceData?.data ? toNamedData(datasourceData.data) : [];
this.dataItems.push({
id: id+'',
dataKey,
data: namedData,
enabled: true
});
if (this.showLegend) {
this.legendItems.push(
{
id: id+'',
label: dataKey.label,
color: dataKey.color,
enabled: true
}
);
}
}
}
}
if (this.settings.showTooltip && this.settings.tooltipShowDate) {
this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat);
}
const barValueStyle: ComponentStyle = textStyle(this.settings.barValueFont);
delete barValueStyle.lineHeight;
barValueStyle.fontSize = this.settings.barValueFont.size;
barValueStyle.color = this.settings.barValueColor;
const barLabelStyle: ComponentStyle = textStyle(this.settings.barLabelFont);
delete barLabelStyle.lineHeight;
barLabelStyle.fontSize = this.settings.barLabelFont.size;
barLabelStyle.color = this.settings.barLabelColor;
this.barLabelOptions = {
show: this.settings.showBarLabel || this.settings.showBarValue,
position: 'insideBottom',
distance: 15,
align: 'left',
verticalAlign: 'middle',
rotate: 90,
formatter: (params) => {
const parts: string[] = [];
if (this.settings.showBarValue) {
const value = formatValue(params.value[1], this.decimals, '', false);
parts.push(`{value|${value}}`);
}
if (this.settings.showBarLabel) {
parts.push(`{label|${params.seriesName}}`);
}
return parts.join(' ');
},
rich: {
value: barValueStyle,
label: barLabelStyle
}
};
this.barLabelLayoutCallback = (params) => {
if (params.rect.width - params.labelRect.width < 2) {
return {
y: '-100%'
};
} else {
return {
hideOverlap: true
};
}
};
}
ngAfterViewInit() {
if (this.drawChartPending) {
this.drawChart();
}
}
ngOnDestroy() {
if (this.shapeResize$) {
this.shapeResize$.disconnect();
}
if (this.barChart) {
this.barChart.dispose();
}
}
public onInit() {
const borderRadius = this.ctx.$widgetElement.css('borderRadius');
this.overlayStyle = {...this.overlayStyle, ...{borderRadius}};
if (this.chartShape) {
this.drawChart();
} else {
this.drawChartPending = true;
}
this.cd.detectChanges();
}
public onDataUpdated() {
let minTime = this.ctx.defaultSubscription.timeWindow.minTime;
for (const item of this.dataItems) {
const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === item.dataKey) : null;
const namedData = datasourceData?.data ? toNamedData(datasourceData.data) : [];
item.data = namedData;
if (datasourceData.data.length) {
minTime = Math.min(datasourceData.data[0][0], minTime);
}
}
if (this.barChart) {
(this.barChartOptions.xAxis as any).min = minTime;
(this.barChartOptions.xAxis as any).max = this.ctx.defaultSubscription.timeWindow.maxTime;
this.barChartOptions.series = this.updateSeries();
this.barChart.setOption(this.barChartOptions);
}
}
private updateSeries(): Array<BarSeriesOption> {
const series: Array<BarSeriesOption> = [];
for (const item of this.dataItems) {
if (item.enabled) {
const seriesOption: BarSeriesOption = {
type: 'bar',
barGap: 0,
barMaxWidth: 40,
id: item.id,
name: item.dataKey.label,
label: this.barLabelOptions,
color: item.dataKey.color,
data: item.data,
emphasis: {
focus: 'series'
},
labelLayout: this.barLabelLayoutCallback
};
series.push(seriesOption);
}
}
return series;
}
public onLegendItemEnter(item: BarChartLegendItem) {
this.barChart.dispatchAction({
type: 'highlight',
seriesId: item.id
});
}
public onLegendItemLeave(item: BarChartLegendItem) {
this.barChart.dispatchAction({
type: 'downplay',
seriesId: item.id
});
}
public toggleLegendItem(item: BarChartLegendItem) {
const enable = !item.enabled;
const dataItem = this.dataItems.find(d => d.id === item.id);
if (dataItem) {
dataItem.enabled = enable;
this.barChartOptions.series = this.updateSeries();
this.barChart.setOption(this.barChartOptions, true);
item.enabled = enable;
if (enable) {
this.barChart.dispatchAction({
type: 'highlight',
seriesId: item.id
});
} else {
for (const otherItem of this.legendItems.filter(i => i.id !== item.id)) {
this.barChart.dispatchAction({
type: 'highlight',
seriesId: otherItem.id
});
}
}
}
}
private drawChart() {
this.barChart = echarts.init(this.chartShape.nativeElement, null, {
renderer: 'canvas',
});
this.barChartOptions = {
tooltip: {
trigger: 'none'
},
grid: {
containLabel: true,
top: '30',
left: 0,
right: 0,
bottom: 0
},
xAxis: {
type: 'time',
axisTick: {
show: false
},
axisLabel: {
hideOverlap: true,
fontSize: 10
},
axisLine: {
onZero: false
},
min: this.ctx.defaultSubscription.timeWindow.minTime,
max: this.ctx.defaultSubscription.timeWindow.maxTime
},
yAxis: {
type: 'value',
axisLabel: {
formatter: value => formatValue(value, this.decimals, this.units, false)
}
}
};
this.barChartOptions.series = this.updateSeries();
if (this.settings.showTooltip) {
this.barChartOptions.tooltip = {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: (params: any[]) => {
if (!params.length || !params[0]) {
return null;
}
const tooltipElement: HTMLElement = this.renderer.createElement('div');
this.renderer.setStyle(tooltipElement, 'display', 'flex');
this.renderer.setStyle(tooltipElement, 'flex-direction', 'column');
this.renderer.setStyle(tooltipElement, 'align-items', 'flex-start');
this.renderer.setStyle(tooltipElement, 'gap', '4px');
if (this.settings.tooltipShowDate) {
const dateElement: HTMLElement = this.renderer.createElement('div');
const ts = params[0].value[0];
this.tooltipDateFormat.update(ts);
this.renderer.appendChild(dateElement, this.renderer.createText(this.tooltipDateFormat.formatted));
this.renderer.setStyle(dateElement, 'font-family', this.settings.tooltipDateFont.family);
this.renderer.setStyle(dateElement, 'font-size', this.settings.tooltipDateFont.size + this.settings.tooltipDateFont.sizeUnit);
this.renderer.setStyle(dateElement, 'font-style', this.settings.tooltipDateFont.style);
this.renderer.setStyle(dateElement, 'font-weight', this.settings.tooltipDateFont.weight);
this.renderer.setStyle(dateElement, 'line-height', this.settings.tooltipDateFont.lineHeight);
this.renderer.setStyle(dateElement, 'color', this.settings.tooltipDateColor);
this.renderer.appendChild(tooltipElement, dateElement);
}
let seriesParams = null;
const focusedSeriesIndex = this.focusedSeriesIndex();
if (focusedSeriesIndex > -1) {
seriesParams = params.find(param => param.seriesIndex === focusedSeriesIndex);
}
if (seriesParams) {
this.renderer.appendChild(tooltipElement, this.constructTooltipSeriesElement(seriesParams));
} else {
for (seriesParams of params) {
this.renderer.appendChild(tooltipElement, this.constructTooltipSeriesElement(seriesParams));
}
}
return tooltipElement;
},
padding: [8, 12],
backgroundColor: this.settings.tooltipBackgroundColor,
extraCssText: `line-height: 1; backdrop-filter: blur(${this.settings.tooltipBackgroundBlur}px);`
};
}
this.barChart.setOption(this.barChartOptions);
this.shapeResize$ = new ResizeObserver(() => {
this.onResize();
});
this.shapeResize$.observe(this.chartShape.nativeElement);
this.onResize();
}
private constructTooltipSeriesElement(seriesParams): HTMLElement {
const labelValueElement: HTMLElement = this.renderer.createElement('div');
this.renderer.setStyle(labelValueElement, 'display', 'flex');
this.renderer.setStyle(labelValueElement, 'flex-direction', 'row');
this.renderer.setStyle(labelValueElement, 'align-items', 'center');
this.renderer.setStyle(labelValueElement, 'align-self', 'stretch');
this.renderer.setStyle(labelValueElement, 'gap', '12px');
const labelElement: HTMLElement = this.renderer.createElement('div');
this.renderer.setStyle(labelElement, 'display', 'flex');
this.renderer.setStyle(labelElement, 'align-items', 'center');
this.renderer.setStyle(labelElement, 'gap', '8px');
this.renderer.appendChild(labelValueElement, labelElement);
const circleElement: HTMLElement = this.renderer.createElement('div');
this.renderer.setStyle(circleElement, 'width', '8px');
this.renderer.setStyle(circleElement, 'height', '8px');
this.renderer.setStyle(circleElement, 'border-radius', '50%');
this.renderer.setStyle(circleElement, 'background', seriesParams.color);
this.renderer.appendChild(labelElement, circleElement);
const labelTextElement: HTMLElement = this.renderer.createElement('div');
this.renderer.appendChild(labelTextElement, this.renderer.createText(seriesParams.seriesName));
this.renderer.setStyle(labelTextElement, 'font-family', 'Roboto');
this.renderer.setStyle(labelTextElement, 'font-size', '12px');
this.renderer.setStyle(labelTextElement, 'font-style', 'normal');
this.renderer.setStyle(labelTextElement, 'font-weight', '400');
this.renderer.setStyle(labelTextElement, 'line-height', '16px');
this.renderer.setStyle(labelTextElement, 'letter-spacing', '0.4px');
this.renderer.setStyle(labelTextElement, 'color', 'rgba(0, 0, 0, 0.76)');
this.renderer.appendChild(labelElement, labelTextElement);
const valueElement: HTMLElement = this.renderer.createElement('div');
const value = formatValue(seriesParams.value[1], this.decimals, this.units, false);
this.renderer.appendChild(valueElement, this.renderer.createText(value));
this.renderer.setStyle(valueElement, 'flex', '1');
this.renderer.setStyle(valueElement, 'text-align', 'end');
this.renderer.setStyle(valueElement, 'font-family', this.settings.tooltipValueFont.family);
this.renderer.setStyle(valueElement, 'font-size', this.settings.tooltipValueFont.size + this.settings.tooltipValueFont.sizeUnit);
this.renderer.setStyle(valueElement, 'font-style', this.settings.tooltipValueFont.style);
this.renderer.setStyle(valueElement, 'font-weight', this.settings.tooltipValueFont.weight);
this.renderer.setStyle(valueElement, 'line-height', this.settings.tooltipValueFont.lineHeight);
this.renderer.setStyle(valueElement, 'color', this.settings.tooltipValueColor);
this.renderer.appendChild(labelValueElement, valueElement);
return labelValueElement;
}
private focusedSeriesIndex(): number {
let index = - 1;
// @ts-ignore
const views: any[] = this.barChart._chartsViews;
if (views) {
const hasBlurredView = !!views.find(view => {
const graphicEls: any[] = view._data._graphicEls;
return !!graphicEls.find(el => el.currentStates.includes('blur'));
});
if (hasBlurredView) {
const focusedView = views.find(view => {
const graphicEls: any[] = view._data._graphicEls;
return !!graphicEls.find(el => !el.currentStates.includes('blur'));
});
if (focusedView) {
index = focusedView._model.seriesIndex;
}
}
}
return index;
}
private onResize() {
const width = this.barChart.getWidth();
const height = this.barChart.getHeight();
const shapeWidth = this.chartShape.nativeElement.offsetWidth;
const shapeHeight = this.chartShape.nativeElement.offsetHeight;
if (width !== shapeWidth || height !== shapeHeight) {
this.barChart.resize();
}
}
}

112
ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.models.ts

@ -0,0 +1,112 @@
///
/// Copyright © 2016-2023 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 {
BackgroundSettings,
BackgroundType, customDateFormat,
DateFormatSettings,
Font
} from '@shared/models/widget-settings.models';
import { LegendPosition } from '@shared/models/widget.models';
export interface BarChartWithLabelsWidgetSettings {
showBarLabel: boolean;
barLabelFont: Font;
barLabelColor: string;
showBarValue: boolean;
barValueFont: Font;
barValueColor: string;
showLegend: boolean;
legendPosition: LegendPosition;
legendLabelFont: Font;
legendLabelColor: string;
showTooltip: boolean;
tooltipValueFont: Font;
tooltipValueColor: string;
tooltipShowDate: boolean;
tooltipDateFormat: DateFormatSettings;
tooltipDateFont: Font;
tooltipDateColor: string;
tooltipBackgroundColor: string;
tooltipBackgroundBlur: number;
background: BackgroundSettings;
}
export const barChartWithLabelsDefaultSettings: BarChartWithLabelsWidgetSettings = {
showBarLabel: true,
barLabelFont: {
family: 'Roboto',
size: 12,
sizeUnit: 'px',
style: 'normal',
weight: '400',
lineHeight: '12px'
},
barLabelColor: 'rgba(0, 0, 0, 0.54)',
showBarValue: true,
barValueFont: {
family: 'Roboto',
size: 12,
sizeUnit: 'px',
style: 'normal',
weight: '700',
lineHeight: '12px'
},
barValueColor: 'rgba(0, 0, 0, 0.76)',
showLegend: true,
legendPosition: LegendPosition.top,
legendLabelFont: {
family: 'Roboto',
size: 12,
sizeUnit: 'px',
style: 'normal',
weight: '400',
lineHeight: '16px'
},
legendLabelColor: 'rgba(0, 0, 0, 0.76)',
showTooltip: true,
tooltipValueFont: {
family: 'Roboto',
size: 12,
sizeUnit: 'px',
style: 'normal',
weight: '500',
lineHeight: '16px'
},
tooltipValueColor: 'rgba(0, 0, 0, 0.76)',
tooltipShowDate: true,
tooltipDateFormat: customDateFormat('MMMM y'),
tooltipDateFont: {
family: 'Roboto',
size: 11,
sizeUnit: 'px',
style: 'normal',
weight: '400',
lineHeight: '16px'
},
tooltipDateColor: 'rgba(0, 0, 0, 0.76)',
tooltipBackgroundColor: 'rgba(255, 255, 255, 0.76)',
tooltipBackgroundBlur: 4,
background: {
type: BackgroundType.color,
color: '#fff',
overlay: {
enabled: false,
color: 'rgba(255,255,255,0.72)',
blur: 3
}
}
};

9
ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts

@ -67,6 +67,9 @@ import { ProgressBarWidgetComponent } from '@home/components/widget/lib/cards/pr
import { LiquidLevelWidgetComponent } from '@home/components/widget/lib/indicator/liquid-level-widget.component';
import { DoughnutWidgetComponent } from '@home/components/widget/lib/chart/doughnut-widget.component';
import { RangeChartWidgetComponent } from '@home/components/widget/lib/chart/range-chart-widget.component';
import {
BarChartWithLabelsWidgetComponent
} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.component';
@NgModule({
declarations:
@ -108,7 +111,8 @@ import { RangeChartWidgetComponent } from '@home/components/widget/lib/chart/ran
ProgressBarWidgetComponent,
LiquidLevelWidgetComponent,
DoughnutWidgetComponent,
RangeChartWidgetComponent
RangeChartWidgetComponent,
BarChartWithLabelsWidgetComponent
],
imports: [
CommonModule,
@ -154,7 +158,8 @@ import { RangeChartWidgetComponent } from '@home/components/widget/lib/chart/ran
ProgressBarWidgetComponent,
LiquidLevelWidgetComponent,
DoughnutWidgetComponent,
RangeChartWidgetComponent
RangeChartWidgetComponent,
BarChartWithLabelsWidgetComponent
],
providers: [
{provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule }

Loading…
Cancel
Save