UI: Improve aggregated value card widget. Improve data key aggregation config form.
This commit is contained in:
parent
943788f25e
commit
1422558ac6
@ -64,6 +64,9 @@
|
||||
<tb-color-settings formControlName="color">
|
||||
</tb-color-settings>
|
||||
</div>
|
||||
<div class="tb-arrow-field">
|
||||
<mat-checkbox formControlName="showArrow"></mat-checkbox>
|
||||
</div>
|
||||
<div class="tb-form-table-row-cell-buttons">
|
||||
<button type="button"
|
||||
mat-icon-button
|
||||
|
||||
@ -49,10 +49,10 @@
|
||||
|
||||
.tb-aggregation-field {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.tb-units-field, .tb-decimals-field, .tb-font-field, .tb-color-field {
|
||||
.tb-units-field, .tb-decimals-field, .tb-font-field, .tb-color-field, tb-arrow-field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
place-content: center;
|
||||
@ -69,14 +69,13 @@
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.tb-font-field {
|
||||
.tb-font-field, .tb-color-field, .tb-arrow-field {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
display: none;
|
||||
@media #{$mat-gt-xs} {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tb-color-field {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.tb-units-field, .tb-decimals-field {
|
||||
|
||||
@ -33,7 +33,7 @@ import {
|
||||
ComparisonResultType,
|
||||
DataKey,
|
||||
DataKeyConfigMode,
|
||||
DatasourceType, Widget,
|
||||
DatasourceType, JsonSettingsSchema, Widget,
|
||||
widgetType
|
||||
} from '@shared/models/widget.models';
|
||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||
@ -104,6 +104,14 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
return this.widgetConfigComponent.widget;
|
||||
}
|
||||
|
||||
get latestDataKeySettingsSchema(): JsonSettingsSchema {
|
||||
return this.widgetConfigComponent.modelValue?.latestDataKeySettingsSchema;
|
||||
}
|
||||
|
||||
get latestDataKeySettingsDirective(): string {
|
||||
return this.widgetConfigComponent.modelValue?.latestDataKeySettingsDirective;
|
||||
}
|
||||
|
||||
get isEntityDatasource(): boolean {
|
||||
return [DatasourceType.device, DatasourceType.entity].includes(this.datasourceType);
|
||||
}
|
||||
@ -124,7 +132,8 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
units: [null, []],
|
||||
decimals: [null, []],
|
||||
font: [null, []],
|
||||
color: [null, []]
|
||||
color: [null, []],
|
||||
showArrow: [null, []]
|
||||
});
|
||||
this.keyRowFormGroup.valueChanges.subscribe(
|
||||
() => this.updateModel()
|
||||
@ -172,7 +181,8 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
units: value?.units,
|
||||
decimals: value?.decimals,
|
||||
font: settings.font,
|
||||
color: settings.color
|
||||
color: settings.color,
|
||||
showArrow: settings.showArrow
|
||||
}, {emitEvent: false}
|
||||
);
|
||||
this.cd.markForCheck();
|
||||
@ -190,8 +200,8 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
data: {
|
||||
dataKey: deepClone(this.modelValue),
|
||||
dataKeyConfigMode: DataKeyConfigMode.general,
|
||||
dataKeySettingsSchema: null,
|
||||
dataKeySettingsDirective: null,
|
||||
dataKeySettingsSchema: this.latestDataKeySettingsSchema,
|
||||
dataKeySettingsDirective: this.latestDataKeySettingsDirective,
|
||||
dashboard: null,
|
||||
aliasController: null,
|
||||
widget: this.widget,
|
||||
@ -207,6 +217,11 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
}).afterClosed().subscribe((updatedDataKey) => {
|
||||
if (updatedDataKey) {
|
||||
this.modelValue = updatedDataKey;
|
||||
const settings: AggregatedValueCardKeySettings = (this.modelValue.settings || {});
|
||||
this.keyRowFormGroup.get('position').patchValue(settings.position, {emitEvent: false});
|
||||
this.keyRowFormGroup.get('font').patchValue(settings.font, {emitEvent: false});
|
||||
this.keyRowFormGroup.get('color').patchValue(settings.color, {emitEvent: false});
|
||||
this.keyRowFormGroup.get('showArrow').patchValue(settings.showArrow, {emitEvent: false});
|
||||
this.keyRowFormGroup.get('units').patchValue(this.modelValue.units, {emitEvent: false});
|
||||
this.keyRowFormGroup.get('decimals').patchValue(this.modelValue.decimals, {emitEvent: false});
|
||||
this.updateModel();
|
||||
@ -220,6 +235,7 @@ export class AggregatedDataKeyRowComponent implements ControlValueAccessor, OnIn
|
||||
this.modelValue.settings.position = value.position;
|
||||
this.modelValue.settings.font = value.font;
|
||||
this.modelValue.settings.color = value.color;
|
||||
this.modelValue.settings.showArrow = value.showArrow;
|
||||
this.modelValue.units = value.units;
|
||||
this.modelValue.decimals = value.decimals;
|
||||
this.propagateChange(this.modelValue);
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
<div class="tb-form-table-header-cell tb-decimals-header" translate>widget-config.decimals-short</div>
|
||||
<div class="tb-form-table-header-cell tb-font-header" translate>widgets.aggregated-value-card.font</div>
|
||||
<div class="tb-form-table-header-cell tb-color-header" translate>widgets.aggregated-value-card.color</div>
|
||||
<div class="tb-form-table-header-cell tb-arrow-header" translate>widgets.aggregated-value-card.arrow</div>
|
||||
<div class="tb-form-table-header-cell tb-actions-header"></div>
|
||||
</div>
|
||||
<div *ngIf="keysFormArray().controls.length; else noKeys" class="tb-form-table-body">
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
&.tb-aggregation-header {
|
||||
flex: 1;
|
||||
min-width: 150px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
&.tb-units-header {
|
||||
@ -38,14 +38,13 @@
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
&.tb-font-header {
|
||||
&.tb-font-header, &.tb-color-header, &.tb-arrow-header {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
display: none;
|
||||
@media #{$mat-gt-xs} {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.tb-color-header {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
&.tb-actions-header {
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
</tb-datasources>
|
||||
<div class="tb-form-panel">
|
||||
<div class="tb-form-panel-title" translate>widget-config.appearance</div>
|
||||
<div class="tb-form-row">
|
||||
<div class="tb-form-row column-xs">
|
||||
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
|
||||
{{ 'widget-config.title' | translate }}
|
||||
</mat-slide-toggle>
|
||||
@ -48,7 +48,7 @@
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row">
|
||||
<div class="tb-form-row column-xs">
|
||||
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showIcon">
|
||||
{{ 'widgets.value-card.icon' | translate }}
|
||||
</mat-slide-toggle>
|
||||
@ -68,7 +68,7 @@
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row">
|
||||
<div class="tb-form-row column-xs">
|
||||
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showSubtitle">
|
||||
{{ 'widgets.aggregated-value-card.subtitle' | translate }}
|
||||
</mat-slide-toggle>
|
||||
@ -80,8 +80,10 @@
|
||||
clearButton
|
||||
[previewText]="aggregatedValueCardWidgetConfigForm.get('subtitle').value">
|
||||
</tb-font-settings>
|
||||
<tb-color-settings formControlName="subtitleColor">
|
||||
</tb-color-settings>
|
||||
<tb-color-input asBoxInput
|
||||
colorClearButton
|
||||
formControlName="subtitleColor">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row column-xs">
|
||||
@ -93,16 +95,27 @@
|
||||
<tb-font-settings formControlName="dateFont"
|
||||
[previewText]="datePreviewFn">
|
||||
</tb-font-settings>
|
||||
<tb-color-settings formControlName="dateColor">
|
||||
</tb-color-settings>
|
||||
<tb-color-input asBoxInput
|
||||
colorClearButton
|
||||
formControlName="dateColor">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tb-form-row space-between">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="showChart">
|
||||
<div class="tb-form-row column-xs">
|
||||
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showChart">
|
||||
{{ 'widgets.aggregated-value-card.chart' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<tb-color-settings formControlName="chartColor">
|
||||
</tb-color-settings>
|
||||
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
|
||||
<tb-unit-input class="flex" formControlName="chartUnits"></tb-unit-input>
|
||||
<mat-form-field appearance="outline" class="flex number" subscriptSizing="dynamic">
|
||||
<input matInput formControlName="chartDecimals" type="number" min="0" max="15" step="1" placeholder="{{ 'widget-config.set' | translate }}">
|
||||
<div matSuffix fxHide.lt-md translate>widget-config.decimals-suffix</div>
|
||||
</mat-form-field>
|
||||
<tb-color-input asBoxInput
|
||||
colorClearButton
|
||||
formControlName="chartColor">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tb-aggregated-data-keys-panel
|
||||
|
||||
@ -90,7 +90,7 @@ export class AggregatedValueCardBasicConfigComponent extends BasicWidgetConfigCo
|
||||
|
||||
protected setupDefaults(configData: WidgetConfigComponentData) {
|
||||
this.setupDefaultDatasource(configData, [
|
||||
{ name: 'watermeter', label: 'Watermeter', type: DataKeyType.timeseries }
|
||||
{ name: 'watermeter', label: 'Watermeter', type: DataKeyType.timeseries, units: 'm³', decimals: 0 }
|
||||
],
|
||||
createDefaultAggregatedValueLatestDataKeys('watermeter', 'm³')
|
||||
);
|
||||
@ -141,6 +141,8 @@ export class AggregatedValueCardBasicConfigComponent extends BasicWidgetConfigCo
|
||||
dateColor: [settings.dateColor, []],
|
||||
|
||||
showChart: [settings.showChart, []],
|
||||
chartUnits: [dataKey?.units, []],
|
||||
chartDecimals: [dataKey?.decimals, []],
|
||||
chartColor: [settings.chartColor, []],
|
||||
|
||||
values: [this.getValues(configData.config.datasources, keyName), []],
|
||||
@ -181,6 +183,13 @@ export class AggregatedValueCardBasicConfigComponent extends BasicWidgetConfigCo
|
||||
this.widgetConfig.config.settings.dateColor = config.dateColor;
|
||||
|
||||
this.widgetConfig.config.settings.showChart = config.showChart;
|
||||
|
||||
const dataKey = getDataKey(this.widgetConfig.config.datasources);
|
||||
if (dataKey) {
|
||||
dataKey.units = config.chartUnits;
|
||||
dataKey.decimals = config.chartDecimals;
|
||||
}
|
||||
|
||||
this.widgetConfig.config.settings.chartColor = config.chartColor;
|
||||
|
||||
this.setValues(config.values, this.widgetConfig.config.datasources);
|
||||
@ -253,8 +262,12 @@ export class AggregatedValueCardBasicConfigComponent extends BasicWidgetConfigCo
|
||||
}
|
||||
|
||||
if (showChart) {
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartUnits').enable();
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartDecimals').enable();
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartColor').enable();
|
||||
} else {
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartUnits').disable();
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartDecimals').disable();
|
||||
this.aggregatedValueCardWidgetConfigForm.get('chartColor').disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,38 +78,44 @@
|
||||
</tb-js-func>
|
||||
</section>
|
||||
<ng-container *ngIf="widgetType === widgetTypes.latest && modelValue.type === dataKeyTypes.timeseries">
|
||||
<mat-form-field subscriptSizing="dynamic">
|
||||
<mat-label translate>datakey.aggregation</mat-label>
|
||||
<mat-select formControlName="aggregationType" style="min-width: 150px;">
|
||||
<div class="tb-form-row column">
|
||||
<div class="tb-form-row space-between no-border no-padding">
|
||||
<div>{{ 'datakey.aggregation' | translate }}</div>
|
||||
<mat-form-field class="medium-width" subscriptSizing="dynamic" appearance="outline">
|
||||
<mat-select formControlName="aggregationType">
|
||||
<mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">
|
||||
{{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div class="tb-hint after-fields">
|
||||
</div>
|
||||
<div class="tb-form-hint tb-primary-fill">
|
||||
{{ dataKeyFormGroup.get('aggregationType').value ? (dataKeyAggregationTypeHintTranslations.get(aggregationTypes[dataKeyFormGroup.get('aggregationType').value]) | translate) : '' }}
|
||||
<section *ngIf="dataKeyFormGroup.get('aggregationType').value !== aggregationTypes.NONE">
|
||||
{{ 'datakey.aggregation-type-hint-common' | translate }}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div *ngIf="dataKeyFormGroup.get('aggregationType').value && dataKeyFormGroup.get('aggregationType').value !== aggregationTypes.NONE"
|
||||
class="tb-form-panel tb-slide-toggle">
|
||||
class="tb-form-panel">
|
||||
<div class="tb-form-panel-title" translate>datakey.delta-calculation</div>
|
||||
<div class="tb-form-panel stroked tb-slide-toggle">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="dataKeyFormGroup.get('comparisonEnabled').value" [disabled]="!dataKeyFormGroup.get('comparisonEnabled').value">
|
||||
<mat-expansion-panel-header fxLayout="row wrap">
|
||||
<mat-panel-title fxLayout="column" fxLayoutAlign="center start">
|
||||
<mat-panel-title fxLayout="column" fxLayoutAlign="center start" fxLayoutGap="8px">
|
||||
<mat-slide-toggle class="mat-slide" formControlName="comparisonEnabled" (click)="$event.stopPropagation()">
|
||||
{{ 'datakey.enable-delta-calculation' | translate }}
|
||||
</mat-slide-toggle>
|
||||
<mat-hint class="tb-hint" style="line-height: 15px; padding-left: 52px;">{{ 'datakey.enable-delta-calculation-hint' | translate }}</mat-hint>
|
||||
<mat-hint class="tb-form-hint tb-primary-fill">{{ 'datakey.enable-delta-calculation-hint' | translate }}</mat-hint>
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<ng-template matExpansionPanelContent>
|
||||
<section fxLayout="column" *ngIf="dataKeyFormGroup.get('comparisonEnabled').value">
|
||||
<mat-form-field fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.chart.time-for-comparison</mat-label>
|
||||
<ng-container *ngIf="dataKeyFormGroup.get('comparisonEnabled').value">
|
||||
<div class="tb-form-row space-between">
|
||||
<div>{{ 'widgets.chart.time-for-comparison' | translate }}</div>
|
||||
<mat-form-field class="medium-width" subscriptSizing="dynamic" appearance="outline">
|
||||
<mat-select formControlName="timeForComparison">
|
||||
<mat-option [value]="'previousInterval'">
|
||||
{{ 'widgets.chart.time-for-comparison-previous-interval' | translate }}
|
||||
@ -131,23 +137,28 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="dataKeyFormGroup.get('timeForComparison').value === 'customInterval'" fxFlex class="mat-block">
|
||||
<mat-label translate>widgets.chart.custom-interval-value</mat-label>
|
||||
</div>
|
||||
<div *ngIf="dataKeyFormGroup.get('timeForComparison').value === 'customInterval'" class="tb-form-row space-between">
|
||||
<div>{{ 'widgets.chart.custom-interval-value' | translate }}</div>
|
||||
<mat-form-field class="medium-width number" subscriptSizing="dynamic" appearance="outline">
|
||||
<input required matInput type="number" min="0" formControlName="comparisonCustomIntervalValue">
|
||||
</mat-form-field>
|
||||
<mat-form-field style="padding-bottom: 16px;">
|
||||
<mat-label translate>datakey.delta-calculation-result</mat-label>
|
||||
</div>
|
||||
<div class="tb-form-row space-between">
|
||||
<div>{{ 'datakey.delta-calculation-result' | translate }}</div>
|
||||
<mat-form-field class="medium-width" subscriptSizing="dynamic" appearance="outline">
|
||||
<mat-select formControlName="comparisonResultType" style="min-width: 150px;">
|
||||
<mat-option *ngFor="let comparisonResultType of comparisonResults" [value]="comparisonResultType">
|
||||
{{ comparisonResultTypeTranslations.get(comparisonResultTypes[comparisonResultType]) | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tb-form-panel tb-slide-toggle"
|
||||
*ngIf="(modelValue.type === dataKeyTypes.timeseries || modelValue.type === dataKeyTypes.attribute || modelValue.type === dataKeyTypes.count) && showPostProcessing">
|
||||
<mat-expansion-panel class="tb-settings" [expanded]="dataKeyFormGroup.get('usePostProcessing').value" [disabled]="!dataKeyFormGroup.get('usePostProcessing').value">
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../../theme";
|
||||
@import "../../../../../../scss/constants";
|
||||
|
||||
.tb-datasource-list-item {
|
||||
&.mat-mdc-list-item {
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
<ng-template #subtitleTpl>
|
||||
<div *ngIf="showSubtitle" class="tb-aggregated-value-card-subtitle"
|
||||
[style]="subtitleStyle" [style.color]="subtitleColor.color">{{ subtitle$ | async }}</div>
|
||||
[style]="subtitleStyle" [style.color]="subtitleColor">{{ subtitle$ | async }}</div>
|
||||
</ng-template>
|
||||
<ng-template #valuesTpl>
|
||||
<div *ngIf="showValues" class="tb-aggregated-value-card-values">
|
||||
@ -73,7 +73,7 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
<ng-template #dateTpl>
|
||||
<div *ngIf="showDate" [style]="dateStyle" [style.color]="dateColor.color" [innerHTML]="dateFormat.formatted"></div>
|
||||
<div *ngIf="showDate" [style]="dateStyle" [style.color]="dateColor" [innerHTML]="dateFormat.formatted"></div>
|
||||
</ng-template>
|
||||
<ng-template #valueTpl let-value="value">
|
||||
<div class="tb-aggregated-value-card-value" [style]="value.style" [style.color]="value.color.color">
|
||||
|
||||
@ -36,9 +36,9 @@ import { WidgetContext } from '@home/models/widget-component.models';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
backgroundStyle,
|
||||
ColorProcessor,
|
||||
ComponentStyle,
|
||||
DateFormatProcessor, getDataKey,
|
||||
DateFormatProcessor,
|
||||
getDataKey,
|
||||
getLatestSingleTsValue,
|
||||
overlayStyle,
|
||||
textStyle
|
||||
@ -47,7 +47,7 @@ import { DatePipe } from '@angular/common';
|
||||
import { TbFlot } from '@home/components/widget/lib/flot-widget';
|
||||
import { TbFlotKeySettings, TbFlotSettings } from '@home/components/widget/lib/flot-widget.models';
|
||||
import { DataKey } from '@shared/models/widget.models';
|
||||
import { formatNumberValue, formatValue, isDefined, isNumeric } from '@core/utils';
|
||||
import { formatNumberValue, formatValue, isDefined } from '@core/utils';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
@ -72,19 +72,19 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit
|
||||
showSubtitle = true;
|
||||
subtitle$: Observable<string>;
|
||||
subtitleStyle: ComponentStyle = {};
|
||||
subtitleColor: ColorProcessor;
|
||||
subtitleColor: string;
|
||||
|
||||
showValues = false;
|
||||
|
||||
values: {[key: string]: AggregatedValueCardValue} = {};
|
||||
|
||||
showChart = true;
|
||||
chartColor: ColorProcessor;
|
||||
chartColor: string;
|
||||
|
||||
showDate = true;
|
||||
dateFormat: DateFormatProcessor;
|
||||
dateStyle: ComponentStyle = {};
|
||||
dateColor: ColorProcessor;
|
||||
dateColor: string;
|
||||
|
||||
backgroundStyle: ComponentStyle = {};
|
||||
overlayStyle: ComponentStyle = {};
|
||||
@ -108,7 +108,7 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit
|
||||
const subtitle = this.settings.subtitle;
|
||||
this.subtitle$ = this.ctx.registerLabelPattern(subtitle, this.subtitle$);
|
||||
this.subtitleStyle = textStyle(this.settings.subtitleFont, '0.25px');
|
||||
this.subtitleColor = ColorProcessor.fromSettings(this.settings.subtitleColor);
|
||||
this.subtitleColor = this.settings.subtitleColor;
|
||||
|
||||
const dataKey = getDataKey(this.ctx.defaultSubscription.datasources);
|
||||
if (dataKey?.name && this.ctx.defaultSubscription.firstDatasource?.latestDataKeys?.length) {
|
||||
@ -123,7 +123,7 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit
|
||||
}
|
||||
|
||||
this.showChart = this.settings.showChart;
|
||||
this.chartColor = ColorProcessor.fromSettings(this.settings.chartColor);
|
||||
this.chartColor = this.settings.chartColor;
|
||||
if (this.showChart) {
|
||||
if (this.ctx.defaultSubscription.firstDatasource?.dataKeys?.length) {
|
||||
this.flotDataKey = this.ctx.defaultSubscription.firstDatasource?.dataKeys[0];
|
||||
@ -132,14 +132,14 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit
|
||||
showLines: true,
|
||||
lineWidth: 2
|
||||
} as TbFlotKeySettings;
|
||||
this.flotDataKey.color = this.chartColor.color;
|
||||
this.flotDataKey.color = this.chartColor;
|
||||
}
|
||||
}
|
||||
|
||||
this.showDate = this.settings.showDate;
|
||||
this.dateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.dateFormat);
|
||||
this.dateStyle = textStyle(this.settings.dateFont, '0.25px');
|
||||
this.dateColor = ColorProcessor.fromSettings(this.settings.dateColor);
|
||||
this.dateColor = this.settings.dateColor;
|
||||
|
||||
this.backgroundStyle = backgroundStyle(this.settings.background);
|
||||
this.overlayStyle = overlayStyle(this.settings.background.overlay);
|
||||
@ -188,17 +188,11 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit
|
||||
public onDataUpdated() {
|
||||
const tsValue = getLatestSingleTsValue(this.ctx.data);
|
||||
let ts;
|
||||
let value;
|
||||
if (tsValue) {
|
||||
ts = tsValue[0];
|
||||
value = tsValue[1];
|
||||
}
|
||||
this.subtitleColor.update(value);
|
||||
this.dateColor.update(value);
|
||||
|
||||
if (this.showChart) {
|
||||
this.chartColor.update(value);
|
||||
this.flot.updateSeriesColor(this.chartColor.color);
|
||||
this.flot.update();
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,6 @@ import {
|
||||
constantColor,
|
||||
DateFormatSettings,
|
||||
Font,
|
||||
iconStyle,
|
||||
lastUpdateAgoDateFormat,
|
||||
textStyle
|
||||
} from '@shared/models/widget-settings.models';
|
||||
@ -36,13 +35,13 @@ export interface AggregatedValueCardWidgetSettings {
|
||||
showSubtitle: boolean;
|
||||
subtitle: string;
|
||||
subtitleFont: Font;
|
||||
subtitleColor: ColorSettings;
|
||||
subtitleColor: string;
|
||||
showDate: boolean;
|
||||
dateFormat: DateFormatSettings;
|
||||
dateFont: Font;
|
||||
dateColor: ColorSettings;
|
||||
dateColor: string;
|
||||
showChart: boolean;
|
||||
chartColor: ColorSettings;
|
||||
chartColor: string;
|
||||
background: BackgroundSettings;
|
||||
}
|
||||
|
||||
@ -83,7 +82,8 @@ export interface AggregatedValueCardValue {
|
||||
downArrow: boolean;
|
||||
}
|
||||
|
||||
export const computeAggregatedCardValue = (dataKeys: DataKey[], keyName: string, position: AggregatedValueCardKeyPosition): AggregatedValueCardValue => {
|
||||
export const computeAggregatedCardValue =
|
||||
(dataKeys: DataKey[], keyName: string, position: AggregatedValueCardKeyPosition): AggregatedValueCardValue => {
|
||||
const key = dataKeys.find(dataKey => ( dataKey.name === keyName && (dataKey.settings?.position === position ||
|
||||
(!dataKey.settings?.position && position === AggregatedValueCardKeyPosition.center)) ));
|
||||
if (key) {
|
||||
@ -123,7 +123,7 @@ export const aggregatedValueCardDefaultSettings: AggregatedValueCardWidgetSettin
|
||||
weight: '400',
|
||||
lineHeight: '16px'
|
||||
},
|
||||
subtitleColor: constantColor('rgba(0, 0, 0, 0.38)'),
|
||||
subtitleColor: 'rgba(0, 0, 0, 0.38)',
|
||||
showDate: true,
|
||||
dateFormat: lastUpdateAgoDateFormat(),
|
||||
dateFont: {
|
||||
@ -134,9 +134,9 @@ export const aggregatedValueCardDefaultSettings: AggregatedValueCardWidgetSettin
|
||||
weight: '400',
|
||||
lineHeight: '16px'
|
||||
},
|
||||
dateColor: constantColor('rgba(0, 0, 0, 0.38)'),
|
||||
dateColor: 'rgba(0, 0, 0, 0.38)',
|
||||
showChart: true,
|
||||
chartColor: constantColor('rgba(0, 0, 0, 0.87)'),
|
||||
chartColor: 'rgba(0, 0, 0, 0.87)',
|
||||
background: {
|
||||
type: BackgroundType.color,
|
||||
color: '#fff',
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../theme";
|
||||
@import "../../../../../scss/constants";
|
||||
|
||||
:host {
|
||||
.fields-group {
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../../theme";
|
||||
@import "../../../../../../scss/constants";
|
||||
|
||||
:host ::ng-deep {
|
||||
.mat-button-toggle-group.tb-notification-unread-toggle-group {
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../../scss/constants";
|
||||
@import "../../../../../../theme";
|
||||
|
||||
:host {
|
||||
form.tb-dialog-container {
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../../theme";
|
||||
@import "../../../../../../scss/constants";
|
||||
|
||||
:host {
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../../../scss/constants";
|
||||
@import "../../../../../../theme";
|
||||
|
||||
:host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) {
|
||||
width: 820px;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@import "../../../../theme";
|
||||
@import "../../../../scss/constants";
|
||||
|
||||
:host {
|
||||
.mini-button {
|
||||
|
||||
@ -18,6 +18,7 @@ import { Component, forwardRef, OnDestroy } from '@angular/core';
|
||||
import { Color, ColorPickerControl } from '@iplab/ngx-color-picker';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormControl } from '@angular/forms';
|
||||
import { isString } from '@core/utils';
|
||||
|
||||
export enum ColorType {
|
||||
hex = 'hex',
|
||||
@ -87,8 +88,9 @@ export class ColorPickerComponent implements ControlValueAccessor, OnDestroy {
|
||||
}
|
||||
|
||||
writeValue(value: string): void {
|
||||
this.setValue = !!value;
|
||||
this.control.setValueFrom(value || '#fff');
|
||||
const valid = this.isValidColorValue(value);
|
||||
this.setValue = valid;
|
||||
this.control.setValueFrom(valid ? value : '#fff');
|
||||
this.modelValue = value;
|
||||
|
||||
if (this.control.initType === ColorType.hexa) {
|
||||
@ -101,6 +103,10 @@ export class ColorPickerComponent implements ControlValueAccessor, OnDestroy {
|
||||
this.presentationControl.patchValue(this.presentations.indexOf(this.control.initType), {emitEvent: false});
|
||||
}
|
||||
|
||||
private isValidColorValue(value: string): boolean {
|
||||
return value && isString(value) && value.trim().length > 0;
|
||||
}
|
||||
|
||||
private updateModel() {
|
||||
const color: string = this.getValueByType(this.control.value, this.presentations[this.presentationControl.value]);
|
||||
if (this.modelValue !== color) {
|
||||
|
||||
@ -53,22 +53,24 @@
|
||||
</ng-container>
|
||||
</div>
|
||||
</cdk-virtual-scroll-viewport>
|
||||
<button *ngIf="!showAllSubject.value" class="tb-material-icons-show-more" mat-button color="primary" (click)="showAllSubject.next(true)">
|
||||
{{ 'action.show-more' | translate }}
|
||||
</button>
|
||||
<ng-container *ngIf="notFound">
|
||||
<div class="tb-no-data-available" [ngStyle]="{width: iconsPanelWidth}">
|
||||
<div class="tb-no-data-bg"></div>
|
||||
<div class="tb-no-data-text">{{ 'icon.no-icons-found' | translate:{iconSearch: searchIconControl.value} }}</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div *ngIf="iconClearButton" class="tb-material-icons-panel-buttons">
|
||||
<button mat-button
|
||||
<div class="tb-material-icons-panel-buttons" *ngIf="iconClearButton || !showAllSubject.value">
|
||||
<button *ngIf="iconClearButton"
|
||||
mat-button
|
||||
color="primary"
|
||||
type="button"
|
||||
(click)="clearIcon()"
|
||||
[disabled]="!selectedIcon">
|
||||
{{ 'action.clear' | translate }}
|
||||
</button>
|
||||
<span fxFlex></span>
|
||||
<button *ngIf="!showAllSubject.value" class="tb-material-icons-show-more" mat-button color="primary" (click)="showAllSubject.next(true)">
|
||||
{{ 'action.show-more' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
letter-spacing: 0.25px;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.tb-material-icons-title, .tb-material-icons-search, .tb-material-icons-show-more {
|
||||
.tb-material-icons-title, .tb-material-icons-search {
|
||||
width: 100%;
|
||||
}
|
||||
.tb-material-icons-viewport {
|
||||
@ -64,6 +64,6 @@
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
align-self: flex-start;
|
||||
align-self: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import "../../../theme";
|
||||
@import "../../../scss/constants";
|
||||
|
||||
:host {
|
||||
|
||||
@ -149,7 +149,7 @@ type ValueColorFunction = (value: any) => string;
|
||||
export abstract class ColorProcessor {
|
||||
|
||||
static fromSettings(color: ColorSettings): ColorProcessor {
|
||||
const settings = color || constantColor('rgba(0, 0, 0, 0.87)');
|
||||
const settings = color || constantColor(null);
|
||||
switch (settings.type) {
|
||||
case ColorType.constant:
|
||||
return new ConstantColorProcessor(settings);
|
||||
@ -192,7 +192,7 @@ class RangeColorProcessor extends ColorProcessor {
|
||||
if (this.settings.rangeList?.length && isDefinedAndNotNull(value) && isNumeric(value)) {
|
||||
const num = Number(value);
|
||||
for (const range of this.settings.rangeList) {
|
||||
if (this.constantRange(range) && range.from === num) {
|
||||
if (RangeColorProcessor.constantRange(range) && range.from === num) {
|
||||
return range.color;
|
||||
} else if ((!isNumber(range.from) || num >= range.from) && (!isNumber(range.to) || num < range.to)) {
|
||||
return range.color;
|
||||
@ -202,7 +202,7 @@ class RangeColorProcessor extends ColorProcessor {
|
||||
return this.settings.color;
|
||||
}
|
||||
|
||||
private constantRange(range: ColorRange): boolean {
|
||||
private static constantRange(range: ColorRange): boolean {
|
||||
return isNumber(range.from) && isNumber(range.to) && range.from === range.to;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5756,6 +5756,7 @@
|
||||
"position-left-bottom": "Left bottom",
|
||||
"font": "Font",
|
||||
"color": "Color",
|
||||
"arrow": "Arrow",
|
||||
"display-up-down-arrow": "Display Up/Down arrow",
|
||||
"add-value": "Add value",
|
||||
"remove-value": "Remove value",
|
||||
|
||||
@ -16,12 +16,16 @@
|
||||
|
||||
@import './scss/constants';
|
||||
|
||||
@mixin form-row-column($breakpoint) {
|
||||
@media #{$breakpoint} {
|
||||
@mixin form-row-column() {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
padding: 12px 7px 12px 16px;
|
||||
}
|
||||
|
||||
@mixin form-row-column-breakpoint($breakpoint) {
|
||||
@media #{$breakpoint} {
|
||||
@include form-row-column;
|
||||
.mat-mdc-form-field, tb-unit-input {
|
||||
width: auto;
|
||||
&.medium-width {
|
||||
@ -132,6 +136,16 @@
|
||||
font-size: 12px;
|
||||
color: #808080;
|
||||
}
|
||||
.tb-form-hint {
|
||||
padding: 12px 16px;
|
||||
font-size: var(--mdc-typography-caption-font-size, 12px);
|
||||
line-height: var(--mdc-typography-caption-line-height, 20px);
|
||||
font-weight: var(--mdc-typography-caption-font-weight, 400);
|
||||
letter-spacing: var(--mdc-typography-caption-letter-spacing, 0.0333333333em);
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
white-space: normal;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.tb-form-row {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
@ -142,11 +156,12 @@
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border-radius: 6px;
|
||||
&.column {
|
||||
@include form-row-column;
|
||||
&-xs {
|
||||
@include form-row-column($mat-xs)
|
||||
@include form-row-column-breakpoint($mat-xs)
|
||||
}
|
||||
&-lt-md {
|
||||
@include form-row-column($mat-lt-md)
|
||||
@include form-row-column-breakpoint($mat-lt-md)
|
||||
}
|
||||
}
|
||||
&.no-border {
|
||||
@ -450,7 +465,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #305680;
|
||||
background: $tb-primary-color;
|
||||
mask-image: url(/assets/home/no_data_folder_bg.svg);
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
@ -470,6 +485,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tb-primary-fill {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
&:before {
|
||||
display: block;
|
||||
height: auto;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: $tb-primary-color;
|
||||
opacity: 0.04;
|
||||
}
|
||||
}
|
||||
|
||||
button.mat-mdc-button-base.tb-box-button, .tb-form-table-row-cell-buttons button.mat-mdc-icon-button.mat-mdc-button-base {
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
|
||||
@ -30,3 +30,10 @@ $mat-gt-xl: "screen and (min-width: 1920px)";
|
||||
$mat-md-lg: "screen and (min-width: 960px) and (max-width: 1819px)";
|
||||
|
||||
$primary-hue-3: rgb(207, 216, 220) !default;
|
||||
|
||||
$tb-primary-color: #305680;
|
||||
$tb-secondary-color: #527dad;
|
||||
$tb-hue3-color: #a7c1de;
|
||||
|
||||
$tb-dark-primary-color: #9fa8da;
|
||||
|
||||
|
||||
@ -21,12 +21,6 @@
|
||||
@include mat.all-component-typographies();
|
||||
@include mat.core();
|
||||
|
||||
$tb-primary-color: #305680;
|
||||
$tb-secondary-color: #527dad;
|
||||
$tb-hue3-color: #a7c1de;
|
||||
|
||||
$tb-dark-primary-color: #9fa8da;
|
||||
|
||||
$tb-mat-indigo: (
|
||||
50: #e8eaf6,
|
||||
100: #c5cae9,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user