Browse Source

UI: Add slide toggle control widget

pull/6049/head
Igor Kulikov 5 years ago
parent
commit
cc6cd2cb2a
  1. 18
      application/src/main/data/json/system/widget_bundles/control_widgets.json
  2. 13
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.html
  3. 91
      ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts
  4. 2
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

18
application/src/main/data/json/system/widget_bundles/control_widgets.json

File diff suppressed because one or more lines are too long

13
ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.html

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<div class="tb-switch" fxLayout="column" [ngStyle]="{'pointerEvents': ctx.isEdit ? 'none' : 'all'}"> <div class="tb-switch" fxLayout="column" [ngStyle]="{'pointerEvents': ctx.isEdit ? 'none' : 'all'}" *ngIf="switchType === 'switch'; else slideToggle">
<div #switchErrorContainer class="error-container" [ngStyle]="{'background': error?.length ? 'rgba(255,255,255,0.25)' : 'none'}" <div #switchErrorContainer class="error-container" [ngStyle]="{'background': error?.length ? 'rgba(255,255,255,0.25)' : 'none'}"
fxLayout="row" fxLayoutAlign="center center"> fxLayout="row" fxLayoutAlign="center center">
<span #switchError class="switch-error">{{ error }}</span> <span #switchError class="switch-error">{{ error }}</span>
@ -37,3 +37,14 @@
</div> </div>
<div #textMeasure id="text-measure"></div> <div #textMeasure id="text-measure"></div>
</div> </div>
<ng-template #slideToggle>
<div class="tb-absolute-fill" fxLayout="column" [ngStyle]="{'pointerEvents': ctx.isEdit ? 'none' : 'all'}" fxLayoutAlign="center center">
<div>
<mat-slide-toggle [disabled]="executingUpdateValue" [labelPosition]="labelPosition" [color]="sliderColor" [(ngModel)]="value" (change)="onValue()">{{title}}</mat-slide-toggle>
<mat-progress-bar style="height: 2px;" [color]="sliderColor" mode="indeterminate" *ngIf="executingUpdateValue"></mat-progress-bar>
<div style="height: 2px;" *ngIf="!executingUpdateValue"></div>
<tb-error style="margin-top: -6px; display: block; pointer-events: none;"
[error]="error"></tb-error>
</div>
</div>
</ng-template>

