Merge pull request #12540 from ArtemDzhereleiko/AD/imp/multiple-input/radio
Radio button for multiple input widget
This commit is contained in:
commit
c5b744f6fd
@ -138,6 +138,28 @@
|
|||||||
{{ getErrorMessageText(key.settings, 'required') }}
|
{{ getErrorMessageText(key.settings, 'required') }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div *ngIf="key.settings.dataKeyValueType === 'radio'">
|
||||||
|
<mat-label>{{key.label}}</mat-label>
|
||||||
|
<mat-radio-group
|
||||||
|
[style]="{'display': 'grid', 'grid-template-columns': 'repeat(' + key.settings.radioColumns + ', 1fr)', 'column-gap': '5px', 'row-gap': '5px'}"
|
||||||
|
[labelPosition]="key.settings.radioLabelPosition"
|
||||||
|
(change)="inputChanged(source, key)"
|
||||||
|
formControlName="{{key.formId}}">
|
||||||
|
<mat-radio-button
|
||||||
|
[style]="radioButtonSelectedColor(key.settings.radioColor)"
|
||||||
|
[disabled]="key.settings.isEditable === 'readonly'"
|
||||||
|
*ngFor="let option of key.settings.selectOptions"
|
||||||
|
[value]="option.value">
|
||||||
|
<ng-container *ngIf="key.settings.icon || key.settings.customIconUrl" matIconPrefix>
|
||||||
|
<ng-container *ngTemplateOutlet="iconPrefix; context: {key: key}"></ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<span class="label-wrapper">
|
||||||
|
{{ getCustomTranslationText(option.label ? option.label : option.value) }}
|
||||||
|
</span>
|
||||||
|
</mat-radio-button>
|
||||||
|
</mat-radio-group>
|
||||||
|
</div>
|
||||||
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'color'"
|
<mat-form-field *ngIf="key.settings.dataKeyValueType === 'color'"
|
||||||
class="color-input" [appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing"
|
class="color-input" [appearance]="key.settings.appearance" [subscriptSizing]="key.settings.subscriptSizing"
|
||||||
(click)="colorInput.openColorPickerPopup($event)">
|
(click)="colorInput.openColorPickerPopup($event)">
|
||||||
|
|||||||
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
:host ::ng-deep {
|
:host ::ng-deep {
|
||||||
.tb-multiple-input {
|
.tb-multiple-input {
|
||||||
.mat-mdc-slide-toggle, .mat-mdc-checkbox {
|
.mat-mdc-slide-toggle, .mat-mdc-checkbox, .mat-mdc-radio-button {
|
||||||
.mdc-form-field {
|
.mdc-form-field {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
& > label {
|
& > label {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ type FieldAlignment = 'row' | 'column';
|
|||||||
type MultipleInputWidgetDataKeyType = 'server' | 'shared' | 'timeseries';
|
type MultipleInputWidgetDataKeyType = 'server' | 'shared' | 'timeseries';
|
||||||
export type MultipleInputWidgetDataKeyValueType = 'string' | 'double' | 'integer' |
|
export type MultipleInputWidgetDataKeyValueType = 'string' | 'double' | 'integer' |
|
||||||
'JSON' | 'booleanCheckbox' | 'booleanSwitch' |
|
'JSON' | 'booleanCheckbox' | 'booleanSwitch' |
|
||||||
'dateTime' | 'date' | 'time' | 'select' | 'color';
|
'dateTime' | 'date' | 'time' | 'select' | 'radio' | 'color';
|
||||||
export type MultipleInputWidgetDataKeyEditableType = 'editable' | 'disabled' | 'readonly';
|
export type MultipleInputWidgetDataKeyEditableType = 'editable' | 'disabled' | 'readonly';
|
||||||
|
|
||||||
type ConvertGetValueFunction = (value: any, ctx: WidgetContext) => any;
|
type ConvertGetValueFunction = (value: any, ctx: WidgetContext) => any;
|
||||||
@ -86,6 +86,9 @@ interface MultipleInputWidgetDataKeySettings {
|
|||||||
dataKeyValueType: MultipleInputWidgetDataKeyValueType;
|
dataKeyValueType: MultipleInputWidgetDataKeyValueType;
|
||||||
slideToggleLabelPosition?: 'after' | 'before';
|
slideToggleLabelPosition?: 'after' | 'before';
|
||||||
selectOptions: MultipleInputWidgetSelectOption[];
|
selectOptions: MultipleInputWidgetSelectOption[];
|
||||||
|
radioColor: string;
|
||||||
|
radioColumns: number;
|
||||||
|
radioLabelPosition?: 'after' | 'before';
|
||||||
required: boolean;
|
required: boolean;
|
||||||
isEditable: MultipleInputWidgetDataKeyEditableType;
|
isEditable: MultipleInputWidgetDataKeyEditableType;
|
||||||
disabledOnDataKey: string;
|
disabledOnDataKey: string;
|
||||||
@ -300,7 +303,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
|||||||
|
|
||||||
// For backward compatibility
|
// For backward compatibility
|
||||||
|
|
||||||
if (dataKey.settings.dataKeyValueType === 'select') {
|
if (dataKey.settings.dataKeyValueType === 'select' || dataKey.settings.dataKeyValueType === 'radio') {
|
||||||
dataKey.settings.selectOptions.forEach((option) => {
|
dataKey.settings.selectOptions.forEach((option) => {
|
||||||
if (option.value.toLowerCase() === 'null') {
|
if (option.value.toLowerCase() === 'null') {
|
||||||
option.value = null;
|
option.value = null;
|
||||||
@ -444,6 +447,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'select':
|
case 'select':
|
||||||
|
case 'radio':
|
||||||
value = keyValue !== null ? keyValue.toString() : null;
|
value = keyValue !== null ? keyValue.toString() : null;
|
||||||
break;
|
break;
|
||||||
case 'JSON':
|
case 'JSON':
|
||||||
@ -566,6 +570,12 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
|
|||||||
return this.getTranslatedErrorText(errorMessage, defaultMessage, messageValues);
|
return this.getTranslatedErrorText(errorMessage, defaultMessage, messageValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public radioButtonSelectedColor(radioColor: string) {
|
||||||
|
if (isDefinedAndNotNull(radioColor)) {
|
||||||
|
return `--mdc-radio-selected-icon-color: ${radioColor}; --mdc-radio-selected-focus-icon-color: ${radioColor}; --mdc-radio-selected-hover-icon-color: ${radioColor}; --mdc-radio-selected-pressed-icon-color: ${radioColor}; --mat-radio-checked-ripple-color: ${radioColor};`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public getTranslatedErrorText(errorMessage: string, defaultMessage: string, messageValues?: object): string {
|
public getTranslatedErrorText(errorMessage: string, defaultMessage: string, messageValues?: object): string {
|
||||||
let messageText;
|
let messageText;
|
||||||
if (errorMessage && errorMessage.length) {
|
if (errorMessage && errorMessage.length) {
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value" class="fields-group">
|
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value" class="fields-group">
|
||||||
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
|
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
|
||||||
|
<div class="flex flex-col">
|
||||||
<section class="flex flex-col gt-xs:flex-row gt-xs:items-center gt-xs:justify-start gt-xs:gap-2">
|
<section class="flex flex-col gt-xs:flex-row gt-xs:items-center gt-xs:justify-start gt-xs:gap-2">
|
||||||
<mat-form-field class="mat-block flex-full xs:max-h-50% gt-xs:max-w-50%">
|
<mat-form-field class="mat-block flex-full xs:max-h-50% gt-xs:max-w-50%">
|
||||||
<mat-label translate>widgets.input-widgets.datakey-type</mat-label>
|
<mat-label translate>widgets.input-widgets.datakey-type</mat-label>
|
||||||
@ -66,6 +67,9 @@
|
|||||||
<mat-option [value]="'select'">
|
<mat-option [value]="'select'">
|
||||||
{{ 'widgets.input-widgets.datakey-value-type-select' | translate }}
|
{{ 'widgets.input-widgets.datakey-value-type-select' | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
<mat-option [value]="'radio'">
|
||||||
|
{{ 'widgets.input-widgets.datakey-value-type-radio' | translate }}
|
||||||
|
</mat-option>
|
||||||
<mat-option [value]="'JSON'">
|
<mat-option [value]="'JSON'">
|
||||||
{{ 'widgets.input-widgets.datakey-value-type-json' | translate }}
|
{{ 'widgets.input-widgets.datakey-value-type-json' | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
@ -98,7 +102,7 @@
|
|||||||
<input matInput formControlName="disabledOnDataKey">
|
<input matInput formControlName="disabledOnDataKey">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
<section *ngIf="!['booleanSwitch', 'booleanCheckbox'].includes(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value)"
|
<section *ngIf="!['booleanSwitch', 'booleanCheckbox', 'radio'].includes(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value)"
|
||||||
class="flex flex-col gt-xs:flex-row gt-xs:items-center gt-xs:justify-start gt-xs:gap-2">
|
class="flex flex-col gt-xs:flex-row gt-xs:items-center gt-xs:justify-start gt-xs:gap-2">
|
||||||
<mat-form-field class="mat-block flex-full xs:max-h-50% gt-xs:max-w-50%">
|
<mat-form-field class="mat-block flex-full xs:max-h-50% gt-xs:max-w-50%">
|
||||||
<mat-label translate>widgets.input-widgets.field-appearance</mat-label>
|
<mat-label translate>widgets.input-widgets.field-appearance</mat-label>
|
||||||
@ -123,6 +127,7 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
||||||
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'booleanSwitch'" class="fields-group">
|
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'booleanSwitch'" class="fields-group">
|
||||||
@ -140,8 +145,10 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
||||||
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'select'" class="fields-group">
|
(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'select' && updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'radio')" class="fields-group">
|
||||||
<legend class="group-title" translate>widgets.input-widgets.select-options</legend>
|
<legend class="group-title">
|
||||||
|
{{ (updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'select' ? 'widgets.input-widgets.select-options' : 'widgets.input-widgets.radio-options') | translate }}
|
||||||
|
</legend>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
|
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
|
||||||
(cdkDropListDropped)="selectOptionDrop($event)">
|
(cdkDropListDropped)="selectOptionDrop($event)">
|
||||||
@ -155,18 +162,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!selectOptionsFormArray().controls.length">
|
<div *ngIf="!selectOptionsFormArray().controls.length">
|
||||||
<span translate
|
<span class="tb-prompt flex items-center justify-center">
|
||||||
class="tb-prompt flex items-center justify-center">widgets.input-widgets.no-select-options</span>
|
{{ (updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'select' ? 'widgets.input-widgets.no-select-options' : 'widgets.input-widgets.no-radio-options') | translate }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-top: 16px;">
|
<div style="padding-top: 16px;">
|
||||||
<button mat-raised-button color="primary"
|
<button mat-raised-button color="primary"
|
||||||
type="button"
|
type="button"
|
||||||
(click)="addSelectOption()">
|
(click)="addSelectOption()">
|
||||||
<span translate>widgets.input-widgets.add-select-option</span>
|
<span>
|
||||||
|
{{ (updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value === 'select' ? 'widgets.input-widgets.add-select-option' : 'widgets.input-widgets.add-radio-option') | translate }}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<div class="tb-form-panel mb-3.5"
|
||||||
|
[class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
||||||
|
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'radio'">
|
||||||
|
<div class="tb-form-panel-title" translate>widgets.input-widgets.radio-button-settings</div>
|
||||||
|
<div class="tb-form-row space-between">
|
||||||
|
<div>{{ 'widgets.input-widgets.color' | translate }}</div>
|
||||||
|
<tb-color-input asBoxInput
|
||||||
|
formControlName="radioColor">
|
||||||
|
</tb-color-input>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-row space-between">
|
||||||
|
<div>{{ 'widgets.input-widgets.columns' | translate }}</div>
|
||||||
|
<mat-form-field appearance="outline" class="number" subscriptSizing="dynamic">
|
||||||
|
<input matInput formControlName="radioColumns" type="number" min="0" step="1" placeholder="{{ 'widget-config.set' | translate }}">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="tb-form-row space-between">
|
||||||
|
<div>{{ 'widgets.input-widgets.radio-label-position' | translate }}</div>
|
||||||
|
<mat-form-field class="medium-width" appearance="outline" subscriptSizing="dynamic">
|
||||||
|
<mat-select formControlName="radioLabelPosition">
|
||||||
|
<mat-option [value]="'after'">
|
||||||
|
{{ 'widgets.input-widgets.radio-label-position-after' | translate }}
|
||||||
|
</mat-option>
|
||||||
|
<mat-option [value]="'before'">
|
||||||
|
{{ 'widgets.input-widgets.radio-label-position-before' | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
<fieldset [class.!hidden]="updateMultipleAttributesKeySettingsForm.get('dataKeyHidden').value ||
|
||||||
(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'integer' &&
|
(updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'integer' &&
|
||||||
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'double')" class="fields-group">
|
updateMultipleAttributesKeySettingsForm.get('dataKeyValueType').value !== 'double')" class="fields-group">
|
||||||
|
|||||||
@ -60,6 +60,9 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
|||||||
|
|
||||||
slideToggleLabelPosition: 'after',
|
slideToggleLabelPosition: 'after',
|
||||||
selectOptions: [],
|
selectOptions: [],
|
||||||
|
radioColor: null,
|
||||||
|
radioColumns: 1,
|
||||||
|
radioLabelPosition: 'after',
|
||||||
step: 1,
|
step: 1,
|
||||||
minValue: null,
|
minValue: null,
|
||||||
maxValue: null,
|
maxValue: null,
|
||||||
@ -104,10 +107,16 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
|||||||
|
|
||||||
slideToggleLabelPosition: [settings.slideToggleLabelPosition, []],
|
slideToggleLabelPosition: [settings.slideToggleLabelPosition, []],
|
||||||
|
|
||||||
// Select options
|
// Select/Radio options
|
||||||
|
|
||||||
selectOptions: this.prepareSelectOptionsFormArray(settings.selectOptions),
|
selectOptions: this.prepareSelectOptionsFormArray(settings.selectOptions),
|
||||||
|
|
||||||
|
// Radio settings
|
||||||
|
|
||||||
|
radioColor: [settings.radioColor, []],
|
||||||
|
radioColumns: [settings.radioColumns, []],
|
||||||
|
radioLabelPosition: [settings.radioLabelPosition, []],
|
||||||
|
|
||||||
// Numeric field settings
|
// Numeric field settings
|
||||||
|
|
||||||
step: [settings.step, [Validators.min(0)]],
|
step: [settings.step, [Validators.min(0)]],
|
||||||
@ -183,6 +192,11 @@ export class UpdateMultipleAttributesKeySettingsComponent extends WidgetSettings
|
|||||||
this.updateMultipleAttributesKeySettingsForm.get('slideToggleLabelPosition').enable({emitEvent: false});
|
this.updateMultipleAttributesKeySettingsForm.get('slideToggleLabelPosition').enable({emitEvent: false});
|
||||||
} else if (dataKeyValueType === 'select') {
|
} else if (dataKeyValueType === 'select') {
|
||||||
this.updateMultipleAttributesKeySettingsForm.get('selectOptions').enable({emitEvent: false});
|
this.updateMultipleAttributesKeySettingsForm.get('selectOptions').enable({emitEvent: false});
|
||||||
|
} else if (dataKeyValueType === 'radio') {
|
||||||
|
this.updateMultipleAttributesKeySettingsForm.get('selectOptions').enable({emitEvent: false});
|
||||||
|
this.updateMultipleAttributesKeySettingsForm.get('radioColor').enable({emitEvent: false});
|
||||||
|
this.updateMultipleAttributesKeySettingsForm.get('radioColumns').enable({emitEvent: false});
|
||||||
|
this.updateMultipleAttributesKeySettingsForm.get('radioLabelPosition').enable({emitEvent: false});
|
||||||
} else if (dataKeyValueType === 'integer' || dataKeyValueType === 'double') {
|
} else if (dataKeyValueType === 'integer' || dataKeyValueType === 'double') {
|
||||||
this.updateMultipleAttributesKeySettingsForm.get('step').enable({emitEvent: false});
|
this.updateMultipleAttributesKeySettingsForm.get('step').enable({emitEvent: false});
|
||||||
this.updateMultipleAttributesKeySettingsForm.get('minValue').enable({emitEvent: false});
|
this.updateMultipleAttributesKeySettingsForm.get('minValue').enable({emitEvent: false});
|
||||||
|
|||||||
@ -7400,6 +7400,7 @@
|
|||||||
"datakey-value-type-date": "Date",
|
"datakey-value-type-date": "Date",
|
||||||
"datakey-value-type-time": "Time",
|
"datakey-value-type-time": "Time",
|
||||||
"datakey-value-type-select": "Select",
|
"datakey-value-type-select": "Select",
|
||||||
|
"datakey-value-type-radio": "Radio",
|
||||||
"datakey-value-type-color": "Color",
|
"datakey-value-type-color": "Color",
|
||||||
"value-is-required": "Value is required",
|
"value-is-required": "Value is required",
|
||||||
"ability-to-edit-attribute": "Ability to edit attribute",
|
"ability-to-edit-attribute": "Ability to edit attribute",
|
||||||
@ -7440,7 +7441,16 @@
|
|||||||
"set-value-function": "setValue function",
|
"set-value-function": "setValue function",
|
||||||
"json-invalid": "JSON value has an invalid format",
|
"json-invalid": "JSON value has an invalid format",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"cancel-button-label": "'Cancel' button label"
|
"cancel-button-label": "'Cancel' button label",
|
||||||
|
"radio-button-settings": "Radio button settings",
|
||||||
|
"color": "Color",
|
||||||
|
"columns": "Columns",
|
||||||
|
"radio-options": "Radio options",
|
||||||
|
"no-radio-options": "No radio options configured",
|
||||||
|
"add-radio-option": "Add radio option",
|
||||||
|
"radio-label-position": "Label position",
|
||||||
|
"radio-label-position-before": "Before",
|
||||||
|
"radio-label-position-after": "After"
|
||||||
},
|
},
|
||||||
"invalid-qr-code-text": "Invalid input text for QR code. Input should have a string type",
|
"invalid-qr-code-text": "Invalid input text for QR code. Input should have a string type",
|
||||||
"qr-code": {
|
"qr-code": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user