UI: Implement input widgets settings forms

This commit is contained in:
Igor Kulikov 2022-04-29 17:34:08 +03:00
parent 03ddc2c378
commit f71b1a63fd
25 changed files with 1720 additions and 26 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,84 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="deviceClaimingWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-button-label</mat-label>
<input matInput formControlName="labelClaimButon">
</mat-form-field>
<mat-slide-toggle class="slide-block" formControlName="deviceSecret">
{{ 'widgets.input-widgets.show-secret-key-field' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.input-widgets.labels-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="deviceClaimingWidgetSettingsForm.get('showLabel').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showLabel" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.input-widgets.show-labels' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<section fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.device-name-label</mat-label>
<input matInput formControlName="deviceLabel">
</mat-form-field>
<mat-form-field [fxShow]="deviceClaimingWidgetSettingsForm.get('deviceSecret').value" fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.secret-key-label</mat-label>
<input matInput formControlName="secretKeyLabel">
</mat-form-field>
</section>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.messages-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-device-success-message</mat-label>
<input matInput formControlName="successfulClaimDevice">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-device-not-found-message</mat-label>
<input matInput formControlName="deviceNotFound">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-device-failed-message</mat-label>
<input matInput formControlName="failedClaimDevice">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-device-name-required-message</mat-label>
<input matInput formControlName="requiredErrorDevice">
</mat-form-field>
<mat-form-field [fxShow]="deviceClaimingWidgetSettingsForm.get('deviceSecret').value" fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.claim-device-secret-key-required-message</mat-label>
<input matInput formControlName="requiredErrorSecretKey">
</mat-form-field>
</fieldset>
</section>

View File

@ -0,0 +1,110 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-device-claiming-widget-settings',
templateUrl: './device-claiming-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class DeviceClaimingWidgetSettingsComponent extends WidgetSettingsComponent {
deviceClaimingWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.deviceClaimingWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
labelClaimButon: '',
deviceSecret: false,
showLabel: true,
deviceLabel: '',
secretKeyLabel: '',
successfulClaimDevice: '',
deviceNotFound: '',
failedClaimDevice: '',
requiredErrorDevice: '',
requiredErrorSecretKey: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.deviceClaimingWidgetSettingsForm = this.fb.group({
// General settings
widgetTitle: [settings.widgetTitle, []],
labelClaimButon: [settings.labelClaimButon, []],
deviceSecret: [settings.deviceSecret, []],
// Labels settings
showLabel: [settings.showLabel, []],
deviceLabel: [settings.deviceLabel, []],
secretKeyLabel: [settings.secretKeyLabel, []],
// Message settings
successfulClaimDevice: [settings.successfulClaimDevice, []],
deviceNotFound: [settings.deviceNotFound, []],
failedClaimDevice: [settings.failedClaimDevice, []],
requiredErrorDevice: [settings.requiredErrorDevice, []],
requiredErrorSecretKey: [settings.requiredErrorSecretKey, []]
});
}
protected validatorTriggers(): string[] {
return ['deviceSecret', 'showLabel'];
}
protected updateValidators(emitEvent: boolean) {
const deviceSecret: boolean = this.deviceClaimingWidgetSettingsForm.get('deviceSecret').value;
const showLabel: boolean = this.deviceClaimingWidgetSettingsForm.get('showLabel').value;
if (deviceSecret) {
if (showLabel) {
this.deviceClaimingWidgetSettingsForm.get('secretKeyLabel').enable();
} else {
this.deviceClaimingWidgetSettingsForm.get('secretKeyLabel').disable();
}
this.deviceClaimingWidgetSettingsForm.get('requiredErrorSecretKey').enable();
} else {
this.deviceClaimingWidgetSettingsForm.get('requiredErrorSecretKey').disable();
this.deviceClaimingWidgetSettingsForm.get('secretKeyLabel').disable();
}
if (showLabel) {
this.deviceClaimingWidgetSettingsForm.get('deviceLabel').enable();
} else {
this.deviceClaimingWidgetSettingsForm.get('deviceLabel').disable();
}
this.deviceClaimingWidgetSettingsForm.get('secretKeyLabel').updateValueAndValidity({emitEvent});
this.deviceClaimingWidgetSettingsForm.get('deviceLabel').updateValueAndValidity({emitEvent});
this.deviceClaimingWidgetSettingsForm.get('requiredErrorSecretKey').updateValueAndValidity({emitEvent});
}
}