91
ui-ngx/src/app/modules/home/components/widget/lib/rpc/switch.component.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { UtilsService } from '@core/services/utils.service'; import { UtilsService } from '@core/services/utils.service';
@ -26,11 +26,14 @@ import { DatasourceType, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { MatSlideToggle } from '@angular/material/slide-toggle'; import { MatSlideToggle } from '@angular/material/slide-toggle';
import { ResizeObserver } from '@juggle/resize-observer'; import { ResizeObserver } from '@juggle/resize-observer';
import { ThemePalette } from '@angular/material/core/common-behaviors/color';
const switchAspectRation = 2.7893; const switchAspectRation = 2.7893;
type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries'; type RetrieveValueMethod = 'rpc' | 'attribute' | 'timeseries';
type SwitchType = 'switch' | 'slide-toggle';
interface SwitchSettings { interface SwitchSettings {
initialValue: boolean; initialValue: boolean;
title: string; title: string;
@ -44,6 +47,8 @@ interface SwitchSettings {
requestTimeout: number; requestTimeout: number;
requestPersistent: boolean; requestPersistent: boolean;
persistentPollingInterval: number; persistentPollingInterval: number;
labelPosition: 'before' | 'after';
sliderColor: ThemePalette;
} }
@Component({ @Component({
@ -51,28 +56,33 @@ interface SwitchSettings {
templateUrl: './switch.component.html', templateUrl: './switch.component.html',
styleUrls: ['./switch.component.scss'] styleUrls: ['./switch.component.scss']
}) })
export class SwitchComponent extends PageComponent implements OnInit, OnDestroy { export class SwitchComponent extends PageComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('switch', {static: true}) switchElementRef: ElementRef<HTMLElement>; @ViewChild('switch', {static: false}) switchElementRef: ElementRef<HTMLElement>;
@ViewChild('switchContainer', {static: true}) switchContainerRef: ElementRef<HTMLElement>; @ViewChild('switchContainer', {static: false}) switchContainerRef: ElementRef<HTMLElement>;
@ViewChild('matSlideToggle', {static: true}) matSlideToggleRef: MatSlideToggle; @ViewChild('matSlideToggle', {static: false}) matSlideToggleRef: MatSlideToggle;
@ViewChild('onoffContainer', {static: true}) onoffContainerRef: ElementRef<HTMLElement>; @ViewChild('onoffContainer', {static: false}) onoffContainerRef: ElementRef<HTMLElement>;
@ViewChild('onLabel', {static: true}) onLabelRef: ElementRef<HTMLElement>; @ViewChild('onLabel', {static: false}) onLabelRef: ElementRef<HTMLElement>;
@ViewChild('offLabel', {static: true}) offLabelRef: ElementRef<HTMLElement>; @ViewChild('offLabel', {static: false}) offLabelRef: ElementRef<HTMLElement>;
@ViewChild('switchTitleContainer', {static: true}) switchTitleContainerRef: ElementRef<HTMLElement>; @ViewChild('switchTitleContainer', {static: false}) switchTitleContainerRef: ElementRef<HTMLElement>;
@ViewChild('switchTitle', {static: true}) switchTitleRef: ElementRef<HTMLElement>; @ViewChild('switchTitle', {static: false}) switchTitleRef: ElementRef<HTMLElement>;
@ViewChild('textMeasure', {static: true}) textMeasureRef: ElementRef<HTMLElement>; @ViewChild('textMeasure', {static: false}) textMeasureRef: ElementRef<HTMLElement>;
@ViewChild('switchErrorContainer', {static: true}) switchErrorContainerRef: ElementRef<HTMLElement>; @ViewChild('switchErrorContainer', {static: false}) switchErrorContainerRef: ElementRef<HTMLElement>;
@ViewChild('switchError', {static: true}) switchErrorRef: ElementRef<HTMLElement>; @ViewChild('switchError', {static: false}) switchErrorRef: ElementRef<HTMLElement>;
@Input() @Input()
ctx: WidgetContext; ctx: WidgetContext;
@Input()
switchType: SwitchType = 'switch';
showTitle = false; showTitle = false;
value = false; value = false;
error = ''; error = '';
title = ''; title = '';
showOnOffLabels = false; showOnOffLabels = false;
labelPosition: 'before' | 'after' = 'after';
sliderColor: ThemePalette = 'accent';
private isSimulated: boolean; private isSimulated: boolean;
private requestTimeout: number; private requestTimeout: number;
@ -87,7 +97,7 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
private valueSubscription: IWidgetSubscription; private valueSubscription: IWidgetSubscription;
private executingUpdateValue: boolean; public executingUpdateValue: boolean;
private scheduledValue: boolean; private scheduledValue: boolean;
private rpcValue: boolean; private rpcValue: boolean;
@ -111,22 +121,27 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
} }
ngOnInit(): void { ngOnInit(): void {
this.switchElement = $(this.switchElementRef.nativeElement); }
this.switchContainer = $(this.switchContainerRef.nativeElement);
this.matSlideToggle = $(this.matSlideToggleRef._elementRef.nativeElement); ngAfterViewInit() {
this.onoffContainer = $(this.onoffContainerRef.nativeElement); if (this.switchType === 'switch') {
this.onLabel = $(this.onLabelRef.nativeElement); this.switchElement = $(this.switchElementRef.nativeElement);
this.offLabel = $(this.offLabelRef.nativeElement); this.switchContainer = $(this.switchContainerRef.nativeElement);
this.switchTitleContainer = $(this.switchTitleContainerRef.nativeElement); this.matSlideToggle = $(this.matSlideToggleRef._elementRef.nativeElement);
this.switchTitle = $(this.switchTitleRef.nativeElement); this.onoffContainer = $(this.onoffContainerRef.nativeElement);
this.textMeasure = $(this.textMeasureRef.nativeElement); this.onLabel = $(this.onLabelRef.nativeElement);
this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement); this.offLabel = $(this.offLabelRef.nativeElement);
this.switchError = $(this.switchErrorRef.nativeElement); this.switchTitleContainer = $(this.switchTitleContainerRef.nativeElement);
this.switchTitle = $(this.switchTitleRef.nativeElement);
this.switchResize$ = new ResizeObserver(() => { this.textMeasure = $(this.textMeasureRef.nativeElement);
this.resize(); this.switchErrorContainer = $(this.switchErrorContainerRef.nativeElement);
}); this.switchError = $(this.switchErrorRef.nativeElement);
this.switchResize$.observe(this.switchContainerRef.nativeElement);
this.switchResize$ = new ResizeObserver(() => {
this.resize();
});
this.switchResize$.observe(this.switchContainerRef.nativeElement);
}
this.init(); this.init();
} }
@ -145,6 +160,8 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
this.title = isDefined(settings.title) ? settings.title : ''; this.title = isDefined(settings.title) ? settings.title : '';
this.showTitle = !!(this.title && this.title.length); this.showTitle = !!(this.title && this.title.length);
this.showOnOffLabels = isDefined(settings.showOnOffLabels) ? settings.showOnOffLabels : true; this.showOnOffLabels = isDefined(settings.showOnOffLabels) ? settings.showOnOffLabels : true;
this.labelPosition = isDefined(settings.labelPosition) ? settings.labelPosition : 'after';
this.sliderColor = isDefined(settings.sliderColor) ? settings.sliderColor : 'accent';
const initialValue = isDefined(settings.initialValue) ? settings.initialValue : false; const initialValue = isDefined(settings.initialValue) ? settings.initialValue : false;
this.setValue(initialValue); this.setValue(initialValue);
@ -256,7 +273,9 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
private onError(error: string) { private onError(error: string) {
this.error = error; this.error = error;
this.setFontSize(this.switchError, this.error, this.switchErrorContainer.height(), this.switchErrorContainer.width()); if (this.switchType === 'switch') {
this.setFontSize(this.switchError, this.error, this.switchErrorContainer.height(), this.switchErrorContainer.width());
}
this.ctx.detectChanges(); this.ctx.detectChanges();
} }
@ -278,6 +297,10 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
}, },
() => { () => {
const errorText = this.ctx.defaultSubscription.rpcErrorText; const errorText = this.ctx.defaultSubscription.rpcErrorText;
if (this.switchType === 'slide-toggle') {
this.ctx.defaultSubscription.rpcErrorText = null;
this.ctx.hideToast(this.ctx.toastTargetId);
}
this.onError(errorText); this.onError(errorText);
} }
); );
@ -304,6 +327,10 @@ export class SwitchComponent extends PageComponent implements OnInit, OnDestroy
() => { () => {
this.executingUpdateValue = false; this.executingUpdateValue = false;
const errorText = this.ctx.defaultSubscription.rpcErrorText; const errorText = this.ctx.defaultSubscription.rpcErrorText;
if (this.switchType === 'slide-toggle') {
this.ctx.defaultSubscription.rpcErrorText = null;
this.ctx.hideToast(this.ctx.toastTargetId);
}
this.onError(errorText); this.onError(errorText);
} }
); );

2
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

@ -922,7 +922,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, Cont
} else if (this.modelValue) { } else if (this.modelValue) {
const config = this.modelValue.config; const config = this.modelValue.config;
if (this.widgetType === widgetType.rpc && this.modelValue.isDataEnabled) { if (this.widgetType === widgetType.rpc && this.modelValue.isDataEnabled) {
if (!config.targetDeviceAliasIds || !config.targetDeviceAliasIds.length) { if (!this.widgetEditMode && (!config.targetDeviceAliasIds || !config.targetDeviceAliasIds.length)) {
return { return {
targetDeviceAliasIds: { targetDeviceAliasIds: {
valid: false valid: false

Loading…
Cancel
Save