UI: Implement sections count parameter for battery level widget.

This commit is contained in:
Igor Kulikov 2023-10-10 13:41:45 +03:00
parent 1bb2e8fc72
commit c836c48366
8 changed files with 78 additions and 9 deletions

View File

@ -40,6 +40,12 @@
{{ batteryLevelLayoutTranslationMap.get(layout) | translate }}
</tb-image-cards-select-option>
</tb-image-cards-select>
<div *ngIf="sectionsCountEnabled" class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.sections-count' | translate }}</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput type="number" min="2" max="20" formControlName="sectionsCount" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.title' | translate }}

View File

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, Injector } from '@angular/core';
import { Component } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@ -35,6 +35,7 @@ import { formatValue, isUndefined } from '@core/utils';
import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models';
import {
batteryLevelDefaultSettings,
BatteryLevelLayout,
batteryLevelLayoutImages,
batteryLevelLayouts,
batteryLevelLayoutTranslations,
@ -67,9 +68,13 @@ export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent
valuePreviewFn = this._valuePreviewFn.bind(this);
get sectionsCountEnabled(): boolean {
const layout: BatteryLevelLayout = this.batteryLevelWidgetConfigForm.get('layout').value;
return [BatteryLevelLayout.vertical_divided, BatteryLevelLayout.horizontal_divided].includes(layout);
}
constructor(protected store: Store<AppState>,
protected widgetConfigComponent: WidgetConfigComponent,
private $injector: Injector,
private fb: UntypedFormBuilder) {
super(store, widgetConfigComponent);
}
@ -90,6 +95,7 @@ export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent
datasources: [configData.config.datasources, []],
layout: [settings.layout, []],
sectionsCount: [settings.sectionsCount, [Validators.min(2), Validators.max(20)]],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
@ -136,6 +142,7 @@ export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent
this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
this.widgetConfig.config.settings.layout = config.layout;
this.widgetConfig.config.settings.sectionsCount = config.sectionsCount;
this.widgetConfig.config.settings.showValue = config.showValue;
this.widgetConfig.config.settings.autoScaleValueSize = config.autoScaleValueSize === true;
@ -155,13 +162,15 @@ export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent
}
protected validatorTriggers(): string[] {
return ['showTitle', 'showIcon', 'showValue'];
return ['showTitle', 'showIcon', 'showValue', 'layout'];
}
protected updateValidators(emitEvent: boolean, trigger?: string) {
const showTitle: boolean = this.batteryLevelWidgetConfigForm.get('showTitle').value;
const showIcon: boolean = this.batteryLevelWidgetConfigForm.get('showIcon').value;
const showValue: boolean = this.batteryLevelWidgetConfigForm.get('showValue').value;
const layout: BatteryLevelLayout = this.batteryLevelWidgetConfigForm.get('layout').value;
const divided = [BatteryLevelLayout.vertical_divided, BatteryLevelLayout.horizontal_divided].includes(layout);
if (showTitle) {
this.batteryLevelWidgetConfigForm.get('title').enable();
@ -199,6 +208,11 @@ export class BatteryLevelBasicConfigComponent extends BasicWidgetConfigComponent
this.batteryLevelWidgetConfigForm.get('valueFont').disable();
this.batteryLevelWidgetConfigForm.get('valueColor').disable();
}
if (divided) {
this.batteryLevelWidgetConfigForm.get('sectionsCount').enable();
} else {
this.batteryLevelWidgetConfigForm.get('sectionsCount').disable();
}
}
private getCardButtons(config: WidgetConfig): string[] {

View File

@ -22,7 +22,7 @@
<div #batteryLevelBox class="tb-battery-level-box">
<div #batteryLevelRectangle class="tb-battery-level-rectangle" [class]="layoutClass" [class.solid]="solid" [class.divided]="!solid">
<div class="tb-battery-level-shape" [style.background]="batteryShapeColor.color"></div>
<div class="tb-battery-level-container">
<div class="tb-battery-level-container" [style.gap]="dividedGap">
<div *ngIf="solid; else dividedIndicator" class="tb-battery-level-indicator-box solid"
[style.background-image]="'linear-gradient(0deg, ' + batteryLevelColor.color + ' 0% 100%)'"
[style.background-size]="vertical ? '100% ' + (value + 1) + '%' : (value + 1) + '% 100%'">
@ -38,5 +38,6 @@
<ng-template #dividedIndicator>
<div *ngFor="let section of batterySections; trackBy: trackBySection" class="tb-battery-level-indicator-box divided"
[style.background]="batteryLevelColor.color"
[style.border-radius]="dividedBorderRadius"
[style.opacity]="section ? '1': '0'"></div>
</ng-template>

View File

@ -117,7 +117,9 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView
value: number;
batterySections: boolean[] = [false, false, false, false];
batterySections: boolean[];
dividedBorderRadius: string;
dividedGap: string;
batteryLevelColor: ColorProcessor;
@ -158,6 +160,26 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView
this.vertical = [BatteryLevelLayout.vertical_solid, BatteryLevelLayout.vertical_divided].includes(this.layout);
this.layoutClass = this.vertical ? 'vertical' : 'horizontal';
this.solid = [BatteryLevelLayout.vertical_solid, BatteryLevelLayout.horizontal_solid].includes(this.layout);
if (!this.solid) {
let sectionsCount = this.settings.sectionsCount;
if (!sectionsCount) {
sectionsCount = 4;
}
sectionsCount = Math.min(Math.max(sectionsCount, 2), 20);
this.batterySections = Array.from(Array(sectionsCount), () => false);
const gap = 1 + (24 - sectionsCount) / 10;
this.dividedGap = `${gap}%`;
const containerAspect = 0.5567;
const sectionHeight = (100 - (gap * (sectionsCount - 1))) / sectionsCount;
const sectionAspect = 100 * containerAspect / sectionHeight;
const rad1 = 8.425 - sectionsCount * 0.32125;
const rad2 = rad1 * sectionAspect;
if (this.vertical) {
this.dividedBorderRadius = `${rad1}% / ${rad2}%`;
} else {
this.dividedBorderRadius = `${rad2}% / ${rad1}%`;
}
}
this.showValue = this.settings.showValue;
this.autoScaleValueSize = this.showValue && this.settings.autoScaleValueSize;
@ -243,6 +265,8 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView
const valueLineHeight = ratios.valueLineHeightRaio * boxSize;
this.setValueFontSize(valueFontSize, valueLineHeight, boxWidth);
}
const fontSize = parseInt(window.getComputedStyle(this.batteryLevelValue.nativeElement).fontSize, 10) || 10;
this.renderer.setStyle(this.batteryLevelValue.nativeElement, 'minWidth', `${Math.min(fontSize*4, boxWidth)}px`);
}
let height = this.batteryLevelContent.nativeElement.getBoundingClientRect().height;
const width = height * verticalBatteryDimensions.shapeAspectRatio;