View File

@ -0,0 +1,59 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="photoCameraInputWidgetSettingsForm">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.image-settings</legend>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.image-format</mat-label>
<mat-select formControlName="imageFormat">
<mat-option [value]="'image/jpeg'">
{{ 'widgets.input-widgets.image-format-jpeg' | translate }}
</mat-option>
<mat-option [value]="'image/png'">
{{ 'widgets.input-widgets.image-format-png' | translate }}
</mat-option>
<mat-option [value]="'image/webp'">
{{ 'widgets.input-widgets.image-format-webp' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.image-quality</mat-label>
<input matInput type="number" min="0" max="1" formControlName="imageQuality">
</mat-form-field>
</section>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.max-image-width</mat-label>
<input matInput type="number" min="1" formControlName="maxWidth">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.max-image-height</mat-label>
<input matInput type="number" min="1" formControlName="maxHeight">
</mat-form-field>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,67 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-photo-camera-input-widget-settings',
templateUrl: './photo-camera-input-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class PhotoCameraInputWidgetSettingsComponent extends WidgetSettingsComponent {
photoCameraInputWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.photoCameraInputWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
imageFormat: 'image/png',
imageQuality: 0.92,
maxWidth: 640,
maxHeight: 480
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.photoCameraInputWidgetSettingsForm = this.fb.group({
// General settings
widgetTitle: [settings.widgetTitle, []],
// Image settings
imageFormat: [settings.imageFormat, []],
imageQuality: [settings.imageQuality, [Validators.min(0), Validators.max(1)]],
maxWidth: [settings.maxWidth, [Validators.min(1)]],
maxHeight: [settings.maxHeight, [Validators.min(1)]]
});
}
}

View File

@ -0,0 +1,47 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateAttributeGeneralSettingsFormGroup">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-slide-toggle fxFlex fxFlex.gt-sm="20" formControlName="showLabel">
{{ 'widgets.input-widgets.show-label' | translate }}
</mat-slide-toggle>
<mat-form-field *ngIf="hasLabelValue" fxFlex fxFlex.gt-sm="80" class="mat-block">
<mat-label translate>widgets.input-widgets.label</mat-label>
<input matInput formControlName="labelValue">
</mat-form-field>
</section>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-slide-toggle fxFlex fxFlex.gt-sm="20" formControlName="isRequired">
{{ 'widgets.input-widgets.required' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex fxFlex.gt-sm="80" class="mat-block">
<mat-label translate>widgets.input-widgets.required-error-message</mat-label>
<input matInput formControlName="requiredErrorMessage">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="showResultMessage" class="slide-block">
{{ 'widgets.input-widgets.show-result-message' | translate }}
</mat-slide-toggle>
</fieldset>
</section>

View File

@ -0,0 +1,172 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
FormControl,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
export interface UpdateAttributeGeneralSettings {
widgetTitle: string;
showLabel: boolean;
labelValue?: string;
isRequired: boolean;
requiredErrorMessage: string;
showResultMessage: boolean;
}
export function updateAttributeGeneralDefaultSettings(hasLabelValue = true): UpdateAttributeGeneralSettings {
const updateAttributeGeneralSettings: UpdateAttributeGeneralSettings = {
widgetTitle: '',
showLabel: true,
isRequired: true,
requiredErrorMessage: '',
showResultMessage: true
};
if (hasLabelValue) {
updateAttributeGeneralSettings.labelValue = '';
}
return updateAttributeGeneralSettings;
}
@Component({
selector: 'tb-update-attribute-general-settings',
templateUrl: './update-attribute-general-settings.component.html',
styleUrls: ['./../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => UpdateAttributeGeneralSettingsComponent),
multi: true
}
]
})
export class UpdateAttributeGeneralSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator {
@Input()
disabled: boolean;
@Input()
hasLabelValue = true;
private modelValue: UpdateAttributeGeneralSettings;
private propagateChange = null;
public updateAttributeGeneralSettingsFormGroup: FormGroup;
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private fb: FormBuilder) {
super(store);
}
ngOnInit(): void {
this.updateAttributeGeneralSettingsFormGroup = this.fb.group({
widgetTitle: ['', []],
showLabel: [true, []],
isRequired: [true, []],
requiredErrorMessage: ['', []],
showResultMessage: [true, []]
});
if (this.hasLabelValue) {
this.updateAttributeGeneralSettingsFormGroup.addControl('labelValue', this.fb.control('', []));
this.updateAttributeGeneralSettingsFormGroup.get('showLabel').valueChanges.subscribe(() => {
this.updateValidators(true);
});
}
this.updateAttributeGeneralSettingsFormGroup.get('isRequired').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.updateAttributeGeneralSettingsFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateValidators(false);
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
this.updateAttributeGeneralSettingsFormGroup.disable({emitEvent: false});
} else {
this.updateAttributeGeneralSettingsFormGroup.enable({emitEvent: false});
}
}
writeValue(value: UpdateAttributeGeneralSettings): void {
this.modelValue = value;
this.updateAttributeGeneralSettingsFormGroup.patchValue(
value, {emitEvent: false}
);
this.updateValidators(false);
}
public validate(c: FormControl) {
return this.updateAttributeGeneralSettingsFormGroup.valid ? null : {
updateAttributeGeneralSettings: {
valid: false,
},
};
}
private updateModel() {
const value: UpdateAttributeGeneralSettings = this.updateAttributeGeneralSettingsFormGroup.value;
this.modelValue = value;
this.propagateChange(this.modelValue);
}
private updateValidators(emitEvent?: boolean): void {
if (this.hasLabelValue) {
const showLabel: boolean = this.updateAttributeGeneralSettingsFormGroup.get('showLabel').value;
if (showLabel) {
this.updateAttributeGeneralSettingsFormGroup.get('labelValue').enable({emitEvent});
} else {
this.updateAttributeGeneralSettingsFormGroup.get('labelValue').disable({emitEvent});
}
this.updateAttributeGeneralSettingsFormGroup.get('labelValue').updateValueAndValidity({emitEvent: false});
}
const isRequired: boolean = this.updateAttributeGeneralSettingsFormGroup.get('isRequired').value;
if (isRequired) {
this.updateAttributeGeneralSettingsFormGroup.get('requiredErrorMessage').enable({emitEvent});
} else {
this.updateAttributeGeneralSettingsFormGroup.get('requiredErrorMessage').disable({emitEvent});
}
this.updateAttributeGeneralSettingsFormGroup.get('requiredErrorMessage').updateValueAndValidity({emitEvent: false});
}
}

