Browse Source

UI: Improved CF strategy settings style

pull/14418/head
Vladyslav_Prykhodko 9 months ago
parent
commit
e1c169786b
  1. 158
      ui-ngx/src/app/modules/home/components/calculated-fields/components/output/calculated-field-output.component.html
  2. 27
      ui-ngx/src/app/modules/home/components/calculated-fields/components/output/calculated-field-output.component.ts
  3. 8
      ui-ngx/src/assets/locale/locale.constant-en_US.json

158
ui-ngx/src/app/modules/home/components/calculated-fields/components/output/calculated-field-output.component.html

@ -46,7 +46,7 @@
@if (hiddenName) {
<div class="grid items-start gap-3 has-[.simpleMode]:grid-cols-2 xs:grid-cols-1">
<ng-container *ngTemplateOutlet="decimalsByDefaultField"></ng-container>
<ng-content select=".simpleMode"></ng-content>
<ng-container *ngTemplateOutlet="simpleContentTemplate"></ng-container>
</div>
} @else {
<div class="flex items-start gap-3 xs:flex-col xs:items-stretch">
@ -74,93 +74,94 @@
</mat-form-field>
<ng-container *ngTemplateOutlet="decimalsByDefaultField"></ng-container>
</div>
<ng-content select=".simpleMode"></ng-content>
<ng-container *ngTemplateOutlet="simpleContentTemplate"></ng-container>
}
}
</div>
<div class="tb-form-panel stroked" formGroupName="strategy">
<div class="flex flex-row items-center justify-between gap-2">
<div class="tb-form-panel-title" tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.hint.strategy' | translate }}">
{{ 'calculated-fields.output-strategy.strategy' | translate }}
</div>
<tb-toggle-select formControlName="type" selectMediaBreakpoint="xs" disablePagination appearance="fill">
@for (outputStrategyType of OutputStrategyTypes; track outputStrategyType) {
<tb-toggle-option [value]="outputStrategyType">{{ OutputStrategyTypeTranslations.get(outputStrategyType) | translate }}</tb-toggle-option>
<mat-expansion-panel class="tb-settings" [disabled]="outputForm.get('strategy.type').value === OutputStrategyType.RULE_CHAIN">
<mat-expansion-panel-header class="flex flex-row flex-wrap">
<mat-panel-title>
<div class="flex flex-1 flex-row items-center justify-between xs:flex-col xs:items-start xs:gap-3">
<div class="tb-form-panel-title" style="color: var(--mat-expansion-header-text-color)" tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.hint.strategy' | translate }}">
{{ 'calculated-fields.output-strategy.strategy' | translate }}
</div>
<tb-toggle-select formControlName="type" selectMediaBreakpoint="xs" disablePagination appearance="fill" (click)="$event.stopPropagation()">
@for (outputStrategyType of OutputStrategyTypes; track outputStrategyType) {
<tb-toggle-option [value]="outputStrategyType">{{ OutputStrategyTypeTranslations.get(outputStrategyType) | translate }}</tb-toggle-option>
}
</tb-toggle-select>
</div>
</mat-panel-title>
</mat-expansion-panel-header>
@if (outputForm.get('strategy.type').value === OutputStrategyType.IMMEDIATE) {
@if (outputForm.get('type').value === OutputType.Timeseries) {
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="saveTimeSeries">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.save-time-series' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.save-time-series</div>
</div>
</mat-slide-toggle>
</div>
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="saveLatest">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.save-latest-values' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.save-latest-values</div>
</div>
</mat-slide-toggle>
</div>
} @else {
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="saveAttribute">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.save-database' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.save-database</div>
</div>
</mat-slide-toggle>
</div>
}
</tb-toggle-select>
</div>
@if (outputForm.get('strategy.type').value === OutputStrategyType.IMMEDIATE) {
<div class="tb-form-panel stroked">
<div class="tb-form-panel-title tb-normal" tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.hint.processing-options' | translate }}">
{{ 'calculated-fields.output-strategy.processing-options' | translate }}
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="sendWsUpdate">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.send-web-sockets' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.send-web-sockets</div>
</div>
</mat-slide-toggle>
</div>
<mat-chip-listbox multiple>
@if (outputForm.get('type').value === OutputType.Timeseries) {
<mat-chip-option
[selected]="outputForm.get('strategy.saveTimeSeries').value"
[disabled]="outputForm.get('strategy.saveTimeSeries').disabled"
(click)="toggleChip('saveTimeSeries')">
{{ 'calculated-fields.output-strategy.save-time-series' | translate }}
</mat-chip-option>
<mat-chip-option
[selected]="outputForm.get('strategy.saveLatest').value"
[disabled]="outputForm.get('strategy.saveLatest').disabled"
(click)="toggleChip('saveLatest')">
{{ 'calculated-fields.output-strategy.save-latest-values' | translate }}
</mat-chip-option>
} @else {
<mat-chip-option
[selected]="outputForm.get('strategy.saveAttribute').value"
[disabled]="outputForm.get('strategy.saveAttribute').disabled"
(click)="toggleChip('saveAttribute')">
{{ 'calculated-fields.output-strategy.save-database' | translate }}
</mat-chip-option>
}
<mat-chip-option
[selected]="outputForm.get('strategy.sendWsUpdate').value"
[disabled]="outputForm.get('strategy.sendWsUpdate').disabled"
(click)="toggleChip('sendWsUpdate')">
{{ 'calculated-fields.output-strategy.send-web-sockets' | translate }}
</mat-chip-option>
<mat-chip-option
[selected]="outputForm.get('strategy.processCfs').value"
[disabled]="outputForm.get('strategy.processCfs').disabled"
(click)="toggleChip('processCfs')">
{{ 'calculated-fields.output-strategy.save-calculated-fields' | translate }}
</mat-chip-option>
</mat-chip-listbox>
</div>
@if (outputForm.get('type').value === OutputType.Attribute) {
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">
<div tb-hint-tooltip-icon="{{ (outputForm.get('strategy.updateAttributesOnlyOnValueChange').value
? 'calculated-fields.output-strategy.hint.update-attributes-only-on-value-change-enabled'
: 'calculated-fields.output-strategy.hint.update-attributes-only-on-value-change') | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.update-attributes-only-on-value-change</div>
<mat-slide-toggle class="mat-slide" formControlName="processCfs">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.save-calculated-fields' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.save-calculated-fields</div>
</div>
</mat-slide-toggle>
</div>
} @else {
<tb-time-unit-input
required
subscriptSizing="dynamic"
appearance="outline"
sameWidthInputs
labelText="{{ 'calculated-fields.output-strategy.ttl' | translate }}"
requiredText="{{ 'calculated-fields.output-strategy.ttl-required' | translate }}"
minErrorText="{{ 'calculated-fields.output-strategy.ttl-min' | translate }}"
formControlName="ttl">
<mat-icon class="help-icon mr-2 cursor-pointer"
aria-hidden="false"
aria-label="help-icon"
color="primary"
matSuffix
matTooltip="{{ 'calculated-fields.output-strategy.hint.ttl' | translate }}">
help_outline
</mat-icon>
</tb-time-unit-input>
@if (outputForm.get('type').value === OutputType.Attribute) {
<div class="tb-form-row flex-1">
<mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">
<div tb-hint-tooltip-icon="{{ (outputForm.get('strategy.updateAttributesOnlyOnValueChange').value
? 'calculated-fields.output-strategy.hint.update-attributes-only-on-value-change-enabled'
: 'calculated-fields.output-strategy.hint.update-attributes-only-on-value-change') | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.update-attributes-only-on-value-change</div>
</div>
</mat-slide-toggle>
</div>
} @else {
<div class="tb-form-row space-between column-xs">
<mat-slide-toggle class="mat-slide" formControlName="useCustomTtl">
<div tb-hint-tooltip-icon="{{ 'calculated-fields.output-strategy.hint.ttl' | translate }}">
<div translate tbTruncateWithTooltip>calculated-fields.output-strategy.ttl</div>
</div>
</mat-slide-toggle>
<tb-time-unit-input
required
inlineField
class="medium-width"
requiredText="{{ 'calculated-fields.output-strategy.ttl-required' | translate }}"
minErrorText="{{ 'calculated-fields.output-strategy.ttl-min' | translate }}"
formControlName="ttl">
</tb-time-unit-input>
</div>
}
}
}
</mat-expansion-panel>
</div>
</div>
<ng-template #decimalsByDefaultField>
@ -172,3 +173,6 @@
}
</mat-form-field>
</ng-template>
<ng-template #simpleContentTemplate>
<ng-content select=".simpleMode"></ng-content>
</ng-template>

