UI: liquid level widget improvements
This commit is contained in:
parent
6c6b606fdf
commit
16fa1780c0
@ -184,10 +184,30 @@
|
||||
formControlName="volumeAttributeName">
|
||||
</tb-string-autocomplete>
|
||||
</ng-template>
|
||||
<tb-unit-input [tagFilter]="unitsType.capacity"
|
||||
required style="max-width: 25%" class="flex"
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row space-between" [fxShow]="volumeInput">
|
||||
<div class="fixed-title-width tb-required" translate>widgets.liquid-level-card.total-volume-units</div>
|
||||
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
|
||||
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic" style="max-width: 25%">
|
||||
<mat-select formControlName="volumeUnitsSource" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
<mat-option *ngFor="let type of DataSourceTypes" [value]="type">
|
||||
{{ DataSourceTypeTranslations.get(type) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<tb-unit-input *ngIf="levelCardWidgetConfigForm.get('volumeUnitsSource').value === DataSourceType.static; else selectVolumeUnitsAttributes"
|
||||
class="flex" required
|
||||
[tagFilter]="unitsType.capacity"
|
||||
formControlName="volumeUnits">
|
||||
</tb-unit-input>
|
||||
<ng-template #selectVolumeUnitsAttributes>
|
||||
<tb-string-autocomplete [fetchOptionsFn]="fetchOptions.bind(this)"
|
||||
required style="flex: 1"
|
||||
[errorText]="'widgets.liquid-level-card.attribute-name-required' | translate"
|
||||
formControlName="volumeUnitsAttributeName">
|
||||
</tb-string-autocomplete>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -194,7 +194,9 @@ export class LiquidLevelCardBasicConfigComponent extends BasicWidgetConfigCompon
|
||||
volumeSource: [settings.volumeSource, []],
|
||||
volumeConstant: [settings.volumeConstant, [Validators.required, Validators.min(0.1)]],
|
||||
volumeAttributeName: [settings.volumeAttributeName, [Validators.required]],
|
||||
volumeUnitsSource: [settings.volumeUnitsSource, []],
|
||||
volumeUnits: [settings.volumeUnits, [Validators.required]],
|
||||
volumeUnitsAttributeName: [settings.volumeUnitsAttributeName, [Validators.required]],
|
||||
volumeFont: [settings.volumeFont, []],
|
||||
volumeColor: [settings.volumeColor, []],
|
||||
units: [settings.units, [Validators.required]],
|
||||
@ -260,6 +262,8 @@ export class LiquidLevelCardBasicConfigComponent extends BasicWidgetConfigCompon
|
||||
this.widgetConfig.config.settings.volumeSource = config.volumeSource;
|
||||
this.widgetConfig.config.settings.volumeConstant = config.volumeConstant;
|
||||
this.widgetConfig.config.settings.volumeAttributeName = config.volumeAttributeName;
|
||||
this.widgetConfig.config.settings.volumeUnitsSource = config.volumeUnitsSource;
|
||||
this.widgetConfig.config.settings.volumeUnitsAttributeName = config.volumeUnitsAttributeName;
|
||||
this.widgetConfig.config.settings.volumeUnits = config.volumeUnits;
|
||||
this.widgetConfig.config.settings.volumeFont = config.volumeFont;
|
||||
this.widgetConfig.config.settings.volumeColor = config.volumeColor;
|
||||
@ -294,7 +298,7 @@ export class LiquidLevelCardBasicConfigComponent extends BasicWidgetConfigCompon
|
||||
protected validatorTriggers(): string[] {
|
||||
return [
|
||||
'showTooltip', 'showTooltipLevel', 'tankSelectionType', 'datasourceUnits', 'showTitleIcon', 'volumeSource',
|
||||
'showTooltipDate', 'layout', 'showTitle', 'widgetUnitsSource'
|
||||
'showTooltipDate', 'layout', 'showTitle', 'widgetUnitsSource', 'volumeUnitsSource'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -106,6 +106,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
private volume: number;
|
||||
private tooltipContent: string;
|
||||
private widgetUnits: string;
|
||||
private volumeUnits: string;
|
||||
|
||||
private capacityUnits = Object.values(CapacityUnits);
|
||||
|
||||
@ -128,7 +129,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
|
||||
this.getData().subscribe(data => {
|
||||
if (data) {
|
||||
const { svg, volume, units } = data;
|
||||
const { svg, volume, units, volumeUnits } = data;
|
||||
if (svg && isNotEmptyStr(svg) && this.liquidLevelContent.nativeElement) {
|
||||
const jQueryContainerElement = $(this.liquidLevelContent.nativeElement);
|
||||
jQueryContainerElement.html(svg);
|
||||
@ -145,6 +146,10 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
this.volume = Number(volume);
|
||||
}
|
||||
|
||||
if (volumeUnits) {
|
||||
this.volumeUnits = volumeUnits;
|
||||
}
|
||||
|
||||
if (units) {
|
||||
this.widgetUnits = units;
|
||||
}
|
||||
@ -164,7 +169,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat);
|
||||
}
|
||||
|
||||
private getData(): Observable<{ svg: string; volume: number; units: string }> {
|
||||
private getData(): Observable<{ svg: string; volume: number; units: string; volumeUnits: string}> {
|
||||
if (this.ctx.datasources?.length) {
|
||||
const entityId: EntityId = {
|
||||
entityType: this.ctx.datasources[0].entityType,
|
||||
@ -308,7 +313,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
.pipe(map(attributes => {
|
||||
const shape = extractValue<Shapes>(attributes, this.settings.shapeAttributeName);
|
||||
if (!shape || !svgMapping.has(shape)) {
|
||||
this.createdErrorMgs(this.settings.shapeAttributeName, isUndefinedOrNull(shape) || isEmptyStr(shape));
|
||||
this.createdErrorMsg(this.settings.shapeAttributeName, isUndefinedOrNull(shape) || isEmptyStr(shape));
|
||||
return this.settings.selectedShape;
|
||||
}
|
||||
return shape;
|
||||
@ -318,12 +323,15 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
return of(this.settings.selectedShape);
|
||||
}
|
||||
|
||||
private getTankersParams(entityId: EntityId): Observable<{ volume: number; units: string }> {
|
||||
private getTankersParams(entityId: EntityId): Observable<{ volume: number; units: string; volumeUnits: string }> {
|
||||
const isVolumeStatic = this.settings.layout !== LevelCardLayout.absolute
|
||||
&& this.settings.datasourceUnits === CapacityUnits.percent
|
||||
|| this.settings.volumeSource === LiquidWidgetDataSourceType.static;
|
||||
const isUnitStatic = this.settings.layout !== LevelCardLayout.absolute ||
|
||||
this.settings.widgetUnitsSource === LiquidWidgetDataSourceType.static;
|
||||
const isVolumeUnitStatic = this.settings.layout !== LevelCardLayout.absolute
|
||||
&& this.settings.datasourceUnits === CapacityUnits.percent
|
||||
|| this.settings.volumeUnitsSource === LiquidWidgetDataSourceType.static;
|
||||
|
||||
const attributeKeys: string[] = [];
|
||||
|
||||
@ -335,20 +343,29 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
attributeKeys.push(this.settings.widgetUnitsAttributeName);
|
||||
}
|
||||
|
||||
if (!isVolumeUnitStatic) {
|
||||
attributeKeys.push(this.settings.volumeUnitsAttributeName);
|
||||
}
|
||||
|
||||
if (!attributeKeys.length || entityId.id === NULL_UUID) {
|
||||
return of({
|
||||
volume: this.settings.volumeConstant,
|
||||
volumeUnits: this.settings.volumeUnits,
|
||||
units: this.settings.units
|
||||
});
|
||||
}
|
||||
|
||||
return this.ctx.attributeService.getEntityAttributes(entityId, null, attributeKeys).pipe(
|
||||
map(attributes => {
|
||||
let volume = isVolumeStatic ? this.settings.volumeConstant : extractValue<number>(attributes, this.settings.volumeAttributeName);
|
||||
let units = isUnitStatic ? this.settings.units : extractValue<string>(attributes, this.settings.widgetUnitsAttributeName);
|
||||
let volume = isVolumeStatic ? this.settings.volumeConstant :
|
||||
extractValue<number>(attributes, this.settings.volumeAttributeName);
|
||||
let volumeUnits = isVolumeUnitStatic ? this.settings.volumeUnits :
|
||||
extractValue<string>(attributes, this.settings.volumeUnitsAttributeName);
|
||||
let units = isUnitStatic ? this.settings.units :
|
||||
extractValue<string>(attributes, this.settings.widgetUnitsAttributeName);
|
||||
|
||||
if (!isVolumeStatic && (!volume || !isNumeric(volume) || volume < 0.1)) {
|
||||
this.createdErrorMgs(this.settings.volumeAttributeName, isUndefinedOrNull(volume) || isEmptyStr(volume));
|
||||
this.createdErrorMsg(this.settings.volumeAttributeName, isUndefinedOrNull(volume) || isEmptyStr(volume));
|
||||
volume = this.settings.volumeConstant;
|
||||
}
|
||||
|
||||
@ -358,20 +375,33 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
units = this.capacityUnits.find(unit => unit.normalize() === normalizeUnits);
|
||||
}
|
||||
if (isUndefinedOrNull(units) || !isNotEmptyStr(units)) {
|
||||
this.createdErrorMgs(this.settings.widgetUnitsAttributeName, isUndefinedOrNull(units) || isEmptyStr(units));
|
||||
this.createdErrorMsg(this.settings.widgetUnitsAttributeName, isUndefinedOrNull(units) || isEmptyStr(units));
|
||||
units = this.settings.units;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVolumeUnitStatic) {
|
||||
if (isNotEmptyStr(volumeUnits)) {
|
||||
const normalizeUnits = volumeUnits.normalize().trim();
|
||||
volumeUnits = this.capacityUnits.find(unit => unit.normalize() === normalizeUnits);
|
||||
}
|
||||
if (isUndefinedOrNull(volumeUnits) || !isNotEmptyStr(volumeUnits)) {
|
||||
this.createdErrorMsg(this.settings.widgetUnitsAttributeName,
|
||||
isUndefinedOrNull(volumeUnits) || isEmptyStr(volumeUnits));
|
||||
volumeUnits = this.settings.volumeUnits;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
volume,
|
||||
volumeUnits,
|
||||
units
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private createdErrorMgs(attributeName: string, isEmpty = false) {
|
||||
private createdErrorMsg(attributeName: string, isEmpty = false) {
|
||||
if (isEmpty) {
|
||||
this.errorsMsg.push(this.translate.instant('widgets.liquid-level-card.attribute-key-not-set', {attributeName}));
|
||||
} else {
|
||||
@ -474,9 +504,14 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (this.settings.layout === LevelCardLayout.absolute) {
|
||||
const volumeInLiters: number = convertLiters(this.volume, this.settings.volumeUnits as CapacityUnits, ConversionType.to);
|
||||
const volume = convertLiters(volumeInLiters, this.widgetUnits as CapacityUnits, ConversionType.from)
|
||||
.toFixed(this.settings.decimals || 0);
|
||||
let volume: number | string;
|
||||
if (this.widgetUnits !== CapacityUnits.percent) {
|
||||
const volumeInLiters: number = convertLiters(this.volume, this.volumeUnits as CapacityUnits, ConversionType.to);
|
||||
volume = convertLiters(volumeInLiters, this.widgetUnits as CapacityUnits, ConversionType.from)
|
||||
.toFixed(this.settings.decimals || 0);
|
||||
} else {
|
||||
volume = this.volume.toFixed(this.settings.decimals || 0);
|
||||
}
|
||||
|
||||
const volumeTextStyle = cssTextFromInlineStyle({...inlineTextStyle(this.settings.volumeFont),
|
||||
color: this.settings.volumeColor});
|
||||
@ -553,7 +588,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
private convertInputData(value: any): number {
|
||||
if (this.settings.datasourceUnits !== CapacityUnits.percent) {
|
||||
return (convertLiters(Number(value), this.settings.datasourceUnits, ConversionType.to) /
|
||||
convertLiters(this.volume, this.settings.volumeUnits, ConversionType.to)) * 100;
|
||||
convertLiters(this.volume, this.volumeUnits as CapacityUnits, ConversionType.to)) * 100;
|
||||
}
|
||||
|
||||
return Number(value);
|
||||
@ -561,7 +596,7 @@ export class LiquidLevelWidgetComponent implements OnInit {
|
||||
|
||||
private convertOutputData(value: number): number {
|
||||
if (this.widgetUnits !== CapacityUnits.percent) {
|
||||
return convertLiters(this.volume * (value / 100), this.settings.volumeUnits, ConversionType.to);
|
||||
return convertLiters(this.volume * (value / 100), this.volumeUnits as CapacityUnits, ConversionType.to);
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
@ -56,6 +56,8 @@ export interface LevelCardWidgetSettings extends WidgetConfig {
|
||||
volumeSource: LiquidWidgetDataSourceType;
|
||||
volumeConstant: number;
|
||||
volumeAttributeName: string;
|
||||
volumeUnitsSource: LiquidWidgetDataSourceType;
|
||||
volumeUnitsAttributeName: string;
|
||||
volumeUnits: CapacityUnits;
|
||||
volumeFont: Font;
|
||||
volumeColor: string;
|
||||
@ -257,8 +259,10 @@ export const levelCardDefaultSettings: LevelCardWidgetSettings = {
|
||||
iconColor: '#5469FF',
|
||||
volumeSource: LiquidWidgetDataSourceType.static,
|
||||
volumeConstant: 500,
|
||||
volumeUnits: CapacityUnits.liters,
|
||||
volumeAttributeName: 'volume',
|
||||
volumeUnitsSource: LiquidWidgetDataSourceType.static,
|
||||
volumeUnitsAttributeName: 'volumeUnits',
|
||||
volumeUnits: CapacityUnits.liters,
|
||||
volumeFont: {
|
||||
family: 'Roboto',
|
||||
size: 14,
|
||||
@ -375,9 +379,7 @@ export const convertLiters = (value: number, units: CapacityUnits, conversionTyp
|
||||
return conversionType === ConversionType.to ? value / factor : value * factor;
|
||||
};
|
||||
|
||||
export const extractValue = <T>(attributes: Array<AttributeData>, attributeName: string): T | undefined => {
|
||||
return attributes.find(attr => attr.key === attributeName)?.value;
|
||||
};
|
||||
export const extractValue = <T>(attributes: Array<AttributeData>, attributeName: string): T | undefined => attributes.find(attr => attr.key === attributeName)?.value;
|
||||
|
||||
export const valueContainerStyleDefaults = cssTextFromInlineStyle({
|
||||
width: '100%',
|
||||
@ -494,6 +496,7 @@ export const updatedFormSettingsValidators = (formGroup: FormGroup) => {
|
||||
const datasourceUnits: string = formGroup.get('datasourceUnits').value;
|
||||
const layout: LevelCardLayout = formGroup.get('layout').value;
|
||||
const volumeSource: LiquidWidgetDataSourceType = formGroup.get('volumeSource').value;
|
||||
const volumeUnitsSource: LiquidWidgetDataSourceType = formGroup.get('volumeUnitsSource').value;
|
||||
const widgetUnitsSource: LiquidWidgetDataSourceType = formGroup.get('widgetUnitsSource').value;
|
||||
const showTooltipLevel: boolean = formGroup.get('showTooltipLevel').value;
|
||||
const showTooltipDate: boolean = formGroup.get('showTooltipDate').value;
|
||||
@ -517,7 +520,7 @@ export const updatedFormSettingsValidators = (formGroup: FormGroup) => {
|
||||
|
||||
if (datasourceUnits !== CapacityUnits.percent) {
|
||||
formGroup.get('volumeSource').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnits').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsSource').enable({emitEvent: false});
|
||||
if (volumeSource === LiquidWidgetDataSourceType.static) {
|
||||
formGroup.get('volumeConstant').enable({emitEvent: false});
|
||||
formGroup.get('volumeAttributeName').disable({emitEvent: false});
|
||||
@ -525,11 +528,20 @@ export const updatedFormSettingsValidators = (formGroup: FormGroup) => {
|
||||
formGroup.get('volumeConstant').disable({emitEvent: false});
|
||||
formGroup.get('volumeAttributeName').enable({emitEvent: false});
|
||||
}
|
||||
if (volumeUnitsSource === LiquidWidgetDataSourceType.static) {
|
||||
formGroup.get('volumeUnits').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsAttributeName').disable({emitEvent: false});
|
||||
} else {
|
||||
formGroup.get('volumeUnits').disable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsAttributeName').enable({emitEvent: false});
|
||||
}
|
||||
} else {
|
||||
formGroup.get('volumeSource').disable({emitEvent: false});
|
||||
formGroup.get('volumeConstant').disable({emitEvent: false});
|
||||
formGroup.get('volumeAttributeName').disable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsSource').disable({emitEvent: false});
|
||||
formGroup.get('volumeUnits').disable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsAttributeName').disable({emitEvent: false});
|
||||
}
|
||||
|
||||
if (layout === LevelCardLayout.simple) {
|
||||
@ -557,7 +569,7 @@ export const updatedFormSettingsValidators = (formGroup: FormGroup) => {
|
||||
}
|
||||
|
||||
formGroup.get('volumeSource').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnits').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsSource').enable({emitEvent: false});
|
||||
if (volumeSource === LiquidWidgetDataSourceType.static) {
|
||||
formGroup.get('volumeConstant').enable({emitEvent: false});
|
||||
formGroup.get('volumeAttributeName').disable({emitEvent: false});
|
||||
@ -565,6 +577,13 @@ export const updatedFormSettingsValidators = (formGroup: FormGroup) => {
|
||||
formGroup.get('volumeConstant').disable({emitEvent: false});
|
||||
formGroup.get('volumeAttributeName').enable({emitEvent: false});
|
||||
}
|
||||
if (volumeUnitsSource === LiquidWidgetDataSourceType.static) {
|
||||
formGroup.get('volumeUnits').enable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsAttributeName').disable({emitEvent: false});
|
||||
} else {
|
||||
formGroup.get('volumeUnits').disable({emitEvent: false});
|
||||
formGroup.get('volumeUnitsAttributeName').enable({emitEvent: false});
|
||||
}
|
||||
|
||||
if (formGroup.get('decimals')) {
|
||||
formGroup.get('decimals').enable({emitEvent: false});
|
||||
|
||||
@ -141,10 +141,30 @@
|
||||
formControlName="volumeAttributeName">
|
||||
</tb-string-autocomplete>
|
||||
</ng-template>
|
||||
<tb-unit-input [tagFilter]="unitsType.capacity"
|
||||
required style="max-width: 25%" class="flex"
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row space-between" [fxShow]="volumeInput">
|
||||
<div class="fixed-title-width tb-required" translate>widgets.liquid-level-card.total-volume-units</div>
|
||||
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
|
||||
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic" style="max-width: 25%">
|
||||
<mat-select formControlName="volumeUnitsSource" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
<mat-option *ngFor="let type of DataSourceTypes" [value]="type">
|
||||
{{ DataSourceTypeTranslations.get(type) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<tb-unit-input *ngIf="levelCardWidgetSettingsForm.get('volumeUnitsSource').value === DataSourceType.static; else selectVolumeUnitsAttributes"
|
||||
class="flex" required
|
||||
[tagFilter]="unitsType.capacity"
|
||||
formControlName="volumeUnits">
|
||||
</tb-unit-input>
|
||||
<ng-template #selectVolumeUnitsAttributes>
|
||||
<tb-string-autocomplete [fetchOptionsFn]="fetchOptions.bind(this)"
|
||||
required style="flex: 1"
|
||||
[errorText]="'widgets.liquid-level-card.attribute-name-required' | translate"
|
||||
formControlName="volumeUnitsAttributeName">
|
||||
</tb-string-autocomplete>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -158,7 +158,9 @@ export class LiquidLevelCardWidgetSettingsComponent extends WidgetSettingsCompon
|
||||
volumeSource: [settings.volumeSource, []],
|
||||
volumeConstant: [settings.volumeConstant, [Validators.required, Validators.min(0.1)]],
|
||||
volumeAttributeName: [settings.volumeAttributeName, [Validators.required]],
|
||||
volumeUnitsSource: [settings.volumeUnitsSource, []],
|
||||
volumeUnits: [settings.volumeUnits, [Validators.required]],
|
||||
volumeUnitsAttributeName: [settings.volumeUnitsAttributeName, [Validators.required]],
|
||||
volumeFont: [settings.volumeFont, []],
|
||||
volumeColor: [settings.volumeColor, []],
|
||||
valueFont: [settings.valueFont, []],
|
||||
@ -195,7 +197,7 @@ export class LiquidLevelCardWidgetSettingsComponent extends WidgetSettingsCompon
|
||||
protected validatorTriggers(): string[] {
|
||||
return [
|
||||
'showBackgroundOverlay', 'showTooltip', 'showTooltipLevel', 'tankSelectionType', 'datasourceUnits',
|
||||
'showTooltipDate', 'layout', 'volumeSource', 'widgetUnitsSource'
|
||||
'showTooltipDate', 'layout', 'volumeSource', 'widgetUnitsSource', 'volumeUnitsSource'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -6241,6 +6241,7 @@
|
||||
"layout": "Layout",
|
||||
"background-overlay": "Value background overlay",
|
||||
"total-volume": "Total volume",
|
||||
"total-volume-units": "Total volume units",
|
||||
"tank": "Tank",
|
||||
"shape": "Shape",
|
||||
"datasource-units": "Source units",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user