View File

@ -0,0 +1,42 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateBooleanAttributeWidgetSettingsForm">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<mat-slide-toggle formControlName="showResultMessage" class="slide-block">
{{ 'widgets.input-widgets.show-result-message' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.checkbox-settings</legend>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.true-label</mat-label>
<input matInput formControlName="trueValue">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.false-label</mat-label>
<input matInput formControlName="falseValue">
</mat-form-field>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,58 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-update-boolean-attribute-widget-settings',
templateUrl: './update-boolean-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateBooleanAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateBooleanAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateBooleanAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
showResultMessage: true,
trueValue: '',
falseValue: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateBooleanAttributeWidgetSettingsForm = this.fb.group({
widgetTitle: [settings.widgetTitle, []],
showResultMessage: [settings.showResultMessage, []],
trueValue: [settings.trueValue, []],
falseValue: [settings.falseValue, []]
});
}
}

View File

@ -0,0 +1,30 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateDateAttributeWidgetSettingsForm" fxLayout="column">
<tb-update-attribute-general-settings
[hasLabelValue]="false"
formControlName="updateAttributeGeneralSettings">
</tb-update-attribute-general-settings>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.datetime-field-settings</legend>
<mat-slide-toggle formControlName="showTimeInput" class="slide-block">
{{ 'widgets.input-widgets.display-time-input' | translate }}
</mat-slide-toggle>
</fieldset>
</section>

View File