27
ui-ngx/src/app/modules/home/components/calculated-fields/components/output/calculated-field-output.component.ts

@ -38,6 +38,8 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
import { coerceBoolean } from '@shared/decorators/coercion';
import { merge } from 'rxjs';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-calculate-field-output',
@ -102,6 +104,7 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
sendWsUpdate: [true],
processCfs: [true],
updateAttributesOnlyOnValueChange: [true],
useCustomTtl: [false],
ttl: [0]
})
});
@ -116,7 +119,10 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
this.updatedStrategy();
});
this.outputForm.get('strategy.type').valueChanges
merge(
this.outputForm.get('strategy.type').valueChanges,
this.outputForm.get('strategy.useCustomTtl').valueChanges
)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.updatedStrategy();
@ -151,6 +157,9 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
writeValue(value: CalculatedFieldOutput | CalculatedFieldSimpleOutput): void {
this.outputForm.patchValue(value, {emitEvent: false});
if (value.type === OutputType.Timeseries && value.strategy?.type === OutputStrategyType.IMMEDIATE && value.strategy?.ttl) {
this.outputForm.get('strategy.useCustomTtl').setValue(true, {emitEvent: false});
}
this.outputForm.get('type').updateValueAndValidity({onlySelf: true});
}
@ -171,13 +180,6 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
}
}
toggleChip(controlName: string) {
const control = this.outputForm.get('strategy').get(controlName);
if (control && control.enabled) {
control.setValue(!control.value);
}
}
private updatedModel(value: CalculatedFieldOutput | CalculatedFieldSimpleOutput) {
if (this.simpleMode && 'name' in value) {
value.name = value.name?.trim() ?? '';
@ -185,6 +187,10 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
if (this.disableType) {
value.type = this.outputForm.get('type').value;
}
if (value.type === OutputType.Timeseries && value.strategy.type === OutputStrategyType.IMMEDIATE) {
value = deepClone(value);
delete (value.strategy as any).useCustomTtl
}
this.propagateChange(value);
}
@ -227,7 +233,10 @@ export class CalculatedFieldOutputComponent implements ControlValueAccessor, Val
} else {
this.outputForm.get('strategy.saveTimeSeries').enable({emitEvent: false});
this.outputForm.get('strategy.saveLatest').enable({emitEvent: false});
this.outputForm.get('strategy.ttl').enable({emitEvent: false});
this.outputForm.get('strategy.useCustomTtl').enable({emitEvent: false});
if (this.outputForm.get('strategy.useCustomTtl').value) {
this.outputForm.get('strategy.ttl').enable({emitEvent: false});
}
}
}
}

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

@ -1248,15 +1248,15 @@
"send-web-sockets": "Send to WebSockets",
"save-calculated-fields": "Send to Calculated fields",
"update-attributes-only-on-value-change": "Save attributes only if the value changes",
"ttl": "TTL",
"ttl-required": "TTL is required.",
"ttl-min": "Only 0 minimum TTL is allowed.",
"ttl": "Custom TTL",
"ttl-required": "TTL is required",
"ttl-min": "Only 0 minimum TTL is allowed",
"hint": {
"strategy": "Strategy",
"processing-options": "Processing options",
"update-attributes-only-on-value-change": "Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.",
"update-attributes-only-on-value-change-enabled": "Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.",
"ttl": "If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied."
"ttl": "Uncheck to use the default system settings"
}
},
"aggregate-interval-type": "Aggregate interval type",

Loading…
Cancel
Save