UI: Improve multiple attributes input widget.
This commit is contained in:
parent
ac6717b99f
commit
244f8239ba
@ -21,7 +21,18 @@ export class TbMissingTranslationHandler implements MissingTranslationHandler {
|
||||
handle(params: MissingTranslationHandlerParams) {
|
||||
if (params.key && !params.key.startsWith(customTranslationsPrefix)) {
|
||||
console.warn('Translation for \'' + params.key + '\' doesn\'t exist');
|
||||
params.translateService.set(params.key, params.key);
|
||||
let translations: any;
|
||||
const parts = params.key.split('.');
|
||||
for (let i=parts.length-1; i>=0; i--) {
|
||||
const newTranslations = {};
|
||||
if (i === parts.length-1) {
|
||||
newTranslations[parts[i]] = params.key;
|
||||
} else {
|
||||
newTranslations[parts[i]] = translations;
|
||||
}
|
||||
translations = newTranslations;
|
||||
}
|
||||
params.translateService.setTranslation(params.translateService.currentLang, translations, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,174 +23,164 @@
|
||||
<fieldset *ngFor="let source of sources" [ngClass]="{'fields-group': settings.showGroupTitle}">
|
||||
<legend class="group-title" *ngIf="settings.showGroupTitle">{{ getGroupTitle(source.datasource) }}
|
||||
</legend>
|
||||
<div class="tb-multiple-input-layout layout-wrap"
|
||||
[ngClass]="{'vertical-alignment': isVerticalAlignment || changeAlignment}">
|
||||
<div *ngFor="let key of visibleKeys(source)"
|
||||
[ngStyle]="{width: (isVerticalAlignment || changeAlignment) ? '100%' : inputWidthSettings}">
|
||||
<div class="input-field" *ngIf="key.settings.dataKeyValueType === 'string'">
|
||||
<mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input matInput
|
||||
formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
type="text"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matPrefix>
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-field" *ngIf="key.settings.dataKeyValueType === 'double' ||
|
||||
key.settings.dataKeyValueType === 'integer'">
|
||||
<mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input matInput
|
||||
formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
type="number"
|
||||
step="{{key.settings.step}}"
|
||||
min="{{key.settings.minValue}}"
|
||||
max="{{key.settings.maxValue}}"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matPrefix>
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings,'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('min')">
|
||||
{{ getErrorMessageText(key.settings,'min') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('max')">
|
||||
{{ getErrorMessageText(key.settings,'max') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-field mat-block" *ngIf="key.settings.dataKeyValueType === 'booleanCheckbox'">
|
||||
<mat-checkbox formControlName="{{key.formId}}"
|
||||
(change)="inputChanged(source, key)">
|
||||
<span class="label-wrapper">{{key.label}}</span>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="input-field" *ngIf="key.settings.dataKeyValueType === 'JSON'">
|
||||
<mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
formControlName="{{key.formId}}"
|
||||
tb-json-to-string
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
[required]="key.settings.required"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)"
|
||||
/>
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matPrefix>
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<button [disabled]="key.settings.isEditable === 'disabled' || key.settings.isEditable === 'readonly'"
|
||||
type="button"
|
||||
matSuffix mat-icon-button
|
||||
(click)="openEditJSONDialog($event, key, source)">
|
||||
<mat-icon>open_in_new</mat-icon>
|
||||
</button>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings,'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('invalidJSON')">
|
||||
{{ getErrorMessageText(key.settings,'invalidJSON') | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-field mat-block" *ngIf="key.settings.dataKeyValueType === 'booleanSwitch'">
|
||||
<mat-slide-toggle formControlName="{{key.formId}}"
|
||||
[labelPosition]="key.settings.slideToggleLabelPosition"
|
||||
(change)="inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon">
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<span class="label-wrapper">{{key.label}}</span>
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<div class="input-field mat-block date-time-input" *ngIf="(key.settings.dataKeyValueType === 'dateTime') ||
|
||||
(key.settings.dataKeyValueType === 'date') ||
|
||||
(key.settings.dataKeyValueType === 'time')" fxLayout="column">
|
||||
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<mat-datetimepicker-toggle [for]="datePicker" matPrefix></mat-datetimepicker-toggle>
|
||||
<mat-datetimepicker #datePicker type="{{datePickerType(key.settings.dataKeyValueType)}}"
|
||||
openOnFocus="true"></mat-datetimepicker>
|
||||
<input matInput formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
[matDatetimepicker]="datePicker"
|
||||
(focus)="key.isFocused = true;"
|
||||
(blur)="key.isFocused = false;"
|
||||
(dateChange)="inputChanged(source, key)">
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('matDatepickerParse')">
|
||||
{{ getErrorMessageText(key.settings, 'invalidDate') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="input-field" *ngIf="key.settings.dataKeyValueType === 'select'">
|
||||
<mat-form-field class="mat-block" appearance="outline" subscriptSizing="dynamic">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<mat-select formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
(focus)="key.isFocused = true;"
|
||||
(selectionChange)="key.isFocused = false; inputChanged(source, key)">
|
||||
<mat-option *ngFor="let option of key.settings.selectOptions"
|
||||
[value]="option.value"
|
||||
[disabled]="key.settings.isEditable === 'readonly'">
|
||||
{{ getCustomTranslationText(option.label ? option.label : option.value) }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="tb-form-row space-between color-picker-input" *ngIf="key.settings.dataKeyValueType === 'color'">
|
||||
<div class="label-container">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon">
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
{{key.label}}
|
||||
</div>
|
||||
<tb-color-input asBoxInput
|
||||
[required]="key.settings.required"
|
||||
[requiredText]="getErrorMessageText(key.settings, 'required')"
|
||||
openOnInput
|
||||
formControlName="{{key.formId}}">
|
||||
<div class="tb-multiple-input-layout"
|
||||
[style]="{'grid-template-columns': 'repeat(' + columns + ', 1fr)', 'column-gap': settings.columnGap + 'px', 'row-gap': settings.rowGap + 'px'}">
|
||||
<ng-container *ngFor="let key of visibleKeys(source)">
|
||||
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'string'"
|
||||
[appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input matInput
|
||||
formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
type="text"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matIconPrefix>
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="['double', 'integer'].includes(key.settings.dataKeyValueType)"
|
||||
[appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input matInput
|
||||
formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
type="number"
|
||||
step="{{key.settings.step}}"
|
||||
min="{{key.settings.minValue}}"
|
||||
max="{{key.settings.maxValue}}"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matIconPrefix>
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings,'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('min')">
|
||||
{{ getErrorMessageText(key.settings,'min') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('max')">
|
||||
{{ getErrorMessageText(key.settings,'max') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'JSON'"
|
||||
[appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
formControlName="{{key.formId}}"
|
||||
tb-json-to-string
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
[required]="key.settings.required"
|
||||
(focus)="key.isFocused = true; focusInputElement($event)"
|
||||
(blur)="key.isFocused = false; inputChanged(source, key)"
|
||||
/>
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matIconPrefix>
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<button [disabled]="key.settings.isEditable === 'disabled' || key.settings.isEditable === 'readonly'"
|
||||
type="button"
|
||||
matSuffix mat-icon-button
|
||||
(click)="openEditJSONDialog($event, key, source)">
|
||||
<mat-icon>open_in_new</mat-icon>
|
||||
</button>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings,'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('invalidJSON')">
|
||||
{{ getErrorMessageText(key.settings,'invalidJSON') | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="['dateTime','date', 'time'].includes(key.settings.dataKeyValueType)"
|
||||
[appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<mat-datetimepicker-toggle [for]="datePicker" matPrefix></mat-datetimepicker-toggle>
|
||||
<mat-datetimepicker #datePicker type="{{datePickerType(key.settings.dataKeyValueType)}}"
|
||||
openOnFocus="true"></mat-datetimepicker>
|
||||
<input matInput formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
[matDatetimepicker]="datePicker"
|
||||
(focus)="key.isFocused = true;"
|
||||
(blur)="key.isFocused = false;"
|
||||
(dateChange)="inputChanged(source, key)">
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('matDatepickerParse')">
|
||||
{{ getErrorMessageText(key.settings, 'invalidDate') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'select'"
|
||||
[appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<mat-select formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
(focus)="key.isFocused = true;"
|
||||
(selectionChange)="key.isFocused = false; inputChanged(source, key)">
|
||||
<mat-option *ngFor="let option of key.settings.selectOptions"
|
||||
[value]="option.value"
|
||||
[disabled]="key.settings.isEditable === 'readonly'">
|
||||
{{ getCustomTranslationText(option.label ? option.label : option.value) }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matIconPrefix>
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'color'"
|
||||
class="color-input" [appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing"
|
||||
(click)="colorInput.openColorPickerPopup($event)">
|
||||
<mat-label>{{key.label}}</mat-label>
|
||||
<input matInput
|
||||
formControlName="{{key.formId}}"
|
||||
[required]="key.settings.required"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
type="text"
|
||||
(keydown)="$event.preventDefault();">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon" matIconPrefix>
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<tb-color-input #colorInput asBoxInput matSuffix
|
||||
colorClearButton
|
||||
[disabled]="multipleInputFormGroup.get(key.formId).disabled"
|
||||
[readonly]="key.settings.isEditable === 'readonly'"
|
||||
[ngModel]="multipleInputFormGroup.get(key.formId).value"
|
||||
(ngModelChange)="colorChanged(source, key, $event)"
|
||||
[ngModelOptions]="{ standalone: true }">
|
||||
</tb-color-input>
|
||||
</div>
|
||||
</div>
|
||||
<mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
|
||||
{{ getErrorMessageText(key.settings, 'required') }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-checkbox *ngIf="key.settings.dataKeyValueType === 'booleanCheckbox'"
|
||||
formControlName="{{key.formId}}"
|
||||
(change)="inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon">
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<span class="label-wrapper">{{key.label}}</span>
|
||||
</mat-checkbox>
|
||||
<mat-slide-toggle *ngIf="key.settings.dataKeyValueType === 'booleanSwitch'"
|
||||
formControlName="{{key.formId}}"
|
||||
[labelPosition]="key.settings.slideToggleLabelPosition"
|
||||
(change)="inputChanged(source, key)">
|
||||
<ng-container *ngIf="key.settings.icon || key.settings.safeCustomIcon">
|
||||
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||
</ng-container>
|
||||
<span class="label-wrapper">{{key.label}}</span>
|
||||
</mat-slide-toggle>
|
||||
</ng-container>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@ -216,3 +206,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<ng-template #iconPrefix let-key="key">
|
||||
<tb-icon *ngIf="!key.settings.safeCustomIcon; else customToggleIcon">{{key.settings.icon}}</tb-icon>
|
||||
<ng-template #customToggleIcon>
|
||||
<img class="mat-icon" [src]="key.settings.safeCustomIcon" alt="icon">
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
||||
@ -38,34 +38,7 @@
|
||||
}
|
||||
|
||||
.tb-multiple-input-layout {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.color-picker-input {
|
||||
padding: 7px 16px 7px 12px;
|
||||
margin: 0 10px 22px 0;
|
||||
border-color: rgba(0, 0, 0, 0.4);
|
||||
|
||||
.label-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mat-icon, img {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-field {
|
||||
padding-right: 10px;
|
||||
|
||||
mat-form-field {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.mat-mdc-slide-toggle {
|
||||
@ -74,17 +47,6 @@
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.date-time-input {
|
||||
.mat-mdc-form-field {
|
||||
width: 100%;
|
||||
margin: 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vertical-alignment {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&--buttons-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -113,18 +75,33 @@
|
||||
|
||||
:host ::ng-deep {
|
||||
.tb-multiple-input {
|
||||
.mat-mdc-slide-toggle .mdc-form-field {
|
||||
width: 100%;
|
||||
& > label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.mat-mdc-slide-toggle, .mat-mdc-checkbox {
|
||||
.mdc-form-field {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
.mat-icon {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
& > label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
.mat-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.mat-mdc-slide-toggle {
|
||||
.mdc-form-field {
|
||||
& > label {
|
||||
.mat-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.color-input {
|
||||
.mat-mdc-form-field-icon-suffix {
|
||||
padding: 0 8px 0 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ import {
|
||||
} from '@shared/components/dialog/json-object-edit-dialog.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||
import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
|
||||
|
||||
type FieldAlignment = 'row' | 'column';
|
||||
|
||||
@ -55,7 +56,7 @@ type MultipleInputWidgetDataKeyType = 'server' | 'shared' | 'timeseries';
|
||||
export type MultipleInputWidgetDataKeyValueType = 'string' | 'double' | 'integer' |
|
||||
'JSON' | 'booleanCheckbox' | 'booleanSwitch' |
|
||||
'dateTime' | 'date' | 'time' | 'select' | 'color';
|
||||
type MultipleInputWidgetDataKeyEditableType = 'editable' | 'disabled' | 'readonly';
|
||||
export type MultipleInputWidgetDataKeyEditableType = 'editable' | 'disabled' | 'readonly';
|
||||
|
||||
type ConvertGetValueFunction = (value: any, ctx: WidgetContext) => any;
|
||||
type ConvertSetValueFunction = (value: any, originValue: any, ctx: WidgetContext) => any;
|
||||
@ -71,6 +72,8 @@ interface MultipleInputWidgetSettings {
|
||||
groupTitle: string;
|
||||
fieldsAlignment: FieldAlignment;
|
||||
fieldsInRow: number;
|
||||
columnGap: number;
|
||||
rowGap: number;
|
||||
attributesShared?: boolean;
|
||||
}
|
||||
|
||||
@ -88,6 +91,8 @@ interface MultipleInputWidgetDataKeySettings {
|
||||
isEditable: MultipleInputWidgetDataKeyEditableType;
|
||||
disabledOnDataKey: string;
|
||||
dataKeyHidden: boolean;
|
||||
appearance: MatFormFieldAppearance;
|
||||
subscriptSizing: SubscriptSizing;
|
||||
step?: number;
|
||||
minValue?: number;
|
||||
maxValue?: number;
|
||||
@ -148,8 +153,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
private isSavingInProgress = false;
|
||||
|
||||
isVerticalAlignment: boolean;
|
||||
inputWidthSettings: string;
|
||||
changeAlignment: boolean;
|
||||
columns: number;
|
||||
saveButtonLabel: string;
|
||||
resetButtonLabel: string;
|
||||
|
||||
@ -228,15 +232,15 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
if (isUndefined(this.settings.fieldsInRow)) {
|
||||
this.settings.fieldsInRow = 2;
|
||||
}
|
||||
// For backward compatibility
|
||||
|
||||
this.isVerticalAlignment = !(this.settings.fieldsAlignment === 'row');
|
||||
|
||||
if (!this.isVerticalAlignment && this.settings.fieldsInRow) {
|
||||
this.inputWidthSettings = 100 / this.settings.fieldsInRow + '%';
|
||||
if (isUndefined(this.settings.columnGap)) {
|
||||
this.settings.columnGap = 10;
|
||||
}
|
||||
if (isUndefined(this.settings.rowGap)) {
|
||||
this.settings.rowGap = 5;
|
||||
}
|
||||
|
||||
this.updateWidgetDisplaying();
|
||||
this.updateColumns();
|
||||
}
|
||||
|
||||
private updateDatasources() {
|
||||
@ -284,6 +288,15 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
dataKey.settings.isEditable = 'editable';
|
||||
}
|
||||
}
|
||||
|
||||
if (isUndefined(dataKey.settings.appearance)) {
|
||||
dataKey.settings.appearance = 'outline';
|
||||
}
|
||||
|
||||
if (isUndefined(dataKey.settings.subscriptSizing)) {
|
||||
dataKey.settings.subscriptSizing = 'fixed';
|
||||
}
|
||||
|
||||
// For backward compatibility
|
||||
|
||||
if (dataKey.settings.dataKeyValueType === 'select') {
|
||||
@ -387,12 +400,6 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (key.settings.dataKeyValueType === 'color') {
|
||||
formControl.valueChanges.pipe(
|
||||
takeUntil(this.destroy$)
|
||||
).subscribe(() => {
|
||||
this.inputChanged(source, key);
|
||||
});
|
||||
}
|
||||
this.multipleInputFormGroup.addControl(key.formId, formControl);
|
||||
}
|
||||
@ -452,9 +459,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
}
|
||||
|
||||
if (key.settings.isEditable === 'editable' && key.settings.disabledOnDataKey) {
|
||||
const conditions = data.filter((item) => {
|
||||
return source.datasource === item.datasource && item.dataKey.name === key.settings.disabledOnDataKey;
|
||||
});
|
||||
const conditions = data.filter((item) =>
|
||||
source.datasource === item.datasource && item.dataKey.name === key.settings.disabledOnDataKey);
|
||||
if (conditions && conditions.length) {
|
||||
if (conditions[0].data.length) {
|
||||
if (conditions[0].data[0][1] === 'false') {
|
||||
@ -494,8 +500,17 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
return data;
|
||||
}
|
||||
|
||||
private updateWidgetDisplaying() {
|
||||
this.changeAlignment = (this.ctx.$container && this.ctx.$container[0].offsetWidth < 620);
|
||||
private updateColumns() {
|
||||
const changeAlignment = (this.ctx.$container && this.ctx.$container[0].offsetWidth < 620);
|
||||
if (changeAlignment) {
|
||||
this.columns = 1;
|
||||
} else {
|
||||
if (!this.isVerticalAlignment && this.settings.fieldsInRow) {
|
||||
this.columns = this.settings.fieldsInRow;
|
||||
} else {
|
||||
this.columns = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public onDataUpdated() {
|
||||
@ -504,7 +519,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
}
|
||||
|
||||
private resize() {
|
||||
this.updateWidgetDisplaying();
|
||||
this.updateColumns();
|
||||
this.ctx.detectChanges();
|
||||
}
|
||||
|
||||
@ -599,6 +614,13 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
public colorChanged(source: MultipleInputWidgetSource, key: MultipleInputWidgetDataKey, color: string) {
|
||||
this.multipleInputFormGroup.get(key.formId).setValue(color);
|
||||
this.multipleInputFormGroup.get(key.formId).markAsDirty();
|
||||
this.multipleInputFormGroup.get(key.formId).markAsTouched();
|
||||
this.inputChanged(source, key);
|
||||
}
|
||||
|
||||
public saveForm() {
|
||||
if (this.settings.showActionButtons) {
|
||||
this.save();
|
||||
@ -737,7 +759,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
||||
this.multipleInputFormGroup.reset(undefined, {emitEvent: false});
|
||||
this.sources.forEach((source) => {
|
||||
for (const key of this.visibleKeys(source)) {
|
||||
this.multipleInputFormGroup.get(key.formId).patchValue(key.value, {emitEvent: false});
|
||||
this.multipleInputFormGroup.get(key.formId).patchValue(key.value);
|
||||
}
|
||||
});
|
||||
this.multipleInputFormGroup.markAsPristine();
|
||||
|
||||
@ -93,11 +93,36 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field [fxShow]="updateMultipleAttributesKeySettingsForm.get('isEditable').value !== 'disabled'" fxFlex="50" class="mat-block">
|
||||
<mat-form-field [fxShow]="updateMultipleAttributesKeySettingsForm.get('isEditable').value === 'editable'" fxFlex="50" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.disable-on-datakey-name</mat-label>
|
||||
<input matInput formControlName="disabledOnDataKey">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
<section *ngIf="!['booleanSwitch', 'booleanCheckbox'].includes(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value)"
|
||||
fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px" fxLayoutAlign.gt-xs="start center">
|
||||
<mat-form-field fxFlex="50" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.field-appearance</mat-label>
|
||||
<mat-select formControlName="appearance">
|
||||
<mat-option [value]="'fill'">
|
||||
{{ 'widgets.input-widgets.appearance-fill' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'outline'">
|
||||
{{ 'widgets.input-widgets.appearance-outline' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="50" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.subscript-sizing</mat-label>
|
||||
<mat-select formControlName="subscriptSizing">
|
||||
<mat-option [value]="'fixed'">
|
||||
{{ 'widgets.input-widgets.subscript-sizing-fixed' | translate }}
|
||||
</mat-option>
|
||||
<mat-option [value]="'dynamic'">
|
||||
{{ 'widgets.input-widgets.subscript-sizing-dynamic' | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</fieldset>
|
||||
<fieldset [fxShow]="!updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value &&
|
||||
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'booleanSwitch'" class="fields-group">
|
||||
@ -208,7 +233,9 @@
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</fieldset>
|
||||
<fieldset [fxShow]="!updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value" class="fields-group">
|
||||
<fieldset [fxShow]="!updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value &&
|
||||
!['date', 'dateTime', 'time'].includes(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value)"
|
||||
class="fields-group">
|
||||
<legend class="group-title" translate>widgets.input-widgets.icon-settings</legend>
|
||||
<mat-slide-toggle formControlName="useCustomIcon" class="slide-block">
|
||||
{{ 'widgets.input-widgets.use-custom-icon' | translate }}
|
||||
|
||||
@ -24,7 +24,10 @@ import {
|
||||
dataKeySelectOptionValidator
|
||||
} from '@home/components/widget/lib/settings/input/datakey-select-option.component';
|
||||
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
||||
import { MultipleInputWidgetDataKeyValueType } from '@home/components/widget/lib/multiple-input-widget.component';
|
||||
import {
|
||||
MultipleInputWidgetDataKeyEditableType,
|
||||
MultipleInputWidgetDataKeyValueType
|
||||
} from '@home/components/widget/lib/multiple-input-widget.component';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-update-multiple-attributes-key-settings',
|
||||
@ -52,6 +55,8 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
||||
required: false,
|
||||
isEditable: 'editable',
|
||||
disabledOnDataKey: '',
|
||||
appearance: 'outline',
|
||||
subscriptSizing: 'fixed',
|
||||
|
||||
slideToggleLabelPosition: 'after',
|
||||
selectOptions: [],
|
||||
@ -92,6 +97,8 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
||||
required: [settings.required, []],
|
||||
isEditable: [settings.isEditable, []],
|
||||
disabledOnDataKey: [settings.disabledOnDataKey, []],
|
||||
appearance: [settings.appearance, []],
|
||||
subscriptSizing: [settings.subscriptSizing, []],
|
||||
|
||||
// Slide toggle settings
|
||||
|
||||
@ -146,7 +153,7 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
||||
const dataKeyValueType: MultipleInputWidgetDataKeyValueType =
|
||||
this.updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value;
|
||||
const required: boolean = this.updateMultipleAttributesKeySettingsForm.get('required').value;
|
||||
const isEditable: string = this.updateMultipleAttributesKeySettingsForm.get('isEditable').value;
|
||||
const isEditable: MultipleInputWidgetDataKeyEditableType = this.updateMultipleAttributesKeySettingsForm.get('isEditable').value;
|
||||
const useCustomIcon: boolean = this.updateMultipleAttributesKeySettingsForm.get('useCustomIcon').value;
|
||||
const useGetValueFunction: boolean = this.updateMultipleAttributesKeySettingsForm.get('useGetValueFunction').value;
|
||||
const useSetValueFunction: boolean = this.updateMultipleAttributesKeySettingsForm.get('useSetValueFunction').value;
|
||||
@ -163,10 +170,15 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
||||
this.updateMultipleAttributesKeySettingsForm.get('useGetValueFunction').enable({emitEvent: false});
|
||||
this.updateMultipleAttributesKeySettingsForm.get('useSetValueFunction').enable({emitEvent: false});
|
||||
|
||||
if (isEditable !== 'disabled') {
|
||||
if (isEditable === 'editable') {
|
||||
this.updateMultipleAttributesKeySettingsForm.get('disabledOnDataKey').enable({emitEvent: false});
|
||||
}
|
||||
|
||||
if (!['booleanSwitch', 'booleanCheckbox'].includes(dataKeyValueType)) {
|
||||
this.updateMultipleAttributesKeySettingsForm.get('appearance').enable({emitEvent: false});
|
||||
this.updateMultipleAttributesKeySettingsForm.get('subscriptSizing').enable({emitEvent: false});
|
||||
}
|
||||
|
||||
if (dataKeyValueType === 'booleanSwitch') {
|
||||
this.updateMultipleAttributesKeySettingsForm.get('slideToggleLabelPosition').enable({emitEvent: false});
|
||||
} else if (dataKeyValueType === 'select') {
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
</section>
|
||||
</fieldset>
|
||||
<fieldset class="fields-group">
|
||||
<legend class="group-title" translate>widgets.input-widgets.fields-alignment</legend>
|
||||
<legend class="group-title" translate>widgets.input-widgets.layout</legend>
|
||||
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px" fxLayoutAlign.gt-xs="start center">
|
||||
<mat-form-field fxFlex="50" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.fields-alignment</mat-label>
|
||||
@ -90,5 +90,15 @@
|
||||
<input matInput type="number" min="1" step="1" formControlName="fieldsInRow">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
<section fxLayout="column" fxLayout.gt-xs="row" fxLayoutGap.gt-xs="8px" fxLayoutAlign.gt-xs="start center">
|
||||
<mat-form-field fxFlex="50" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.row-gap</mat-label>
|
||||
<input matInput type="number" min="0" step="1" formControlName="rowGap">
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex="50" [fxShow]="updateMultipleAttributesWidgetSettingsForm.get('fieldsAlignment').value === 'row'" class="mat-block">
|
||||
<mat-label translate>widgets.input-widgets.column-gap</mat-label>
|
||||
<input matInput type="number" min="0" step="1" formControlName="columnGap">
|
||||
</mat-form-field>
|
||||
</section>
|
||||
</fieldset>
|
||||
</section>
|
||||
|
||||
@ -49,7 +49,9 @@ export class UpdateMultipleAttributesWidgetSettingsComponent extends WidgetSetti
|
||||
showGroupTitle: false,
|
||||
groupTitle: '',
|
||||
fieldsAlignment: 'row',
|
||||
fieldsInRow: 2
|
||||
fieldsInRow: 2,
|
||||
rowGap: 5,
|
||||
columnGap: 10
|
||||
};
|
||||
}
|
||||
|
||||
@ -77,6 +79,11 @@ export class UpdateMultipleAttributesWidgetSettingsComponent extends WidgetSetti
|
||||
|
||||
fieldsAlignment: [settings.fieldsAlignment, []],
|
||||
fieldsInRow: [settings.fieldsInRow, [Validators.min(1)]],
|
||||
|
||||
// Layout gap
|
||||
|
||||
rowGap: [settings.rowGap, [Validators.min(0)]],
|
||||
columnGap: [settings.columnGap, [Validators.min(0)]]
|
||||
});
|
||||
}
|
||||
|
||||
@ -105,13 +112,16 @@ export class UpdateMultipleAttributesWidgetSettingsComponent extends WidgetSetti
|
||||
}
|
||||
if (fieldsAlignment === 'row') {
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('fieldsInRow').enable();
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('columnGap').enable();
|
||||
} else {
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('fieldsInRow').disable();
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('columnGap').disable();
|
||||
}
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('updateAllValues').updateValueAndValidity({emitEvent});
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('saveButtonLabel').updateValueAndValidity({emitEvent});
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('resetButtonLabel').updateValueAndValidity({emitEvent});
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('groupTitle').updateValueAndValidity({emitEvent});
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('fieldsInRow').updateValueAndValidity({emitEvent});
|
||||
this.updateMultipleAttributesWidgetSettingsForm.get('columnGap').updateValueAndValidity({emitEvent});
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
class="tb-box-button"
|
||||
[disabled]="disabled"
|
||||
#matButton
|
||||
(click)="openColorPickerPopup($event, matButton)">
|
||||
(click)="openColorPickerPopup($event, matButton._elementRef)">
|
||||
<div class="tb-color-preview no-margin box" [ngClass]="{'disabled': disabled}">
|
||||
<div class="tb-color-result" [style]="!disabled ? {background: colorFormGroup.get('color').value} : {}"></div>
|
||||
</div>
|
||||
|
||||
@ -14,7 +14,16 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { ChangeDetectorRef, Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
Input,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
ViewContainerRef
|
||||
} from '@angular/core';
|
||||
import { PageComponent } from '@shared/components/page.component';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState } from '@core/core.state';
|
||||
@ -84,6 +93,10 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro
|
||||
@Input()
|
||||
disabled: boolean;
|
||||
|
||||
@Input()
|
||||
@coerceBoolean()
|
||||
readonly = false;
|
||||
|
||||
private modelValue: string;
|
||||
|
||||
private propagateChange = null;
|
||||
@ -151,43 +164,47 @@ export class ColorInputComponent extends PageComponent implements OnInit, Contro
|
||||
|
||||
showColorPicker($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.dialogs.colorPicker(this.colorFormGroup.get('color').value,
|
||||
this.colorClearButton).subscribe(
|
||||
(result) => {
|
||||
if (!result?.canceled) {
|
||||
this.colorFormGroup.patchValue(
|
||||
{color: result?.color}, {emitEvent: true}
|
||||
);
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
}
|
||||
);
|
||||
if (!this.disabled && !this.readonly) {
|
||||
this.dialogs.colorPicker(this.colorFormGroup.get('color').value,
|
||||
this.colorClearButton).subscribe(
|
||||
(result) => {
|
||||
if (!result?.canceled) {
|
||||
this.colorFormGroup.patchValue(
|
||||
{color: result?.color}, {emitEvent: true}
|
||||
);
|
||||
this.cd.markForCheck();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
openColorPickerPopup($event: Event, matButton: MatButton) {
|
||||
openColorPickerPopup($event: Event, element?: ElementRef) {
|
||||
if ($event) {
|
||||
$event.stopPropagation();
|
||||
}
|
||||
const trigger = matButton._elementRef.nativeElement;
|
||||
if (this.popoverService.hasPopover(trigger)) {
|
||||
this.popoverService.hidePopover(trigger);
|
||||
} else {
|
||||
const colorPickerPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
||||
this.viewContainerRef, ColorPickerPanelComponent, 'left', true, null,
|
||||
{
|
||||
color: this.colorFormGroup.get('color').value,
|
||||
colorClearButton: this.colorClearButton
|
||||
},
|
||||
{},
|
||||
{}, {}, true);
|
||||
colorPickerPopover.tbComponentRef.instance.popover = colorPickerPopover;
|
||||
colorPickerPopover.tbComponentRef.instance.colorSelected.subscribe((color) => {
|
||||
colorPickerPopover.hide();
|
||||
this.colorFormGroup.patchValue(
|
||||
{color}, {emitEvent: true}
|
||||
);
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
if (!this.disabled && !this.readonly) {
|
||||
const trigger = element ? element.nativeElement : $event.target;
|
||||
if (this.popoverService.hasPopover(trigger)) {
|
||||
this.popoverService.hidePopover(trigger);
|
||||
} else {
|
||||
const colorPickerPopover = this.popoverService.displayPopover(trigger, this.renderer,
|
||||
this.viewContainerRef, ColorPickerPanelComponent, 'left', true, null,
|
||||
{
|
||||
color: this.colorFormGroup.get('color').value,
|
||||
colorClearButton: this.colorClearButton
|
||||
},
|
||||
{},
|
||||
{}, {}, true);
|
||||
colorPickerPopover.tbComponentRef.instance.popover = colorPickerPopover;
|
||||
colorPickerPopover.tbComponentRef.instance.colorSelected.subscribe((color) => {
|
||||
colorPickerPopover.hide();
|
||||
this.colorFormGroup.patchValue(
|
||||
{color}, {emitEvent: true}
|
||||
);
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5329,6 +5329,9 @@
|
||||
"input-fields-alignment": "Input fields alignment",
|
||||
"input-fields-alignment-column": "Column (default)",
|
||||
"input-fields-alignment-row": "Row",
|
||||
"layout": "Layout",
|
||||
"row-gap": "Gap between rows in pixels",
|
||||
"column-gap": "Gap between columns in pixels",
|
||||
"latitude-field-required": "Latitude field required",
|
||||
"longitude-field-required": "Longitude field required",
|
||||
"attribute-settings": "Attribute settings",
|
||||
@ -5384,6 +5387,12 @@
|
||||
"ability-to-edit-attribute-disabled": "Disabled",
|
||||
"ability-to-edit-attribute-readonly": "Read-only",
|
||||
"disable-on-datakey-name": "Disable on false value of another datakey (specify datakey name)",
|
||||
"field-appearance": "Field appearance",
|
||||
"appearance-fill": "Fill",
|
||||
"appearance-outline": "Outline",
|
||||
"subscript-sizing": "Subscript sizing",
|
||||
"subscript-sizing-fixed": "Fixed",
|
||||
"subscript-sizing-dynamic": "Dynamic",
|
||||
"slide-toggle-settings": "Slide toggle settings",
|
||||
"slide-toggle-label-position": "Slide toggle label position",
|
||||
"slide-toggle-label-position-after": "After",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user