@ -0,0 +1,73 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone } from '@core/utils';
import {
updateAttributeGeneralDefaultSettings
} from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component';
@Component({
selector: 'tb-update-date-attribute-widget-settings',
templateUrl: './update-date-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateDateAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateDateAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateDateAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
...updateAttributeGeneralDefaultSettings(false),
showTimeInput: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateDateAttributeWidgetSettingsForm = this.fb.group({
updateAttributeGeneralSettings: [settings.updateAttributeGeneralSettings, []],
showTimeInput: [settings.showTimeInput, []]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const updateAttributeGeneralSettings = deepClone(settings, ['showTimeInput']);
return {
updateAttributeGeneralSettings,
showTimeInput: settings.showTimeInput
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return {
...settings.updateAttributeGeneralSettings,
showTimeInput: settings.showTimeInput
};
}
}

View File

@ -0,0 +1,36 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateDoubleAttributeWidgetSettingsForm" fxLayout="column">
<tb-update-attribute-general-settings
formControlName="updateAttributeGeneralSettings">
</tb-update-attribute-general-settings>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.double-field-settings</legend>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.min-value</mat-label>
<input matInput type="number" step="any" formControlName="minValue">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.max-value</mat-label>
<input matInput type="number" step="any" formControlName="maxValue">
</mat-form-field>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,77 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone } from '@core/utils';
import {
updateAttributeGeneralDefaultSettings
} from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component';
@Component({
selector: 'tb-update-double-attribute-widget-settings',
templateUrl: './update-double-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateDoubleAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateDoubleAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateDoubleAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
...updateAttributeGeneralDefaultSettings(),
minValue: null,
maxValue: null
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateDoubleAttributeWidgetSettingsForm = this.fb.group({
updateAttributeGeneralSettings: [settings.updateAttributeGeneralSettings, []],
minValue: [settings.minValue, []],
maxValue: [settings.maxValue, []]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const updateAttributeGeneralSettings = deepClone(settings, ['minValue', 'maxValue']);
return {
updateAttributeGeneralSettings,
minValue: settings.minValue,
maxValue: settings.maxValue
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return {
...settings.updateAttributeGeneralSettings,
minValue: settings.minValue,
maxValue: settings.maxValue
};
}
}

View File

@ -0,0 +1,46 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateImageAttributeWidgetSettingsForm">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<mat-slide-toggle formControlName="showResultMessage" class="slide-block">
{{ 'widgets.input-widgets.show-result-message' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.image-input-settings</legend>
<section fxLayout="column">
<mat-slide-toggle formControlName="displayPreview" class="slide-block">
{{ 'widgets.input-widgets.display-preview' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="displayClearButton" class="slide-block">
{{ 'widgets.input-widgets.display-clear-button' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="displayApplyButton" class="slide-block">
{{ 'widgets.input-widgets.display-apply-button' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="displayDiscardButton" class="slide-block">
{{ 'widgets.input-widgets.display-discard-button' | translate }}
</mat-slide-toggle>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,62 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-update-image-attribute-widget-settings',
templateUrl: './update-image-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateImageAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateImageAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateImageAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
showResultMessage: true,
displayPreview: true,
displayClearButton: false,
displayApplyButton: true,
displayDiscardButton: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateImageAttributeWidgetSettingsForm = this.fb.group({
widgetTitle: [settings.widgetTitle, []],
showResultMessage: [settings.showResultMessage, []],
displayPreview: [settings.displayPreview, []],
displayClearButton: [settings.displayClearButton, []],
displayApplyButton: [settings.displayApplyButton, []],
displayDiscardButton: [settings.displayDiscardButton, []]
});
}
}

View File

@ -0,0 +1,36 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateIntegerAttributeWidgetSettingsForm" fxLayout="column">
<tb-update-attribute-general-settings
formControlName="updateAttributeGeneralSettings">
</tb-update-attribute-general-settings>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.integer-field-settings</legend>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.min-value</mat-label>
<input matInput type="number" step="1" formControlName="minValue">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.max-value</mat-label>
<input matInput type="number" step="1" formControlName="maxValue">
</mat-form-field>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,77 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone } from '@core/utils';
import {
updateAttributeGeneralDefaultSettings
} from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component';
@Component({
selector: 'tb-update-integer-attribute-widget-settings',
templateUrl: './update-integer-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateIntegerAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateIntegerAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateIntegerAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
...updateAttributeGeneralDefaultSettings(),
minValue: null,
maxValue: null,
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateIntegerAttributeWidgetSettingsForm = this.fb.group({
updateAttributeGeneralSettings: [settings.updateAttributeGeneralSettings, []],
minValue: [settings.minValue, []],
maxValue: [settings.maxValue, []]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const updateAttributeGeneralSettings = deepClone(settings, ['minValue', 'maxValue']);
return {
updateAttributeGeneralSettings,
minValue: settings.minValue,
maxValue: settings.maxValue
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return {
...settings.updateAttributeGeneralSettings,
minValue: settings.minValue,
maxValue: settings.maxValue
};
}
}

View File

@ -0,0 +1,68 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateJsonAttributeWidgetSettingsForm">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-slide-toggle fxFlex fxFlex.gt-sm="20" formControlName="showLabel">
{{ 'widgets.input-widgets.show-label' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex fxFlex.gt-sm="80" class="mat-block">
<mat-label translate>widgets.input-widgets.label</mat-label>
<input matInput formControlName="labelValue">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="showResultMessage" class="slide-block">
{{ 'widgets.input-widgets.show-result-message' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.attribute-settings</legend>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px" fxLayoutAlign.gt-sm="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-mode</mat-label>
<mat-select formControlName="widgetMode">
<mat-option [value]="'ATTRIBUTE'">
{{ 'widgets.input-widgets.widget-mode-update-attribute' | translate }}
</mat-option>
<mat-option [value]="'TIME_SERIES'">
{{ 'widgets.input-widgets.widget-mode-update-timeseries' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field [fxShow]="updateJsonAttributeWidgetSettingsForm.get('widgetMode').value === 'ATTRIBUTE'" fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.attribute-scope</mat-label>
<mat-select formControlName="attributeScope">
<mat-option [value]="'SERVER_SCOPE'">
{{ 'widgets.input-widgets.attribute-scope-server' | translate }}
</mat-option>
<mat-option [value]="'SHARED_SCOPE'">
{{ 'widgets.input-widgets.attribute-scope-shared' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>
<mat-slide-toggle formControlName="attributeRequired" class="slide-block">
{{ 'widgets.input-widgets.value-required' | translate }}
</mat-slide-toggle>
</fieldset>
</section>

View File

@ -0,0 +1,93 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-update-json-attribute-widget-settings',
templateUrl: './update-json-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateJsonAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateJsonAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateJsonAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
showLabel: true,
labelValue: '',
showResultMessage: true,
widgetMode: 'ATTRIBUTE',
attributeScope: 'SERVER_SCOPE',
attributeRequired: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateJsonAttributeWidgetSettingsForm = this.fb.group({
// General settings
widgetTitle: [settings.widgetTitle, []],
showLabel: [settings.showLabel, []],
labelValue: [settings.labelValue, []],
showResultMessage: [settings.showResultMessage, []],
// Attribute settings
widgetMode: [settings.widgetMode, []],
attributeScope: [settings.attributeScope, []],
attributeRequired: [settings.attributeRequired, []]
});
}
protected validatorTriggers(): string[] {
return ['showLabel', 'widgetMode'];
}
protected updateValidators(emitEvent: boolean) {
const showLabel: boolean = this.updateJsonAttributeWidgetSettingsForm.get('showLabel').value;
const widgetMode: string = this.updateJsonAttributeWidgetSettingsForm.get('widgetMode').value;
if (showLabel) {
this.updateJsonAttributeWidgetSettingsForm.get('labelValue').enable();
} else {
this.updateJsonAttributeWidgetSettingsForm.get('labelValue').disable();
}
if (widgetMode === 'ATTRIBUTE') {
this.updateJsonAttributeWidgetSettingsForm.get('attributeScope').enable();
} else {
this.updateJsonAttributeWidgetSettingsForm.get('attributeScope').disable();
}
this.updateJsonAttributeWidgetSettingsForm.get('labelValue').updateValueAndValidity({emitEvent});
this.updateJsonAttributeWidgetSettingsForm.get('attributeScope').updateValueAndValidity({emitEvent});
}
}

View File

@ -0,0 +1,84 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateLocationAttributeWidgetSettingsForm">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.general-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.widget-title</mat-label>
<input matInput formControlName="widgetTitle">
</mat-form-field>
<mat-slide-toggle formControlName="showResultMessage" class="slide-block">
{{ 'widgets.input-widgets.show-result-message' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.latitude-key-name</mat-label>
<input matInput formControlName="latKeyName">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.longitude-key-name</mat-label>
<input matInput formControlName="lngKeyName">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="showGetLocation" class="slide-block">
{{ 'widgets.input-widgets.show-get-location-button' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="enableHighAccuracy" class="slide-block">
{{ 'widgets.input-widgets.use-high-accuracy' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.location-fields-settings</legend>
<mat-slide-toggle formControlName="showLabel" class="slide-block">
{{ 'widgets.input-widgets.show-label' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.latitude-label</mat-label>
<input matInput formControlName="latLabel">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.longitude-label</mat-label>
<input matInput formControlName="lngLabel">
</mat-form-field>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.input-fields-alignment</mat-label>
<mat-select formControlName="inputFieldsAlignment">
<mat-option [value]="'column'">
{{ 'widgets.input-widgets.input-fields-alignment-column' | translate }}
</mat-option>
<mat-option [value]="'row'">
{{ 'widgets.input-widgets.input-fields-alignment-row' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="isLatRequired">
{{ 'widgets.input-widgets.latitude-field-required' | translate }}
</mat-slide-toggle>
<mat-slide-toggle fxFlex formControlName="isLngRequired">
{{ 'widgets.input-widgets.longitude-field-required' | translate }}
</mat-slide-toggle>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.required-error-message</mat-label>
<input matInput formControlName="requiredErrorMessage">
</mat-form-field>
</fieldset>
</section>

View File

@ -0,0 +1,109 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-update-location-attribute-widget-settings',
templateUrl: './update-location-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateLocationAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateLocationAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateLocationAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
widgetTitle: '',
showResultMessage: true,
latKeyName: 'latitude',
lngKeyName: 'longitude',
showGetLocation: true,
enableHighAccuracy: false,
showLabel: true,
latLabel: '',
lngLabel: '',
inputFieldsAlignment: 'column',
isLatRequired: true,
isLngRequired: true,
requiredErrorMessage: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateLocationAttributeWidgetSettingsForm = this.fb.group({
// General settings
widgetTitle: [settings.widgetTitle, []],
showResultMessage: [settings.showResultMessage, []],
latKeyName: [settings.latKeyName, []],
lngKeyName: [settings.lngKeyName, []],
showGetLocation: [settings.showGetLocation, []],
enableHighAccuracy: [settings.enableHighAccuracy, []],
// Location fields settings
showLabel: [settings.showLabel, []],
latLabel: [settings.latLabel, []],
lngLabel: [settings.lngLabel, []],
inputFieldsAlignment: [settings.inputFieldsAlignment, []],
isLatRequired: [settings.isLatRequired, []],
isLngRequired: [settings.isLngRequired, []],
requiredErrorMessage: [settings.requiredErrorMessage, []]
});
}
protected validatorTriggers(): string[] {
return ['showLabel', 'isLatRequired', 'isLngRequired'];
}
protected updateValidators(emitEvent: boolean) {
const showLabel: boolean = this.updateLocationAttributeWidgetSettingsForm.get('showLabel').value;
const isLatRequired: boolean = this.updateLocationAttributeWidgetSettingsForm.get('isLatRequired').value;
const isLngRequired: boolean = this.updateLocationAttributeWidgetSettingsForm.get('isLngRequired').value;
if (showLabel) {
this.updateLocationAttributeWidgetSettingsForm.get('latLabel').enable();
this.updateLocationAttributeWidgetSettingsForm.get('lngLabel').enable();
} else {
this.updateLocationAttributeWidgetSettingsForm.get('latLabel').disable();
this.updateLocationAttributeWidgetSettingsForm.get('lngLabel').disable();
}
if (isLatRequired || isLngRequired) {
this.updateLocationAttributeWidgetSettingsForm.get('requiredErrorMessage').enable();
} else {
this.updateLocationAttributeWidgetSettingsForm.get('requiredErrorMessage').disable();
}
this.updateLocationAttributeWidgetSettingsForm.get('latLabel').updateValueAndValidity({emitEvent});
this.updateLocationAttributeWidgetSettingsForm.get('lngLabel').updateValueAndValidity({emitEvent});
this.updateLocationAttributeWidgetSettingsForm.get('requiredErrorMessage').updateValueAndValidity({emitEvent});
}
}

View File

@ -0,0 +1,36 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="updateStringAttributeWidgetSettingsForm" fxLayout="column">
<tb-update-attribute-general-settings
formControlName="updateAttributeGeneralSettings">
</tb-update-attribute-general-settings>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.input-widgets.text-field-settings</legend>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.min-length</mat-label>
<input matInput type="number" step="1" min="0" formControlName="minLength">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.input-widgets.max-length</mat-label>
<input matInput type="number" step="1" min="1" formControlName="maxLength">
</mat-form-field>
</section>
</fieldset>
</section>

View File

@ -0,0 +1,77 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { deepClone } from '@core/utils';
import {
updateAttributeGeneralDefaultSettings
} from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component';
@Component({
selector: 'tb-update-string-attribute-widget-settings',
templateUrl: './update-string-attribute-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class UpdateStringAttributeWidgetSettingsComponent extends WidgetSettingsComponent {
updateStringAttributeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.updateStringAttributeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
...updateAttributeGeneralDefaultSettings(),
minLength: null,
maxLength: null,
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.updateStringAttributeWidgetSettingsForm = this.fb.group({
updateAttributeGeneralSettings: [settings.updateAttributeGeneralSettings, []],
minLength: [settings.minLength, [Validators.min(0)]],
maxLength: [settings.maxLength, [Validators.min(1)]]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
const updateAttributeGeneralSettings = deepClone(settings, ['minLength', 'maxLength']);
return {
updateAttributeGeneralSettings,
minLength: settings.minLength,
maxLength: settings.maxLength
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return {
...settings.updateAttributeGeneralSettings,
minLength: settings.minLength,
maxLength: settings.maxLength
};
}
}

View File

@ -169,6 +169,39 @@ import {
import {
NavigationCardsWidgetSettingsComponent
} from '@home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component';
import {
DeviceClaimingWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/device-claiming-widget-settings.component';
import {
UpdateAttributeGeneralSettingsComponent
} from '@home/components/widget/lib/settings/input/update-attribute-general-settings.component';
import {
UpdateIntegerAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-integer-attribute-widget-settings.component';
import {
UpdateDoubleAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-double-attribute-widget-settings.component';
import {
UpdateStringAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-string-attribute-widget-settings.component';
import {
UpdateBooleanAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-boolean-attribute-widget-settings.component';
import {
UpdateImageAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-image-attribute-widget-settings.component';
import {
UpdateDateAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-date-attribute-widget-settings.component';
import {
UpdateLocationAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-location-attribute-widget-settings.component';
import {
UpdateJsonAttributeWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/update-json-attribute-widget-settings.component';
import {
PhotoCameraInputWidgetSettingsComponent
} from '@home/components/widget/lib/settings/input/photo-camera-input-widget-settings.component';
@NgModule({
declarations: [
@ -231,7 +264,18 @@ import {
GpioControlWidgetSettingsComponent,
GpioPanelWidgetSettingsComponent,
NavigationCardWidgetSettingsComponent,
NavigationCardsWidgetSettingsComponent
NavigationCardsWidgetSettingsComponent,
DeviceClaimingWidgetSettingsComponent,
UpdateAttributeGeneralSettingsComponent,
UpdateIntegerAttributeWidgetSettingsComponent,
UpdateDoubleAttributeWidgetSettingsComponent,
UpdateStringAttributeWidgetSettingsComponent,
UpdateBooleanAttributeWidgetSettingsComponent,
UpdateImageAttributeWidgetSettingsComponent,
UpdateDateAttributeWidgetSettingsComponent,
UpdateLocationAttributeWidgetSettingsComponent,
UpdateJsonAttributeWidgetSettingsComponent,
PhotoCameraInputWidgetSettingsComponent
],
imports: [
CommonModule,
@ -298,7 +342,18 @@ import {
GpioControlWidgetSettingsComponent,
GpioPanelWidgetSettingsComponent,
NavigationCardWidgetSettingsComponent,
NavigationCardsWidgetSettingsComponent
NavigationCardsWidgetSettingsComponent,
DeviceClaimingWidgetSettingsComponent,
UpdateAttributeGeneralSettingsComponent,
UpdateIntegerAttributeWidgetSettingsComponent,
UpdateDoubleAttributeWidgetSettingsComponent,
UpdateStringAttributeWidgetSettingsComponent,
UpdateBooleanAttributeWidgetSettingsComponent,
UpdateImageAttributeWidgetSettingsComponent,
UpdateDateAttributeWidgetSettingsComponent,
UpdateLocationAttributeWidgetSettingsComponent,
UpdateJsonAttributeWidgetSettingsComponent,
PhotoCameraInputWidgetSettingsComponent
]
})
export class WidgetSettingsModule {
@ -350,5 +405,15 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-gpio-control-widget-settings': GpioControlWidgetSettingsComponent,
'tb-gpio-panel-widget-settings': GpioPanelWidgetSettingsComponent,
'tb-navigation-card-widget-settings': NavigationCardWidgetSettingsComponent,
'tb-navigation-cards-widget-settings': NavigationCardsWidgetSettingsComponent
'tb-navigation-cards-widget-settings': NavigationCardsWidgetSettingsComponent,
'tb-device-claiming-widget-settings': DeviceClaimingWidgetSettingsComponent,
'tb-update-integer-attribute-widget-settings': UpdateIntegerAttributeWidgetSettingsComponent,
'tb-update-double-attribute-widget-settings': UpdateDoubleAttributeWidgetSettingsComponent,
'tb-update-string-attribute-widget-settings': UpdateStringAttributeWidgetSettingsComponent,
'tb-update-boolean-attribute-widget-settings': UpdateBooleanAttributeWidgetSettingsComponent,
'tb-update-image-attribute-widget-settings': UpdateImageAttributeWidgetSettingsComponent,
'tb-update-date-attribute-widget-settings': UpdateDateAttributeWidgetSettingsComponent,
'tb-update-location-attribute-widget-settings': UpdateLocationAttributeWidgetSettingsComponent,
'tb-update-json-attribute-widget-settings': UpdateJsonAttributeWidgetSettingsComponent,
'tb-photo-camera-input-widget-settings': PhotoCameraInputWidgetSettingsComponent
};

View File

@ -3592,7 +3592,71 @@
"update-successful": "Update successful",
"update-attribute": "Update attribute",
"update-timeseries": "Update timeseries",
"value": "Value"
"value": "Value",
"general-settings": "General settings",
"widget-title": "Widget title",
"claim-button-label": "Claiming button label",
"show-secret-key-field": "Show 'Secret key' input field",
"labels-settings": "Labels settings",
"show-labels": "Show labels",
"device-name-label": "Label for device name input field",
"secret-key-label": "Label for secret key input field",
"messages-settings": "Messages settings",
"claim-device-success-message": "Text message of successful device claiming",
"claim-device-not-found-message": "Text message when device not found",
"claim-device-failed-message": "Text message of failed device claiming",
"claim-device-name-required-message": "'Device name required' error message",
"claim-device-secret-key-required-message": "'Secret key required' error message",
"show-label": "Show label",
"label": "Label",
"required": "Required",
"required-error-message": "'Required' error message",
"show-result-message": "Show result message",
"integer-field-settings": "Integer field settings",
"min-value": "Min value",
"max-value": "Max value",
"double-field-settings": "Double field settings",
"text-field-settings": "Text field settings",
"min-length": "Min length",
"max-length": "Max length",
"checkbox-settings": "Checkbox settings",
"true-label": "Checked label",
"false-label": "Unchecked label",
"image-input-settings": "Image input settings",
"display-preview": "Display preview",
"display-clear-button": "Display clear button",
"display-apply-button": "Display apply button",
"display-discard-button": "Display discard button",
"datetime-field-settings": "Date/time field settings",
"display-time-input": "Display time input",
"latitude-key-name": "Latitude key name",
"longitude-key-name": "Longitude key name",
"show-get-location-button": "Show button 'Get current location'",
"use-high-accuracy": "Use high accuracy",
"location-fields-settings": "Location fields settings",
"latitude-label": "Label for latitude",
"longitude-label": "Label for longitude",
"input-fields-alignment": "Input fields alignment",
"input-fields-alignment-column": "Column (default)",
"input-fields-alignment-row": "Row",
"latitude-field-required": "Latitude field required",
"longitude-field-required": "Longitude field required",
"attribute-settings": "Attribute settings",
"widget-mode": "Widget mode",
"widget-mode-update-attribute": "Update attribute",
"widget-mode-update-timeseries": "Update timeseries",
"attribute-scope": "Attribute scope",
"attribute-scope-server": "Server attribute",
"attribute-scope-shared": "Shared attribute",
"value-required": "Value required",
"image-settings": "Image settings",
"image-format": "Image format",
"image-format-jpeg": "JPEG",
"image-format-png": "PNG",
"image-format-webp": "WEBP",
"image-quality": "Image quality that use lossy compression such as jpeg and webp",
"max-image-width": "Maximum image width",
"max-image-height": "Maximum image height"
},
"invalid-qr-code-text": "Invalid input text for QR code. Input should have a string type",
"qr-code": {