{{ 'widgets.doughnut.central-total-value' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts
index 2feb44615d..f8149bc97d 100644
--- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/doughnut-basic-config.component.ts
@@ -40,7 +40,7 @@ import {
doughnutLayoutImages,
doughnutLayouts,
doughnutLayoutTranslations,
- DoughnutLegendPosition,
+ doughnutLegendPositions,
doughnutLegendPositionTranslations,
DoughnutTooltipValueType,
doughnutTooltipValueTypes,
@@ -83,7 +83,7 @@ export class DoughnutBasicConfigComponent extends BasicWidgetConfigComponent {
doughnutLayoutImageMap: Map;
- doughnutLegendPositions: DoughnutLegendPosition[];
+ doughnutLegendPositions = doughnutLegendPositions;
doughnutLegendPositionTranslationMap = doughnutLegendPositionTranslations;
@@ -116,8 +116,6 @@ export class DoughnutBasicConfigComponent extends BasicWidgetConfigComponent {
const params = widgetConfig.typeParameters as any;
this.horizontal = isDefinedAndNotNull(params.horizontal) ? params.horizontal : false;
this.doughnutLayoutImageMap = this.horizontal ? horizontalDoughnutLayoutImages : doughnutLayoutImages;
- this.doughnutLegendPositions = this.horizontal ? [DoughnutLegendPosition.left, DoughnutLegendPosition.right] :
- [DoughnutLegendPosition.top, DoughnutLegendPosition.bottom];
super.setupConfig(widgetConfig);
}
@@ -136,6 +134,8 @@ export class DoughnutBasicConfigComponent extends BasicWidgetConfigComponent {
layout: [settings.layout, []],
autoScale: [settings.autoScale, []],
+ clockwise: [settings.clockwise, []],
+ sortSeries: [settings.sortSeries, []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
@@ -193,6 +193,8 @@ export class DoughnutBasicConfigComponent extends BasicWidgetConfigComponent {
this.widgetConfig.config.settings.layout = config.layout;
this.widgetConfig.config.settings.autoScale = config.autoScale;
+ this.widgetConfig.config.settings.clockwise = config.clockwise;
+ this.widgetConfig.config.settings.sortSeries = config.sortSeries;
this.widgetConfig.config.settings.totalValueFont = config.totalValueFont;
this.widgetConfig.config.settings.totalValueColor = config.totalValueColor;
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts
index 573aea1e90..a6b6c426a0 100644
--- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts
@@ -69,9 +69,11 @@ import { coerceBoolean } from '@shared/decorators/coercion';
import { alarmFields } from '@shared/models/alarm.models';
import { UtilsService } from '@core/services/utils.service';
+export const dataKeyValid = (key: DataKey): boolean => !!key && !!key.type && !!key.name;
+
export const dataKeyRowValidator = (control: AbstractControl): ValidationErrors | null => {
const dataKey: DataKey = control.value;
- if (!dataKey || !dataKey.type || !dataKey.name) {
+ if (!dataKeyValid(dataKey)) {
return {
dataKey: true
};
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts
index 00684f6d53..07a122c66a 100644
--- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.ts
@@ -38,7 +38,7 @@ import {
import { MatDialog } from '@angular/material/dialog';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { DataKey, DatasourceType, JsonSettingsSchema, widgetType } from '@shared/models/widget.models';
-import { dataKeyRowValidator } from '@home/components/widget/config/basic/common/data-key-row.component';
+import { dataKeyRowValidator, dataKeyValid } from '@home/components/widget/config/basic/common/data-key-row.component';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { UtilsService } from '@core/services/utils.service';
@@ -168,7 +168,13 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC
keys: [this.fb.array([]), []]
});
this.keysListFormGroup.valueChanges.subscribe(
- (val) => this.propagateChange(this.keysListFormGroup.get('keys').value)
+ () => {
+ let keys: DataKey[] = this.keysListFormGroup.get('keys').value;
+ if (keys) {
+ keys = keys.filter(k => dataKeyValid(k));
+ }
+ this.propagateChange(keys);
+ }
);
this.updateParams();
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts
index 92b2e84618..08c86de1d5 100644
--- a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts
@@ -263,7 +263,7 @@ export class DatasourceComponent implements ControlValueAccessor, OnInit, Valida
}
public isDataKeysOptional(type?: DatasourceType): boolean {
- if (this.hasAdditionalLatestDataKeys) {
+ if (this.hasAdditionalLatestDataKeys || this.hideDataKeys) {
return true;
} else {
return this.dataKeysOptional
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts
index c4f32f89c9..1595c59110 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts
@@ -209,7 +209,13 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
}
}
}
- if (!this.showTotal && this.showLegend) {
+ if (this.settings.sortSeries) {
+ this.dataItems.sort((a, b) => a.dataKey.label.localeCompare(b.dataKey.label));
+ if (this.showLegend) {
+ this.legendItems.sort((a, b) => a.label.localeCompare(b.label));
+ }
+ }
+ if (this.showLegend && !this.showTotal) {
this.legendItems.push(
{
id: null,
@@ -251,17 +257,17 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
}
public onDataUpdated() {
- for (let i=0; i < this.ctx.data.length; i++) {
- const dsData = this.ctx.data[i];
+ for (const dsData of this.ctx.data) {
let value = 0;
const tsValue = dsData.data[0];
+ const dataItem = this.dataItems.find(item => item.dataKey === dsData.dataKey);
if (tsValue && isDefinedAndNotNull(tsValue[1]) && isNumeric(tsValue[1])) {
value = tsValue[1];
- this.dataItems[i].hasValue = true;
- this.dataItems[i].value = value;
+ dataItem.hasValue = true;
+ dataItem.value = Number(value);
} else {
- this.dataItems[i].hasValue = false;
- this.dataItems[i].value = 0;
+ dataItem.hasValue = false;
+ dataItem.value = 0;
}
}
this.updateSeriesData();
@@ -281,8 +287,7 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
let hasValue = false;
const seriesData: PieDataItemOption[] = [];
const enabledDataItems = this.dataItems.filter(item => item.enabled && item.hasValue);
- for (let i=0; i < this.dataItems.length; i++) {
- const dataItem = this.dataItems[i];
+ for (const dataItem of this.dataItems) {
if (dataItem.enabled && dataItem.hasValue) {
hasValue = true;
this.total += dataItem.value;
@@ -296,12 +301,13 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
}
}
if (this.showLegend) {
+ const legendItem = this.legendItems.find(item => item.id === dataItem.id);
if (dataItem.hasValue) {
- this.legendItems[i].hasValue = true;
- this.legendItems[i].value = formatValue(dataItem.value, this.decimals, this.units, false);
+ legendItem.hasValue = true;
+ legendItem.value = formatValue(dataItem.value, this.decimals, this.units, false);
} else {
- this.legendItems[i].hasValue = false;
- this.legendItems[i].value = '--';
+ legendItem.hasValue = false;
+ legendItem.value = '--';
}
}
}
@@ -395,7 +401,7 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
series: [
{
type: 'pie',
- clockwise: false,
+ clockwise: this.settings.clockwise,
radius: [innerRadius, outerRadius],
avoidLabelOverlap: false,
itemStyle: {
@@ -424,6 +430,9 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit
if (this.settings.showTooltip) {
this.doughnutOptions.series[0].tooltip = {
formatter: (params) => {
+ if (!params.name) {
+ return null;
+ }
let value: string;
if (this.settings.tooltipValueType === DoughnutTooltipValueType.percentage) {
const percents = params.value / this.total * 100;
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.models.ts
index 1e3c323cb6..1771dbbb8a 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.models.ts
@@ -57,6 +57,8 @@ export enum DoughnutLegendPosition {
right = 'right'
}
+export const doughnutLegendPositions = Object.keys(DoughnutLegendPosition) as DoughnutLegendPosition[];
+
export const doughnutLegendPositionTranslations = new Map(
[
[DoughnutLegendPosition.top, 'widgets.doughnut.legend-position-top'],
@@ -83,6 +85,8 @@ export const doughnutTooltipValueTypeTranslations = new Map ({
layout: DoughnutLayout.default,
autoScale: true,
+ clockwise: false,
+ sortSeries: false,
totalValueFont: {
family: 'Roboto',
size: 24,
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts
index 9bb7053c3e..847937581b 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts
@@ -160,26 +160,30 @@ export class LiquidLevelWidgetComponent implements OnInit {
}
private getData(): Observable<{ svg: string; volume: number; units: string }> {
- const entityId: EntityId = {
- entityType: this.ctx.datasources[0].entityType,
- id: this.ctx.datasources[0].entityId
- };
+ if (this.ctx.datasources?.length) {
+ const entityId: EntityId = {
+ entityType: this.ctx.datasources[0].entityType,
+ id: this.ctx.datasources[0].entityId
+ };
+
+ return this.getShape(entityId).pipe(
+ switchMap(shape => {
+ this.shape = shape;
+ this.svgParams = svgMapping.get(shape);
+ if (this.svgParams) {
+ return forkJoin([
+ this.resourcesService.loadJsonResource(this.svgParams.svg),
+ this.getTankersParams(entityId)
+ ]).pipe(
+ map(params => ({svg: params[0], ...params[1]}))
+ );
+ }
+ return of(null);
+ })
+ );
+ }
- return this.getShape(entityId).pipe(
- switchMap(shape => {
- this.shape = shape;
- this.svgParams = svgMapping.get(shape);
- if (this.svgParams) {
- return forkJoin([
- this.resourcesService.loadJsonResource(this.svgParams.svg),
- this.getTankersParams(entityId)
- ]).pipe(
- map(params => ({svg: params[0], ...params[1]}))
- );
- }
- return of(null);
- })
- );
+ return of(null);
}
public onInit() {
@@ -541,13 +545,13 @@ export class LiquidLevelWidgetComponent implements OnInit {
`;
}
- private convertInputData(value: number): number {
+ private convertInputData(value: any): number {
if (this.settings.datasourceUnits !== CapacityUnits.percent) {
- return (convertLiters(value, this.settings.datasourceUnits, ConversionType.to) /
+ return (convertLiters(Number(value), this.settings.datasourceUnits, ConversionType.to) /
convertLiters(this.volume, this.settings.volumeUnits, ConversionType.to)) * 100;
}
- return value;
+ return Number(value);
}
private convertOutputData(value: number): number {
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.html
index a92c0526f0..a0e76da09c 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-widget-settings.component.html
@@ -32,7 +32,17 @@
- {{ 'widgets.value-card.auto-scale' | translate }}
+ {{ 'widgets.doughnut.auto-scale' | translate }}
+
+
+
+
+ {{ 'widgets.doughnut.clockwise-layout' | translate }}
+
+
+
+
+ {{ 'widgets.doughnut.sort-series' | translate }}