Browse Source

UI: Refactoring unit service; Fixed slider widget use unit convertor; add support unit conversion in dynamic form

pull/13282/head
Vladyslav_Prykhodko 1 year ago
parent
commit
ca5b7623b7
  1. 28
      ui-ngx/src/app/core/services/unit.service.ts
  2. 8
      ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts
  3. 21
      ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts
  4. 21
      ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts
  5. 4
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.html
  6. 8
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts
  7. 6
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html
  8. 3
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts
  9. 1
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html
  10. 3
      ui-ngx/src/app/shared/components/convert-unit-settings-panel.component.scss
  11. 18
      ui-ngx/src/app/shared/models/dynamic-form.models.ts
  12. 9
      ui-ngx/src/app/shared/models/widget-settings.models.ts
  13. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

28
ui-ngx/src/app/core/services/unit.service.ts

@ -21,6 +21,8 @@ import {
AllMeasuresUnits,
Converter,
getUnitConverter,
isTbUnitMapping,
TbUnit,
TbUnitConverter,
TbUnitMapping,
UnitInfo,
@ -78,15 +80,18 @@ export class UnitService {
return this.converter.getDefaultUnit(measure, unitSystem);
}
geUnitConverter(unit: TbUnitMapping): TbUnitConverter;
geUnitConverter(unit: TbUnit): TbUnitConverter;
geUnitConverter(from: string, to: string): TbUnitConverter;
geUnitConverter(unit: TbUnitMapping | string, to?: string): TbUnitConverter {
geUnitConverter(unit: TbUnit, to?: string): TbUnitConverter {
try {
if (unit !== null && typeof unit === 'object') {
if (isTbUnitMapping(unit)) {
const target = this.getTargetUnitSymbol(unit);
return this.converter.getUnitConverter(unit.from, target);
return this.converter.getUnitConverter((unit as TbUnitMapping).from, target);
}
return this.converter.getUnitConverter(unit as string, to);
if (isNotEmptyStr(to)) {
return this.converter.getUnitConverter(unit as string, to);
}
return (x: number) => x;
} catch (e) {
console.warn(e);
return (x: number) => x;
@ -100,15 +105,18 @@ export class UnitService {
return typeof unit === 'string' ? unit : null;
}
convertUnitValue(value: number, unit: TbUnitMapping): number;
convertUnitValue(value: number, unit: TbUnit): number;
convertUnitValue(value: number, from: string, to: string): number;
convertUnitValue(value: number, unit: string | TbUnitMapping, to?: string): number {
convertUnitValue(value: number, unit: TbUnit, to?: string): number {
try {
if (unit !== null && typeof unit === 'object') {
if (isTbUnitMapping(unit)) {
const target = this.getTargetUnitSymbol(unit);
return this.converter.convert(value, unit.from, target);
return this.converter.convert(value, (unit as TbUnitMapping).from, target);
}
return this.converter.convert(value, unit as string, to);
if (isNotEmptyStr(to)) {
return this.converter.convert(value, unit as string, to);
}
return value;
} catch (e) {
console.warn(e);
return value;

8
ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts

@ -48,7 +48,7 @@ import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart';
import { WidgetComponent } from '@home/components/widget/widget.component';
import { isTbUnitMapping, TbUnitMapping } from '@shared/models/unit.models';
import { TbUnitConverter } from '@shared/models/unit.models';
import { UnitService } from '@core/services/unit.service';
@Component({
@ -80,7 +80,7 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn
private decimals = 0;
private units: string = '';
private unitConvertor = (x: number) => x;
private unitConvertor: TbUnitConverter;
private rangeItems: RangeItem[];
@ -111,9 +111,7 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn
dataKey.settings = rangeChartTimeSeriesKeySettings(this.settings);
}
this.units = unitService.getTargetUnitSymbol(units);
if (isTbUnitMapping(units)) {
this.unitConvertor = unitService.geUnitConverter(units as unknown as TbUnitMapping);
}
this.unitConvertor = unitService.geUnitConverter(units);
this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer);
this.overlayStyle = overlayStyle(this.settings.background.overlay);

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

@ -83,7 +83,7 @@ import {
TimeSeriesChartTooltipValueFormatFunction
} from '@home/components/widget/lib/chart/time-series-chart-tooltip.models';
import { UnitService } from '@core/services/unit.service';
import { isNotEmptyTbUnits, isTbUnitMapping, TbUnit, TbUnitMapping } from '@shared/models/unit.models';
import { isNotEmptyTbUnits, TbUnit } from '@shared/models/unit.models';
export class TbTimeSeriesChart {
@ -420,10 +420,7 @@ export class TbTimeSeriesChart {
const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === dataKey) : null;
const units: TbUnit = isNotEmptyTbUnits(dataKey.units) ? dataKey.units : this.ctx.units;
const unitSymbol = this.unitService.getTargetUnitSymbol(units);
let unitConvertor: (value: number) => number;
if (isTbUnitMapping(units)) {
unitConvertor = this.unitService.geUnitConverter(units as unknown as TbUnitMapping);
}
const unitConvertor = this.unitService.geUnitConverter(units);
const data = datasourceData?.data ?
toTimeSeriesChartDataSet(datasourceData.data, this.stateValueConverter?.valueConverter ?? unitConvertor) : [];
const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals :
@ -467,12 +464,9 @@ export class TbTimeSeriesChart {
let latestDataKey: DataKey = null;
let entityDataKey: DataKey = null;
let value = null;
const units: TbUnit = isNotEmptyTbUnits(threshold.units) ? threshold.units : this.ctx.units;
const units = isNotEmptyTbUnits(threshold.units) ? threshold.units : this.ctx.units;
const unitSymbol = this.unitService.getTargetUnitSymbol(units);
let unitConvertor: (value: number) => number;
if (isTbUnitMapping(units)) {
unitConvertor = this.unitService.geUnitConverter(units as unknown as TbUnitMapping);
}
const unitConvertor = this.unitService.geUnitConverter(units);
if (threshold.type === ValueSourceType.latestKey) {
if (this.ctx.datasources.length) {
for (const datasource of this.ctx.datasources) {
@ -558,12 +552,9 @@ export class TbTimeSeriesChart {
for (const yAxisSettings of yAxisSettingsList) {
const axisSettings = mergeDeep<TimeSeriesChartYAxisSettings>({} as TimeSeriesChartYAxisSettings,
defaultTimeSeriesChartYAxisSettings, yAxisSettings);
const units: TbUnit = isNotEmptyTbUnits(axisSettings.units) ? axisSettings.units : this.ctx.units;
const units = isNotEmptyTbUnits(axisSettings.units) ? axisSettings.units : this.ctx.units;
const unitSymbol = this.unitService.getTargetUnitSymbol(units);
let unitConvertor: (value: number) => number = (x) => x;
if (isTbUnitMapping(units)) {
unitConvertor = this.unitService.geUnitConverter(units as unknown as TbUnitMapping);
}
const unitConvertor = this.unitService.geUnitConverter(units);
const decimals = isDefinedAndNotNull(axisSettings.decimals) ? axisSettings.decimals :
(isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2);
if (this.stateValueConverter) {

21
ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts

@ -60,7 +60,13 @@ import { TranslateService } from '@ngx-translate/core';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser';
import { DataEntry } from '@shared/models/widget.models';
import { getSourceTbUnitSymbol, isNotEmptyTbUnits, isTbUnitMapping, TbUnit } from '@shared/models/unit.models';
import {
getSourceTbUnitSymbol,
isNotEmptyTbUnits,
isTbUnitMapping,
TbUnit,
TbUnitConverter
} from '@shared/models/unit.models';
import { UnitService } from '@core/services/unit.service';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
@ -110,10 +116,10 @@ export class LiquidLevelWidgetComponent implements OnInit {
private tooltipContent: string;
private widgetUnits: TbUnit;
private widgetUnitsSymbol: string;
private widgetUnitsConvertor = (x: number) => x;
private widgetUnitsConvertor: TbUnitConverter;
private volumeUnits: string;
private tooltipUnitSymbol: string;
private tooltipUnitConvertor = (x: number) => x;
private tooltipUnitConvertor: TbUnitConverter;
private capacityUnits = Object.values(CapacityUnits);
@ -164,14 +170,11 @@ export class LiquidLevelWidgetComponent implements OnInit {
}
this.widgetUnitsSymbol = this.unitService.getTargetUnitSymbol(this.widgetUnits);
if (isTbUnitMapping(this.widgetUnits)) {
this.widgetUnitsConvertor = this.unitService.geUnitConverter(this.widgetUnits as any);
}
this.widgetUnitsConvertor = this.unitService.geUnitConverter(this.widgetUnits);
this.tooltipUnitSymbol = this.unitService.getTargetUnitSymbol(this.settings.tooltipUnits);
if (isTbUnitMapping(this.settings.tooltipUnits)) {
this.tooltipUnitConvertor = this.unitService.geUnitConverter(this.settings.tooltipUnits as any);
}
this.tooltipUnitConvertor = this.unitService.geUnitConverter(this.settings.tooltipUnits);
this.update(true);
}
});

4
ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.html

@ -42,10 +42,10 @@
</mat-slider>
<div *ngIf="showTicks" class="tb-slider-ticks" [style]="ticksStyle">
<div #sliderTickMinContainer>
<div #sliderTickMin>{{ settings.tickMin }}</div>
<div #sliderTickMin>{{ tickMinText }}</div>
</div>
<div #sliderTickMaxContainer>
<div #sliderTickMax>{{ settings.tickMax }}</div>
<div #sliderTickMax>{{ tickMaxText }}</div>
</div>
</div>
</div>

8
ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.component.ts

@ -47,6 +47,7 @@ import {
import { isDefinedAndNotNull, isNumeric } from '@core/utils';
import { WidgetComponent } from '@home/components/widget/widget.component';
import tinycolor from 'tinycolor2';
import { UnitService } from '@core/services/unit.service';
@Component({
selector: 'tb-slider-widget',
@ -115,6 +116,8 @@ export class SliderWidgetComponent extends
showTicks = true;
ticksStyle: ComponentStyle = {};
tickMinText: number;
tickMaxText: number;
sliderStep: number = undefined;
@ -137,7 +140,8 @@ export class SliderWidgetComponent extends
private utils: UtilsService,
private widgetComponent: WidgetComponent,
protected cd: ChangeDetectorRef,
private elementRef: ElementRef) {
private elementRef: ElementRef,
private unitService: UnitService) {
super(cd);
}
@ -180,6 +184,8 @@ export class SliderWidgetComponent extends
if (this.showTicks) {
this.ticksStyle = textStyle(this.settings.ticksFont);
this.ticksStyle.color = this.settings.ticksColor;
this.tickMinText = this.unitService.convertUnitValue(this.settings.tickMin, this.settings.valueUnits);
this.tickMaxText = this.unitService.convertUnitValue(this.settings.tickMax, this.settings.valueUnits);
}
if (this.settings.showTickMarks) {

6
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.html

@ -380,6 +380,11 @@
</mat-radio-button>
</mat-radio-group>
</div>
<div *ngIf="propertyItemType === FormPropertyType.units" class="tb-form-row space-between">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="supportsUnitConversion">
{{ 'dynamic-form.property.support-unit-conversion' | translate }}
</mat-slide-toggle>
</div>
<div *ngIf="isPropertyTypeAllowedForRow(propertyItemType)" class="tb-form-row space-between">
<div class="fixed-title-width" translate>dynamic-form.property.default-value</div>
<mat-form-field *ngIf="[FormPropertyType.text, FormPropertyType.password].includes(propertyItemType)"
@ -412,6 +417,7 @@
disabledLineHeight>
</tb-font-settings>
<tb-unit-input *ngIf="propertyItemType === FormPropertyType.units"
[supportsUnitConversion]="propertyFormGroup.get('supportsUnitConversion').value"
formControlName="default"></tb-unit-input>
<tb-value-input *ngIf="propertyItemType === FormPropertyType.switch"
[valueType]="ValueType.BOOLEAN"

3
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form-property-panel.component.ts

@ -132,7 +132,8 @@ export class DynamicFormPropertyPanelComponent implements OnInit {
allowClear: [this.property.allowClear || true, []],
dateTimeType: [this.property.dateTimeType || 'datetime', []],
htmlContent: [this.property.htmlContent || '', []],
htmlClassList: [this.property.htmlClassList || [], []]
htmlClassList: [this.property.htmlClassList || [], []],
supportsUnitConversion: [this.property.supportsUnitConversion ?? false]
}
);
if (this.disabled) {

1
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/dynamic-form/dynamic-form.component.html

@ -123,6 +123,7 @@
<tb-unit-input *ngIf="property.type === FormPropertyType.units"
[class]="property.fieldClass"
[required]="property.required"
[supportsUnitConversion]="property.supportsUnitConversion"
formControlName="{{ property.id }}"></tb-unit-input>
<tb-material-icon-select *ngIf="property.type === FormPropertyType.icon"
[required]="property.required"

3
ui-ngx/src/app/shared/components/convert-unit-settings-panel.component.scss

@ -20,7 +20,8 @@
display: flex;
flex-direction: column;
gap: 16px;
@media #{$mat-lt-md} {
max-height: calc(100vh - 24px);
@media #{$mat-xs} {
width: 90vw;
}
.tb-convert-settings-title {

18
ui-ngx/src/app/shared/models/dynamic-form.models.ts

@ -162,8 +162,13 @@ export interface FormHtmlSection extends FormPropertyBase {
htmlContent?: string;
}
export interface FormUnitProperty extends FormPropertyBase {
supportsUnitConversion?: boolean;
}
export type FormProperty = FormPropertyBase & FormTextareaProperty & FormNumberProperty & FormSelectProperty & FormRadiosProperty
& FormDateTimeProperty & FormJavascriptProperty & FormMarkdownProperty & FormFieldSetProperty & FormArrayProperty & FormHtmlSection;
& FormDateTimeProperty & FormJavascriptProperty & FormMarkdownProperty & FormFieldSetProperty & FormArrayProperty & FormHtmlSection
& FormUnitProperty;
export const cleanupFormProperties = (properties: FormProperty[]): FormProperty[] => {
for (const property of properties) {
@ -213,6 +218,9 @@ export const cleanupFormProperty = (property: FormProperty): FormProperty => {
delete property.htmlClassList;
delete property.htmlContent;
}
if (property.type !== FormPropertyType.units) {
delete property.supportsUnitConversion;
}
for (const key of Object.keys(property)) {
const val = property[key];
if (isUndefinedOrNull(val) || isEmptyStr(val)) {
@ -276,9 +284,9 @@ export const toPropertyGroups = (properties: FormProperty[],
customTranslate: CustomTranslatePipe,
sanitizer: DomSanitizer): FormPropertyGroup[] => {
const groups: {title: string, properties: FormProperty[]}[] = [];
for (let property of properties) {
for (const property of properties) {
if (!property.group) {
let group = groups.length ? groups[groups.length - 1] : null;
const group = groups.length ? groups[groups.length - 1] : null;
if (group && !group.title) {
group.properties.push(property);
} else {
@ -311,7 +319,7 @@ const toPropertyContainers = (properties: FormProperty[],
customTranslate: CustomTranslatePipe,
sanitizer: DomSanitizer): FormPropertyContainer[] => {
const result: FormPropertyContainer[] = [];
for (let property of properties) {
for (const property of properties) {
if (property.type === FormPropertyType.array) {
const propertyArray: FormPropertyArray = {
property,
@ -382,7 +390,7 @@ const toPropertyContainers = (properties: FormProperty[],
}
}
}
for (let container of result.filter(c =>
for (const container of result.filter(c =>
c.type === FormPropertyContainerType.row && !c.switch && c.properties?.length === 1)) {
const property = container.properties[0];
if (isInputFieldPropertyType(property.type)) {

9
ui-ngx/src/app/shared/models/widget-settings.models.ts

@ -54,7 +54,7 @@ import {
WidgetSubscriptionOptions
} from '@core/api/widget-api.models';
import { UnitService } from '@core/services/unit.service';
import { TbUnit, TbUnitConverter, TbUnitMapping } from '@shared/models/unit.models';
import { TbUnit, TbUnitConverter } from '@shared/models/unit.models';
export type ComponentStyle = {[klass: string]: any};
@ -932,7 +932,7 @@ export class UnitConverterValueFormatProcessor extends ValueFormatProcessor {
protected settings: ValueFormatSettings) {
super($injector, settings);
const unitService = this.$injector.get(UnitService);
const unit = settings.units as TbUnitMapping;
const unit = settings.units;
this.unitSymbol = settings.ignoreUnitSymbol ? null : unitService.getTargetUnitSymbol(unit);
this.unitConverter = unitService.geUnitConverter(unit);
@ -942,10 +942,7 @@ export class UnitConverterValueFormatProcessor extends ValueFormatProcessor {
format(value: any): string {
if (isDefinedAndNotNull(value) && isNumeric(value)) {
let formatted = Number(value);
if (this.unitConverter) {
formatted = this.unitConverter(value);
}
const formatted = this.unitConverter(Number(value));
return this.formatValue(formatted);
}
return value ?? '';

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

@ -1790,7 +1790,8 @@
"array-item": "Array item",
"item-type": "Item type",
"item-name": "Item name",
"no-items": "No items"
"no-items": "No items",
"support-unit-conversion": "Support unit conversion"
},
"clear-form": "Clear form",
"clear-form-prompt": "Are you sure you want to remove all form properties?",

Loading…
Cancel
Save