UI: Refactoring after review

This commit is contained in:
Vladyslav_Prykhodko 2025-05-16 14:01:44 +03:00
parent be4407c3ca
commit 8b14e72f8c
12 changed files with 137 additions and 131 deletions

View File

@ -33,7 +33,6 @@ import { svgIcons, svgIconsUrl } from '@shared/models/icon.models';
import { ActionSettingsChangeLanguage } from '@core/settings/settings.actions'; import { ActionSettingsChangeLanguage } from '@core/settings/settings.actions';
import { SETTINGS_KEY } from '@core/settings/settings.effects'; import { SETTINGS_KEY } from '@core/settings/settings.effects';
import { initCustomJQueryEvents } from '@shared/models/jquery-event.models'; import { initCustomJQueryEvents } from '@shared/models/jquery-event.models';
import { UnitService } from '@core/services/unit.service';
@Component({ @Component({
selector: 'tb-root', selector: 'tb-root',
@ -47,8 +46,7 @@ export class AppComponent {
private translate: TranslateService, private translate: TranslateService,
private matIconRegistry: MatIconRegistry, private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer, private domSanitizer: DomSanitizer,
private authService: AuthService, private authService: AuthService) {
private unitService: UnitService) {
console.log(`ThingsBoard Version: ${env.tbVersion}`); console.log(`ThingsBoard Version: ${env.tbVersion}`);
@ -96,14 +94,12 @@ export class AppComponent {
this.store.select(selectUserReady).pipe( this.store.select(selectUserReady).pipe(
filter((data) => data.isUserLoaded), filter((data) => data.isUserLoaded),
tap((data) => { tap((data) => {
const userDetails = getCurrentAuthState(this.store).userDetails; let userLang = getCurrentAuthState(this.store).userDetails?.additionalInfo?.lang ?? null;
let userLang = userDetails?.additionalInfo?.lang ?? null;
if (!userLang && !data.isAuthenticated) { if (!userLang && !data.isAuthenticated) {
const settings = this.storageService.getItem(SETTINGS_KEY); const settings = this.storageService.getItem(SETTINGS_KEY);
userLang = settings?.userLang ?? null; userLang = settings?.userLang ?? null;
} }
this.notifyUserLang(userLang); this.notifyUserLang(userLang);
this.unitService.setUnitSystem(userDetails?.additionalInfo?.unitSystem);
}), }),
skip(1), skip(1),
).subscribe((data) => { ).subscribe((data) => {

View File

@ -62,10 +62,11 @@ import { AlarmDataService } from '@core/api/alarm-data.service';
import { IDashboardController } from '@home/components/dashboard-page/dashboard-page.models'; import { IDashboardController } from '@home/components/dashboard-page/dashboard-page.models';
import { PopoverPlacement } from '@shared/components/popover.models'; import { PopoverPlacement } from '@shared/components/popover.models';
import { PersistentRpc } from '@shared/models/rpc.models'; import { PersistentRpc } from '@shared/models/rpc.models';
import { EventEmitter, Injector } from '@angular/core'; import { EventEmitter } from '@angular/core';
import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { TbUnit } from '@shared/models/unit.models'; import { TbUnit } from '@shared/models/unit.models';
import { UnitService } from '@core/services/unit.service';
export interface TimewindowFunctions { export interface TimewindowFunctions {
onUpdateTimewindow: (startTimeMs: number, endTimeMs: number, interval?: number) => void; onUpdateTimewindow: (startTimeMs: number, endTimeMs: number, interval?: number) => void;
@ -234,8 +235,8 @@ export class WidgetSubscriptionContext {
utils: UtilsService; utils: UtilsService;
dashboardUtils: DashboardUtilsService; dashboardUtils: DashboardUtilsService;
raf: RafService; raf: RafService;
unitService: UnitService;
widgetUtils: IWidgetUtils; widgetUtils: IWidgetUtils;
$injector: Injector;
getServerTimeDiff: () => Observable<number>; getServerTimeDiff: () => Observable<number>;
} }

View File

@ -1419,7 +1419,7 @@ export class WidgetSubscription implements IWidgetSubscription {
if (this.displayLegend) { if (this.displayLegend) {
const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : this.decimals; const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : this.decimals;
const units = isNotEmptyTbUnits(dataKey.units) ? dataKey.units : this.units; const units = isNotEmptyTbUnits(dataKey.units) ? dataKey.units : this.units;
const valueFormat = ValueFormatProcessor.fromSettings(this.ctx.$injector, {decimals, units}) const valueFormat = ValueFormatProcessor.fromSettings(this.ctx.unitService, {decimals, units})
const legendKey: LegendKey = { const legendKey: LegendKey = {
dataKey, dataKey,
dataIndex: dataKeyIndex, dataIndex: dataKeyIndex,

View File

@ -32,6 +32,10 @@ import {
import { isNotEmptyStr, isObject } from '@core/utils'; import { isNotEmptyStr, isObject } from '@core/utils';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { selectAuth, selectIsAuthenticated } from '@core/auth/auth.selectors';
import { filter, switchMap, take } from 'rxjs/operators';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -41,12 +45,19 @@ export class UnitService {
private currentUnitSystem: UnitSystem = UnitSystem.METRIC; private currentUnitSystem: UnitSystem = UnitSystem.METRIC;
private converter: Converter; private converter: Converter;
constructor(private translate: TranslateService) { constructor(private translate: TranslateService,
private store: Store<AppState>) {
this.translate.onLangChange.pipe( this.translate.onLangChange.pipe(
takeUntilDestroyed() takeUntilDestroyed()
).subscribe(() => { ).subscribe(() => {
this.converter = getUnitConverter(this.translate); this.converter = getUnitConverter(this.translate);
}); });
this.store.select(selectIsAuthenticated).pipe(
filter((data) => data),
switchMap(() => this.store.select(selectAuth).pipe(take(1)))
).subscribe((data) => {
this.setUnitSystem(data.userDetails?.additionalInfo?.unitSystem)
})
} }
getUnitSystem(): UnitSystem { getUnitSystem(): UnitSystem {
@ -65,8 +76,8 @@ export class UnitService {
return this.converter?.listUnits(measure, unitSystem); return this.converter?.listUnits(measure, unitSystem);
} }
getUnitsGroupedByMeasure(measure?: AllMeasures, unitSystem?: UnitSystem): UnitInfoGroupByMeasure<AllMeasures> { getUnitsGroupedByMeasure(measure?: AllMeasures, unitSystem?: UnitSystem, tagFilter?: string): UnitInfoGroupByMeasure<AllMeasures> {
return this.converter?.unitsGroupByMeasure(measure, unitSystem); return this.converter?.unitsGroupByMeasure(measure, unitSystem, tagFilter);
} }
getUnitInfo(symbol: AllMeasuresUnits | string): UnitInfo { getUnitInfo(symbol: AllMeasuresUnits | string): UnitInfo {

View File

@ -48,7 +48,7 @@
</mat-form-field> </mat-form-field>
<div class="tb-units-field"> <div class="tb-units-field">
<tb-unit-input <tb-unit-input
[supportsUnitConversion]="supportsUnitConversion" supportsUnitConversion
formControlName="units"> formControlName="units">
</tb-unit-input> </tb-unit-input>
</div> </div>

View File

@ -118,10 +118,6 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
return this.widgetConfigComponent.modelValue?.latestDataKeySettingsDirective; return this.widgetConfigComponent.modelValue?.latestDataKeySettingsDirective;
} }
get supportsUnitConversion(): boolean {
return this.widgetConfigComponent.modelValue?.typeParameters?.supportsUnitConversion ?? false;
}
private propagateChange = (_val: any) => {}; private propagateChange = (_val: any) => {};
constructor(private fb: UntypedFormBuilder, constructor(private fb: UntypedFormBuilder,
@ -220,7 +216,7 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
hideDataKeyName: true, hideDataKeyName: true,
hideDataKeyLabel: true, hideDataKeyLabel: true,
hideDataKeyColor: true, hideDataKeyColor: true,
supportsUnitConversion: this.supportsUnitConversion supportsUnitConversion: true
} }
}).afterClosed().subscribe((updatedDataKey) => { }).afterClosed().subscribe((updatedDataKey) => {
if (updatedDataKey) { if (updatedDataKey) {

View File

@ -100,7 +100,7 @@
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div translate>widget-config.units-short</div> <div translate>widget-config.units-short</div>
<tb-unit-input <tb-unit-input
supportsUnitConversion="" supportsUnitConversion
formControlName="units"> formControlName="units">
</tb-unit-input> </tb-unit-input>
</div> </div>

View File

@ -84,7 +84,7 @@
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div translate>widget-config.units-short</div> <div translate>widget-config.units-short</div>
<tb-unit-input <tb-unit-input
supportsUnitConversion="" supportsUnitConversion
formControlName="units"> formControlName="units">
</tb-unit-input> </tb-unit-input>
</div> </div>

View File

@ -105,6 +105,7 @@ import { ExceptionData } from '@shared/models/error.models';
import { WidgetComponentService } from './widget-component.service'; import { WidgetComponentService } from './widget-component.service';
import { Timewindow } from '@shared/models/time/time.models'; import { Timewindow } from '@shared/models/time/time.models';
import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service';
import { UnitService } from '@core/services/unit.service';
import { DashboardService } from '@core/http/dashboard.service'; import { DashboardService } from '@core/http/dashboard.service';
import { WidgetSubscription } from '@core/api/widget-subscription'; import { WidgetSubscription } from '@core/api/widget-subscription';
import { EntityService } from '@core/http/entity.service'; import { EntityService } from '@core/http/entity.service';
@ -216,6 +217,7 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
private dashboardUtils: DashboardUtilsService, private dashboardUtils: DashboardUtilsService,
private mobileService: MobileService, private mobileService: MobileService,
private raf: RafService, private raf: RafService,
private unitService: UnitService,
private ngZone: NgZone, private ngZone: NgZone,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private http: HttpClient) { private http: HttpClient) {
@ -341,8 +343,8 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
this.subscriptionContext.utils = this.utils; this.subscriptionContext.utils = this.utils;
this.subscriptionContext.dashboardUtils = this.dashboardUtils; this.subscriptionContext.dashboardUtils = this.dashboardUtils;
this.subscriptionContext.raf = this.raf; this.subscriptionContext.raf = this.raf;
this.subscriptionContext.unitService = this.unitService;
this.subscriptionContext.widgetUtils = this.widgetContext.utils; this.subscriptionContext.widgetUtils = this.widgetContext.utils;
this.subscriptionContext.$injector = this.injector;
this.subscriptionContext.getServerTimeDiff = this.dashboardService.getServerTimeDiff.bind(this.dashboardService); this.subscriptionContext.getServerTimeDiff = this.dashboardService.getServerTimeDiff.bind(this.dashboardService);
this.widgetComponentService.getWidgetInfo(this.widget.typeFullFqn).subscribe({ this.widgetComponentService.getWidgetInfo(this.widget.typeFullFqn).subscribe({

View File

@ -34,7 +34,9 @@ import { Observable, of, shareReplay } from 'rxjs';
import { import {
AllMeasures, AllMeasures,
getSourceTbUnitSymbol, getSourceTbUnitSymbol,
getTbUnitFromSearch,
isTbUnitMapping, isTbUnitMapping,
searchUnit,
TbUnit, TbUnit,
UnitInfo, UnitInfo,
UnitSystem UnitSystem
@ -43,7 +45,7 @@ import { map, mergeMap } from 'rxjs/operators';
import { UnitService } from '@core/services/unit.service'; import { UnitService } from '@core/services/unit.service';
import { TbPopoverService } from '@shared/components/popover.service'; import { TbPopoverService } from '@shared/components/popover.service';
import { UnitSettingsPanelComponent } from '@shared/components/unit-settings-panel.component'; import { UnitSettingsPanelComponent } from '@shared/components/unit-settings-panel.component';
import { isDefinedAndNotNull, isEqual, isNotEmptyStr } from '@core/utils'; import { isDefinedAndNotNull, isEqual } from '@core/utils';
@Component({ @Component({
selector: 'tb-unit-input', selector: 'tb-unit-input',
@ -200,7 +202,7 @@ export class UnitInputComponent implements ControlValueAccessor, OnInit, OnChang
hostView: this.viewContainerRef, hostView: this.viewContainerRef,
preferredPlacement: ['left', 'bottom', 'top'], preferredPlacement: ['left', 'bottom', 'top'],
context: { context: {
unit: this.extractTbUnit(this.unitsFormControl.value), unit: getTbUnitFromSearch(this.unitsFormControl.value),
required: this.required, required: this.required,
disabled: this.disabled, disabled: this.disabled,
tagFilter: this.tagFilter, tagFilter: this.tagFilter,
@ -217,7 +219,7 @@ export class UnitInputComponent implements ControlValueAccessor, OnInit, OnChang
} }
private updateModel(value: UnitInfo | TbUnit ) { private updateModel(value: UnitInfo | TbUnit ) {
let res = this.extractTbUnit(value); let res = getTbUnitFromSearch(value);
if (this.onlySystemUnits && !isTbUnitMapping(res)) { if (this.onlySystemUnits && !isTbUnitMapping(res)) {
const unitInfo = this.unitService.getUnitInfo(res as string); const unitInfo = this.unitService.getUnitInfo(res as string);
if (unitInfo) { if (unitInfo) {
@ -238,106 +240,17 @@ export class UnitInputComponent implements ControlValueAccessor, OnInit, OnChang
private fetchUnits(searchText?: string): Observable<Array<[AllMeasures, Array<UnitInfo>]>> { private fetchUnits(searchText?: string): Observable<Array<[AllMeasures, Array<UnitInfo>]>> {
this.searchText = searchText; this.searchText = searchText;
return this.getGroupedUnits().pipe( return this.getGroupedUnits().pipe(
map(unit => this.searchUnit(unit, searchText)) map(unit => searchUnit(unit, searchText))
); );
} }
private getGroupedUnits(): Observable<Array<[AllMeasures, Array<UnitInfo>]>> { private getGroupedUnits(): Observable<Array<[AllMeasures, Array<UnitInfo>]>> {
if (this.fetchUnits$ === null) { if (this.fetchUnits$ === null) {
this.fetchUnits$ = of(this.unitService.getUnitsGroupedByMeasure(this.measure, this.unitSystem)).pipe( this.fetchUnits$ = of(this.unitService.getUnitsGroupedByMeasure(this.measure, this.unitSystem, this.tagFilter)).pipe(
map(data => { map(data => Object.entries(data) as Array<[AllMeasures, UnitInfo[]]>),
let objectData = Object.entries(data) as Array<[AllMeasures, UnitInfo[]]>;
if (this.tagFilter) {
objectData = objectData
.map((measure) => [measure[0], measure[1].filter(u => u.tags.includes(this.tagFilter))] as [AllMeasures, UnitInfo[]])
.filter((measure) => measure[1].length > 0);
}
return objectData;
}),
shareReplay(1) shareReplay(1)
); );
} }
return this.fetchUnits$; return this.fetchUnits$;
} }
private searchUnit(units: Array<[AllMeasures, Array<UnitInfo>]>, searchText?: string): Array<[AllMeasures, Array<UnitInfo>]> {
if (isNotEmptyStr(searchText)) {
const filterValue = searchText.trim().toUpperCase();
const scoredGroups = units
.map(([measure, unitInfos]) => {
const scoredUnits = unitInfos
.map(unit => ({
unit,
score: this.calculateRelevanceScore(unit, filterValue)
}))
.filter(({ score }) => score > 0)
.sort((a, b) => b.score - a.score)
.map(({ unit }) => unit);
let groupScore = scoredUnits.length > 0
? Math.max(...scoredUnits.map(unit => this.calculateRelevanceScore(unit, filterValue)))
: 0;
if (measure.toUpperCase() === filterValue) {
groupScore += 200;
}
return { measure, units: scoredUnits, groupScore };
})
.filter(group => group.units.length > 0)
.sort((a, b) => {
if (b.groupScore !== a.groupScore) {
return b.groupScore - a.groupScore;
}
return b.units.length - a.units.length;
});
return scoredGroups.map(group => [group.measure, group.units] as [AllMeasures, Array<UnitInfo>]);
}
return units;
}
private calculateRelevanceScore(unit: UnitInfo, filterValue: string): number {
const name = unit.name.toUpperCase();
const abbr = unit.abbr.toUpperCase();
const tags = unit.tags.map(tag => tag.toUpperCase());
let score = 0;
if (name === filterValue || abbr === filterValue) {
score += 100;
} else if (tags.includes(filterValue)) {
score += 80;
} else if (name.startsWith(filterValue) || abbr.startsWith(filterValue)) {
score += 60;
} else if (tags.some(tag => tag.startsWith(filterValue))) {
score += 50;
} else if (tags.some(tag => tag.includes(filterValue))) {
score += 30;
}
if (score > 0) {
score += Math.max(0, 10 - (name.length + abbr.length) / 2);
}
return score;
}
private extractTbUnit(value: TbUnit | UnitInfo | null): TbUnit {
if (value === null) {
return null;
}
if (value === undefined) {
return undefined;
}
if (typeof value === 'string') {
return value;
}
if ('abbr' in value) {
return value.abbr;
}
return value;
}
} }

View File

@ -104,7 +104,7 @@ import voltage, { VoltageUnits } from '@shared/models/units/voltage';
import volume, { VolumeUnits } from '@shared/models/units/volume'; import volume, { VolumeUnits } from '@shared/models/units/volume';
import volumeFlow, { VolumeFlowUnits } from '@shared/models/units/volume-flow'; import volumeFlow, { VolumeFlowUnits } from '@shared/models/units/volume-flow';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { isNotEmptyStr } from '@core/utils'; import { deepClone, isNotEmptyStr } from '@core/utils';
export type AllMeasuresUnits = export type AllMeasuresUnits =
| AbsorbedDoseRateUnits | AbsorbedDoseRateUnits
@ -548,7 +548,7 @@ export class Converter {
return results; return results;
} }
unitsGroupByMeasure(measureName?: AllMeasures, unitSystem?: UnitSystem): UnitInfoGroupByMeasure<AllMeasures> { unitsGroupByMeasure(measureName?: AllMeasures, unitSystem?: UnitSystem, tagFilter?: string): UnitInfoGroupByMeasure<AllMeasures> {
const results: UnitInfoGroupByMeasure<AllMeasures> = {}; const results: UnitInfoGroupByMeasure<AllMeasures> = {};
const measures = measureName const measures = measureName
@ -573,9 +573,15 @@ export class Converter {
} }
for (const abbr of Object.keys(units) as AllMeasuresUnits[]) { for (const abbr of Object.keys(units) as AllMeasuresUnits[]) {
results[name].push(this.describe(abbr)); const unitInfo = this.describe(abbr);
if (!tagFilter || unitInfo.tags.includes(tagFilter)) {
results[name].push(unitInfo);
}
} }
} }
if (!results[name].length) {
delete results[name];
}
} }
return results; return results;
} }
@ -641,7 +647,7 @@ function buildUnitCache(measures: Record<AllMeasures, TbMeasure<AllMeasuresUnits
} }
export function getUnitConverter(translate: TranslateService): Converter { export function getUnitConverter(translate: TranslateService): Converter {
const unitCache = buildUnitCache(allMeasures, translate); const unitCache = buildUnitCache(deepClone(allMeasures), translate);
return new Converter(allMeasures, unitCache); return new Converter(allMeasures, unitCache);
} }
@ -669,3 +675,84 @@ export const isTbUnitMapping = (unit: any): boolean => {
if (typeof unit !== 'object' || unit === null) return false; if (typeof unit !== 'object' || unit === null) return false;
return isNotEmptyStr(unit.from); return isNotEmptyStr(unit.from);
}; };
export const searchUnit =
(units: Array<[AllMeasures, Array<UnitInfo>]>, searchText?: string): Array<[AllMeasures, Array<UnitInfo>]> => {
if (isNotEmptyStr(searchText)) {
const filterValue = searchText.trim().toUpperCase();
const scoredGroups = units
.map(([measure, unitInfos]) => {
const scoredUnits = unitInfos
.map(unit => ({
unit,
score: calculateRelevanceScore(unit, filterValue)
}))
.filter(({score}) => score > 0)
.sort((a, b) => b.score - a.score)
.map(({unit}) => unit);
let groupScore = scoredUnits.length > 0
? Math.max(...scoredUnits.map(unit => calculateRelevanceScore(unit, filterValue)))
: 0;
if (measure.toUpperCase() === filterValue) {
groupScore += 200;
}
return {measure, units: scoredUnits, groupScore};
})
.filter(group => group.units.length > 0)
.sort((a, b) => {
if (b.groupScore !== a.groupScore) {
return b.groupScore - a.groupScore;
}
return b.units.length - a.units.length;
});
return scoredGroups.map(group => [group.measure, group.units] as [AllMeasures, Array<UnitInfo>]);
}
return units;
}
function calculateRelevanceScore (unit: UnitInfo, filterValue: string): number{
const name = unit.name.toUpperCase();
const abbr = unit.abbr.toUpperCase();
const tags = unit.tags.map(tag => tag.toUpperCase());
let score = 0;
if (name === filterValue || abbr === filterValue) {
score += 100;
} else if (tags.includes(filterValue)) {
score += 80;
} else if (name.startsWith(filterValue) || abbr.startsWith(filterValue)) {
score += 60;
} else if (tags.some(tag => tag.startsWith(filterValue))) {
score += 50;
} else if (tags.some(tag => tag.includes(filterValue))) {
score += 30;
}
if (score > 0) {
score += Math.max(0, 10 - (name.length + abbr.length) / 2);
}
return score;
}
export const getTbUnitFromSearch = (value: TbUnit | UnitInfo | null): TbUnit => {
if (value === null) {
return null;
}
if (value === undefined) {
return undefined;
}
if (typeof value === 'string') {
return value;
}
if ('abbr' in value) {
return value.abbr;
}
return value;
}

View File

@ -875,15 +875,16 @@ export abstract class ValueFormatProcessor {
protected hideZeroDecimals: boolean; protected hideZeroDecimals: boolean;
protected unitSymbol: string; protected unitSymbol: string;
static fromSettings($injector: Injector, settings: ValueFormatSettings): ValueFormatProcessor { static fromSettings($injector: Injector, settings: ValueFormatSettings): ValueFormatProcessor;
static fromSettings(unitService: UnitService, settings: ValueFormatSettings): ValueFormatProcessor;
static fromSettings(unitServiceOrInjector: Injector | UnitService, settings: ValueFormatSettings): ValueFormatProcessor {
if (settings.units !== null && typeof settings.units === 'object') { if (settings.units !== null && typeof settings.units === 'object') {
return new UnitConverterValueFormatProcessor($injector, settings) return new UnitConverterValueFormatProcessor(unitServiceOrInjector, settings)
} }
return new SimpleValueFormatProcessor($injector, settings); return new SimpleValueFormatProcessor(settings);
} }
protected constructor(protected $injector: Injector, protected constructor(protected settings: ValueFormatSettings) {
protected settings: ValueFormatSettings) {
} }
abstract format(value: any): string; abstract format(value: any): string;
@ -908,9 +909,8 @@ export class SimpleValueFormatProcessor extends ValueFormatProcessor {
private readonly isDefinedUnit: boolean; private readonly isDefinedUnit: boolean;
constructor(protected $injector: Injector, constructor(protected settings: ValueFormatSettings) {
protected settings: ValueFormatSettings) { super(settings);
super($injector, settings);
this.unitSymbol = !settings.ignoreUnitSymbol && isNotEmptyStr(settings.units) ? (settings.units as string) : null; this.unitSymbol = !settings.ignoreUnitSymbol && isNotEmptyStr(settings.units) ? (settings.units as string) : null;
this.isDefinedDecimals = isDefinedAndNotNull(settings.decimals); this.isDefinedDecimals = isDefinedAndNotNull(settings.decimals);
this.hideZeroDecimals = !settings.showZeroDecimals; this.hideZeroDecimals = !settings.showZeroDecimals;
@ -928,10 +928,10 @@ export class UnitConverterValueFormatProcessor extends ValueFormatProcessor {
private readonly unitConverter: TbUnitConverter; private readonly unitConverter: TbUnitConverter;
constructor(protected $injector: Injector, constructor(protected unitServiceOrInjector: Injector | UnitService,
protected settings: ValueFormatSettings) { protected settings: ValueFormatSettings) {
super($injector, settings); super(settings);
const unitService = this.$injector.get(UnitService); const unitService = this.unitServiceOrInjector instanceof UnitService ? this.unitServiceOrInjector : this.unitServiceOrInjector.get(UnitService);
const unit = settings.units; const unit = settings.units;
this.unitSymbol = settings.ignoreUnitSymbol ? null : unitService.getTargetUnitSymbol(unit); this.unitSymbol = settings.ignoreUnitSymbol ? null : unitService.getTargetUnitSymbol(unit);
this.unitConverter = unitService.geUnitConverter(unit); this.unitConverter = unitService.geUnitConverter(unit);