View File

@ -53,6 +53,7 @@ export const batteryLevelLayoutImages = new Map<BatteryLevelLayout, string>(
export interface BatteryLevelWidgetSettings {
layout: BatteryLevelLayout;
sectionsCount: number;
showValue: boolean;
autoScaleValueSize: boolean;
valueFont: Font;
@ -64,6 +65,7 @@ export interface BatteryLevelWidgetSettings {
export const batteryLevelDefaultSettings: BatteryLevelWidgetSettings = {
layout: BatteryLevelLayout.vertical_solid,
sectionsCount: 4,
showValue: true,
autoScaleValueSize: true,
valueFont: {

View File

@ -28,6 +28,12 @@
{{ batteryLevelLayoutTranslationMap.get(layout) | translate }}
</tb-image-cards-select-option>
</tb-image-cards-select>
<div *ngIf="sectionsCountEnabled" class="tb-form-row space-between">
<div>{{ 'widgets.battery-level.sections-count' | translate }}</div>
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
<input matInput type="number" min="2" max="20" formControlName="sectionsCount" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-form-row space-between column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showValue">
{{ 'widgets.battery-level.value' | translate }}

View File

@ -16,12 +16,12 @@
import { Component, Injector } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { formatValue } from '@core/utils';
import {
batteryLevelDefaultSettings,
batteryLevelDefaultSettings, BatteryLevelLayout,
batteryLevelLayoutImages,
batteryLevelLayouts,
batteryLevelLayoutTranslations
@ -43,6 +43,11 @@ export class BatteryLevelWidgetSettingsComponent extends WidgetSettingsComponent
valuePreviewFn = this._valuePreviewFn.bind(this);
get sectionsCountEnabled(): boolean {
const layout: BatteryLevelLayout = this.batteryLevelWidgetSettingsForm.get('layout').value;
return [BatteryLevelLayout.vertical_divided, BatteryLevelLayout.horizontal_divided].includes(layout);
}
constructor(protected store: Store<AppState>,
private $injector: Injector,
private fb: UntypedFormBuilder) {
@ -60,6 +65,7 @@ export class BatteryLevelWidgetSettingsComponent extends WidgetSettingsComponent
protected onSettingsSet(settings: WidgetSettings) {
this.batteryLevelWidgetSettingsForm = this.fb.group({
layout: [settings.layout, []],
sectionsCount: [settings.sectionsCount, [Validators.min(2), Validators.max(20)]],
showValue: [settings.showValue, []],
autoScaleValueSize: [settings.autoScaleValueSize, []],
@ -74,11 +80,13 @@ export class BatteryLevelWidgetSettingsComponent extends WidgetSettingsComponent
}
protected validatorTriggers(): string[] {
return ['showValue'];
return ['showValue', 'layout'];
}
protected updateValidators(emitEvent: boolean) {
const showValue: boolean = this.batteryLevelWidgetSettingsForm.get('showValue').value;
const layout: BatteryLevelLayout = this.batteryLevelWidgetSettingsForm.get('layout').value;
const divided = [BatteryLevelLayout.vertical_divided, BatteryLevelLayout.horizontal_divided].includes(layout);
if (showValue) {
this.batteryLevelWidgetSettingsForm.get('autoScaleValueSize').enable();
@ -90,9 +98,16 @@ export class BatteryLevelWidgetSettingsComponent extends WidgetSettingsComponent
this.batteryLevelWidgetSettingsForm.get('valueColor').disable();
}
if (divided) {
this.batteryLevelWidgetSettingsForm.get('sectionsCount').enable();
} else {
this.batteryLevelWidgetSettingsForm.get('sectionsCount').disable();
}
this.batteryLevelWidgetSettingsForm.get('autoScaleValueSize').updateValueAndValidity({emitEvent});
this.batteryLevelWidgetSettingsForm.get('valueFont').updateValueAndValidity({emitEvent});
this.batteryLevelWidgetSettingsForm.get('valueColor').updateValueAndValidity({emitEvent});
this.batteryLevelWidgetSettingsForm.get('sectionsCount').updateValueAndValidity({emitEvent});
}
private _valuePreviewFn(): string {

View File

@ -5057,7 +5057,8 @@
"auto-scale": "Auto scale",
"battery-level-color": "Battery level color",
"battery-shape-color": "Battery shape color",
"battery-level-card-style": "Battery level card style"
"battery-level-card-style": "Battery level card style",
"sections-count": "Sections count"
},
"chart": {
"common-settings": "Common settings",