UI: Command button widget
This commit is contained in:
		
							parent
							
								
									2fab6dc5c6
								
							
						
					
					
						commit
						147f817445
					
				@ -8,6 +8,7 @@
 | 
			
		||||
    "name": "Buttons"
 | 
			
		||||
  },
 | 
			
		||||
  "widgetTypeFqns": [
 | 
			
		||||
    "action_button"
 | 
			
		||||
    "action_button",
 | 
			
		||||
    "command_button"
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -97,6 +97,9 @@ import {
 | 
			
		||||
import {
 | 
			
		||||
  ActionButtonBasicConfigComponent
 | 
			
		||||
} from '@home/components/widget/config/basic/button/action-button-basic-config.component';
 | 
			
		||||
import {
 | 
			
		||||
  CommandButtonBasicConfigComponent
 | 
			
		||||
} from '@home/components/widget/config/basic/button/command-button-basic-config.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -127,7 +130,8 @@ import {
 | 
			
		||||
    RangeChartBasicConfigComponent,
 | 
			
		||||
    BarChartWithLabelsBasicConfigComponent,
 | 
			
		||||
    SingleSwitchBasicConfigComponent,
 | 
			
		||||
    ActionButtonBasicConfigComponent
 | 
			
		||||
    ActionButtonBasicConfigComponent,
 | 
			
		||||
    CommandButtonBasicConfigComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -162,7 +166,8 @@ import {
 | 
			
		||||
    RangeChartBasicConfigComponent,
 | 
			
		||||
    BarChartWithLabelsBasicConfigComponent,
 | 
			
		||||
    SingleSwitchBasicConfigComponent,
 | 
			
		||||
    ActionButtonBasicConfigComponent
 | 
			
		||||
    ActionButtonBasicConfigComponent,
 | 
			
		||||
    CommandButtonBasicConfigComponent
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class BasicWidgetConfigModule {
 | 
			
		||||
@ -191,5 +196,6 @@ export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetCo
 | 
			
		||||
  'tb-range-chart-basic-config': RangeChartBasicConfigComponent,
 | 
			
		||||
  'tb-bar-chart-with-labels-basic-config': BarChartWithLabelsBasicConfigComponent,
 | 
			
		||||
  'tb-single-switch-basic-config': SingleSwitchBasicConfigComponent,
 | 
			
		||||
  'tb-action-button-basic-config': ActionButtonBasicConfigComponent
 | 
			
		||||
  'tb-action-button-basic-config': ActionButtonBasicConfigComponent,
 | 
			
		||||
  'tb-command-button-basic-config': CommandButtonBasicConfigComponent
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,59 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2024 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<ng-container [formGroup]="commandButtonWidgetConfigForm">
 | 
			
		||||
  <tb-target-device formControlName="targetDevice"></tb-target-device>
 | 
			
		||||
  <div class="tb-form-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widgets.command-button.behavior</div>
 | 
			
		||||
    <div class="tb-form-row space-between">
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.command-button.on-click-hint' | translate}}" translate>widgets.command-button.on-click</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.command-button.on-click"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
                                    formControlName="onClickState"></tb-set-value-action-settings>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tb-form-row">
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.button-state.disabled-state-hint' | translate}}" translate>widgets.button-state.disabled-state</div>
 | 
			
		||||
      <tb-get-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.button-state.disabled-state"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    stateLabel="widgets.button-state.disabled"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
                                    formControlName="disabledState"></tb-get-value-action-settings>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widget-config.appearance</div>
 | 
			
		||||
    <tb-widget-button-appearance
 | 
			
		||||
      [borderRadius]="commandButtonWidgetConfigForm.get('borderRadius').value"
 | 
			
		||||
      formControlName="appearance">
 | 
			
		||||
    </tb-widget-button-appearance>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
 | 
			
		||||
    <div class="tb-form-row space-between">
 | 
			
		||||
      <div>{{ 'widget-config.card-border-radius' | translate }}</div>
 | 
			
		||||
      <mat-form-field appearance="outline" subscriptSizing="dynamic">
 | 
			
		||||
        <input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}">
 | 
			
		||||
      </mat-form-field>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</ng-container>
 | 
			
		||||
@ -0,0 +1,85 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
 | 
			
		||||
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
 | 
			
		||||
import { TargetDevice, } from '@shared/models/widget.models';
 | 
			
		||||
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
 | 
			
		||||
import { ValueType } from '@shared/models/constants';
 | 
			
		||||
import {
 | 
			
		||||
  commandButtonDefaultSettings,
 | 
			
		||||
  CommandButtonWidgetSettings
 | 
			
		||||
} from '@home/components/widget/lib/button/command-button-widget.models';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-command-button-basic-config',
 | 
			
		||||
  templateUrl: './command-button-basic-config.component.html',
 | 
			
		||||
  styleUrls: ['../basic-config.scss']
 | 
			
		||||
})
 | 
			
		||||
export class CommandButtonBasicConfigComponent extends BasicWidgetConfigComponent {
 | 
			
		||||
 | 
			
		||||
  get targetDevice(): TargetDevice {
 | 
			
		||||
    return this.commandButtonWidgetConfigForm.get('targetDevice').value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  valueType = ValueType;
 | 
			
		||||
 | 
			
		||||
  commandButtonWidgetConfigForm: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              protected widgetConfigComponent: WidgetConfigComponent,
 | 
			
		||||
              private fb: UntypedFormBuilder) {
 | 
			
		||||
    super(store, widgetConfigComponent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected configForm(): UntypedFormGroup {
 | 
			
		||||
    return this.commandButtonWidgetConfigForm;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected onConfigSet(configData: WidgetConfigComponentData) {
 | 
			
		||||
    const settings: CommandButtonWidgetSettings = {...commandButtonDefaultSettings, ...(configData.config.settings || {})};
 | 
			
		||||
    this.commandButtonWidgetConfigForm = this.fb.group({
 | 
			
		||||
      targetDevice: [configData.config.targetDevice, []],
 | 
			
		||||
 | 
			
		||||
      onClickState: [settings.onClickState, []],
 | 
			
		||||
      disabledState: [settings.disabledState, []],
 | 
			
		||||
 | 
			
		||||
      appearance: [settings.appearance, []],
 | 
			
		||||
 | 
			
		||||
      borderRadius: [configData.config.borderRadius, []]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected prepareOutputConfig(config: any): WidgetConfigComponentData {
 | 
			
		||||
 | 
			
		||||
    this.widgetConfig.config.targetDevice = config.targetDevice;
 | 
			
		||||
 | 
			
		||||
    this.widgetConfig.config.settings = this.widgetConfig.config.settings || {};
 | 
			
		||||
 | 
			
		||||
    this.widgetConfig.config.settings.onClickState = config.onClickState;
 | 
			
		||||
    this.widgetConfig.config.settings.disabledState = config.disabledState;
 | 
			
		||||
 | 
			
		||||
    this.widgetConfig.config.settings.appearance = config.appearance;
 | 
			
		||||
 | 
			
		||||
    this.widgetConfig.config.borderRadius = config.borderRadius;
 | 
			
		||||
 | 
			
		||||
    return this.widgetConfig;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -36,7 +36,6 @@
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.turn-on-hint' | translate}}" translate>widgets.rpc-state.turn-on</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.rpc-state.turn-on"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
@ -46,7 +45,6 @@
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.turn-off-hint' | translate}}" translate>widgets.rpc-state.turn-off</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.rpc-state.turn-off"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2024 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div class="tb-command-button-widget" [style.pointer-events]="ctx.isEdit ? 'none' : 'all'">
 | 
			
		||||
  <div class="tb-command-button-widget-title-panel">
 | 
			
		||||
    <ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container>
 | 
			
		||||
  </div>
 | 
			
		||||
  <tb-widget-button
 | 
			
		||||
    [appearance]="appearance"
 | 
			
		||||
    [borderRadius]="borderRadius"
 | 
			
		||||
    [disabled]="disabled"
 | 
			
		||||
    (clicked)="onClick($event)">
 | 
			
		||||
  </tb-widget-button>
 | 
			
		||||
  <div *ngIf="error" class="tb-action-widget-error-container">
 | 
			
		||||
    <div class="tb-action-widget-error-panel">
 | 
			
		||||
      <div class="tb-action-widget-error-text" [innerHTML]="error | safe: 'html'"></div>
 | 
			
		||||
      <button class="tb-action-widget-error-clear tb-mat-20" mat-icon-button (click)="clearError()"><mat-icon>close</mat-icon></button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2024 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.
 | 
			
		||||
 */
 | 
			
		||||
.tb-command-button-widget {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  position: relative;
 | 
			
		||||
 | 
			
		||||
  > div.tb-command-button-widget-title-panel {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 12px;
 | 
			
		||||
    left: 12px;
 | 
			
		||||
    right: 12px;
 | 
			
		||||
    z-index: 2;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,94 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 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 { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
 | 
			
		||||
import { BasicActionWidgetComponent, ValueSetter } from '@home/components/widget/lib/action/action-widget.models';
 | 
			
		||||
import { ImagePipe } from '@shared/pipe/image.pipe';
 | 
			
		||||
import { DomSanitizer } from '@angular/platform-browser';
 | 
			
		||||
import { ValueType } from '@shared/models/constants';
 | 
			
		||||
import { WidgetButtonAppearance } from '@shared/components/button/widget-button.models';
 | 
			
		||||
import {
 | 
			
		||||
  commandButtonDefaultSettings,
 | 
			
		||||
  CommandButtonWidgetSettings
 | 
			
		||||
} from '@home/components/widget/lib/button/command-button-widget.models';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-command-button-widget',
 | 
			
		||||
  templateUrl: './command-button-widget.component.html',
 | 
			
		||||
  styleUrls: ['../action/action-widget.scss', './command-button-widget.component.scss'],
 | 
			
		||||
  encapsulation: ViewEncapsulation.None
 | 
			
		||||
})
 | 
			
		||||
export class CommandButtonWidgetComponent extends
 | 
			
		||||
  BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  settings: CommandButtonWidgetSettings;
 | 
			
		||||
 | 
			
		||||
  disabled = false;
 | 
			
		||||
 | 
			
		||||
  appearance: WidgetButtonAppearance;
 | 
			
		||||
  borderRadius = '4px';
 | 
			
		||||
 | 
			
		||||
  private clickValueSetter: ValueSetter<any>;
 | 
			
		||||
 | 
			
		||||
  constructor(protected imagePipe: ImagePipe,
 | 
			
		||||
              protected sanitizer: DomSanitizer,
 | 
			
		||||
              protected cd: ChangeDetectorRef) {
 | 
			
		||||
    super(cd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    super.ngOnInit();
 | 
			
		||||
    this.settings = {...commandButtonDefaultSettings, ...this.ctx.settings};
 | 
			
		||||
 | 
			
		||||
    this.appearance = this.settings.appearance;
 | 
			
		||||
 | 
			
		||||
    const disabledStateSettings =
 | 
			
		||||
      {...this.settings.disabledState, actionLabel: this.ctx.translate.instant('widgets.button-state.disabled-state')};
 | 
			
		||||
    this.createValueGetter(disabledStateSettings, ValueType.BOOLEAN, {
 | 
			
		||||
      next: (value) => this.onDisabled(value)
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const onClickStateSettings = {...this.settings.onClickState,
 | 
			
		||||
      actionLabel: this.ctx.translate.instant('widgets.command-button.on-click')};
 | 
			
		||||
    this.clickValueSetter = this.createValueSetter(onClickStateSettings);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngAfterViewInit(): void {
 | 
			
		||||
    super.ngAfterViewInit();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    super.ngOnDestroy();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onInit() {
 | 
			
		||||
    super.onInit();
 | 
			
		||||
    this.borderRadius = this.ctx.$widgetElement.css('borderRadius');
 | 
			
		||||
    this.cd.detectChanges();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onClick(_$event: MouseEvent) {
 | 
			
		||||
    if (!this.ctx.isEdit && !this.ctx.isPreview) {
 | 
			
		||||
      this.updateValue(this.clickValueSetter, null);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private onDisabled(value: boolean): void {
 | 
			
		||||
    this.disabled = !!value;
 | 
			
		||||
    this.cd.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 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 { WidgetButtonAppearance, widgetButtonDefaultAppearance } from '@shared/components/button/widget-button.models';
 | 
			
		||||
import {
 | 
			
		||||
  DataToValueType,
 | 
			
		||||
  GetValueAction,
 | 
			
		||||
  GetValueSettings, SetValueAction,
 | 
			
		||||
  SetValueSettings, ValueToDataType
 | 
			
		||||
} from '@shared/models/action-widget-settings.models';
 | 
			
		||||
import { AttributeScope } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
 | 
			
		||||
export interface CommandButtonWidgetSettings {
 | 
			
		||||
  appearance: WidgetButtonAppearance;
 | 
			
		||||
  onClickState: SetValueSettings;
 | 
			
		||||
  disabledState: GetValueSettings<boolean>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const commandButtonDefaultSettings: CommandButtonWidgetSettings = {
 | 
			
		||||
  appearance: {...widgetButtonDefaultAppearance, label: 'Send', icon: 'arrow_outward'},
 | 
			
		||||
  onClickState: {
 | 
			
		||||
    action: SetValueAction.EXECUTE_RPC,
 | 
			
		||||
    executeRpc: {
 | 
			
		||||
      method: 'setState',
 | 
			
		||||
      requestTimeout: 5000,
 | 
			
		||||
      requestPersistent: false,
 | 
			
		||||
      persistentPollingInterval: 1000
 | 
			
		||||
    },
 | 
			
		||||
    setAttribute: {
 | 
			
		||||
      key: 'state',
 | 
			
		||||
      scope: AttributeScope.SHARED_SCOPE
 | 
			
		||||
    },
 | 
			
		||||
    putTimeSeries: {
 | 
			
		||||
      key: 'state'
 | 
			
		||||
    },
 | 
			
		||||
    valueToData: {
 | 
			
		||||
      type: ValueToDataType.NONE,
 | 
			
		||||
      constantValue: true,
 | 
			
		||||
      valueToDataFunction: '/* Return RPC parameters or attribute/time-series value */\nreturn true;'
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  disabledState: {
 | 
			
		||||
    action: GetValueAction.DO_NOTHING,
 | 
			
		||||
    defaultValue: false,
 | 
			
		||||
    getAttribute: {
 | 
			
		||||
      key: 'state',
 | 
			
		||||
      scope: null
 | 
			
		||||
    },
 | 
			
		||||
    getTimeSeries: {
 | 
			
		||||
      key: 'state'
 | 
			
		||||
    },
 | 
			
		||||
    dataToValue: {
 | 
			
		||||
      type: DataToValueType.NONE,
 | 
			
		||||
      compareToValue: true,
 | 
			
		||||
      dataToValueFunction: '/* Should return boolean value */\nreturn data;'
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@ -211,13 +211,15 @@ export class SingleSwitchWidgetComponent extends
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onToggleChange(event: MouseEvent) {
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
    const targetValue = this.value;
 | 
			
		||||
    const targetSetter = targetValue ? this.onValueSetter : this.offValueSetter;
 | 
			
		||||
    this.updateValue(targetSetter, targetValue, {
 | 
			
		||||
      next: () => this.onValue(targetValue),
 | 
			
		||||
      error: () => this.onValue(!targetValue)
 | 
			
		||||
    });
 | 
			
		||||
    if (!this.ctx.isEdit && !this.ctx.isPreview) {
 | 
			
		||||
      event.preventDefault();
 | 
			
		||||
      const targetValue = this.value;
 | 
			
		||||
      const targetSetter = targetValue ? this.onValueSetter : this.offValueSetter;
 | 
			
		||||
      this.updateValue(targetSetter, targetValue, {
 | 
			
		||||
        next: () => this.onValue(targetValue),
 | 
			
		||||
        error: () => this.onValue(!targetValue)
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private onValue(value: boolean): void {
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,49 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2024 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.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<ng-container [formGroup]="commandButtonWidgetSettingsForm">
 | 
			
		||||
  <div class="tb-form-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widgets.command-button.behavior</div>
 | 
			
		||||
    <div class="tb-form-row space-between">
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.command-button.on-click-hint' | translate}}" translate>widgets.command-button.on-click</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.command-button.on-click"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
                                    formControlName="onClickState"></tb-set-value-action-settings>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tb-form-row">
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.button-state.disabled-state-hint' | translate}}" translate>widgets.button-state.disabled-state</div>
 | 
			
		||||
      <tb-get-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.button-state.disabled-state"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    stateLabel="widgets.button-state.disabled"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
                                    formControlName="disabledState"></tb-get-value-action-settings>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="tb-form-panel">
 | 
			
		||||
    <div class="tb-form-panel-title" translate>widget-config.appearance</div>
 | 
			
		||||
    <tb-widget-button-appearance
 | 
			
		||||
      [borderRadius]="borderRadius"
 | 
			
		||||
      formControlName="appearance">
 | 
			
		||||
    </tb-widget-button-appearance>
 | 
			
		||||
  </div>
 | 
			
		||||
</ng-container>
 | 
			
		||||
@ -0,0 +1,68 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2024 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 { TargetDevice, WidgetSettings, WidgetSettingsComponent, widgetType } from '@shared/models/widget.models';
 | 
			
		||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { ValueType } from '@shared/models/constants';
 | 
			
		||||
import { commandButtonDefaultSettings } from '@home/components/widget/lib/button/command-button-widget.models';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-command-button-widget-settings',
 | 
			
		||||
  templateUrl: './command-button-widget-settings.component.html',
 | 
			
		||||
  styleUrls: ['./../widget-settings.scss']
 | 
			
		||||
})
 | 
			
		||||
export class CommandButtonWidgetSettingsComponent extends WidgetSettingsComponent {
 | 
			
		||||
 | 
			
		||||
  get targetDevice(): TargetDevice {
 | 
			
		||||
    return this.widgetConfig?.config?.targetDevice;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get widgetType(): widgetType {
 | 
			
		||||
    return this.widgetConfig?.widgetType;
 | 
			
		||||
  }
 | 
			
		||||
  get borderRadius(): string {
 | 
			
		||||
    return this.widgetConfig?.config?.borderRadius;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  valueType = ValueType;
 | 
			
		||||
 | 
			
		||||
  commandButtonWidgetSettingsForm: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              private fb: UntypedFormBuilder) {
 | 
			
		||||
    super(store);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected settingsForm(): UntypedFormGroup {
 | 
			
		||||
    return this.commandButtonWidgetSettingsForm;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected defaultSettings(): WidgetSettings {
 | 
			
		||||
    return {...commandButtonDefaultSettings};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected onSettingsSet(settings: WidgetSettings) {
 | 
			
		||||
    this.commandButtonWidgetSettingsForm = this.fb.group({
 | 
			
		||||
      onClickState: [settings.onClickState, []],
 | 
			
		||||
      disabledState: [settings.disabledState, []],
 | 
			
		||||
 | 
			
		||||
      appearance: [settings.appearance, []]
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -22,14 +22,12 @@ import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { merge } from 'rxjs';
 | 
			
		||||
import {
 | 
			
		||||
  getValueActions,
 | 
			
		||||
  SetValueAction,
 | 
			
		||||
  setValueActions, setValueActionsByWidgetType,
 | 
			
		||||
  setValueActionsByWidgetType,
 | 
			
		||||
  setValueActionTranslations,
 | 
			
		||||
  SetValueSettings,
 | 
			
		||||
  ValueToDataType
 | 
			
		||||
} from '@shared/models/action-widget-settings.models';
 | 
			
		||||
import { ValueType } from '@shared/models/constants';
 | 
			
		||||
import { TargetDevice, widgetType } from '@shared/models/widget.models';
 | 
			
		||||
import { AttributeScope, DataKeyType, telemetryTypeTranslationsShort } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
import { IAliasController } from '@core/api/widget-api.models';
 | 
			
		||||
@ -50,9 +48,6 @@ export class SetValueActionSettingsPanelComponent extends PageComponent implemen
 | 
			
		||||
  @Input()
 | 
			
		||||
  setValueSettings: SetValueSettings;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  valueType: ValueType;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  aliasController: IAliasController;
 | 
			
		||||
 | 
			
		||||
@ -84,8 +79,6 @@ export class SetValueActionSettingsPanelComponent extends PageComponent implemen
 | 
			
		||||
 | 
			
		||||
  functionScopeVariables = this.widgetService.getWidgetScopeVariables();
 | 
			
		||||
 | 
			
		||||
  ValueType = ValueType;
 | 
			
		||||
 | 
			
		||||
  setValueSettingsFormGroup: UntypedFormGroup;
 | 
			
		||||
 | 
			
		||||
  constructor(private fb: UntypedFormBuilder,
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,6 @@ import { MatButton } from '@angular/material/button';
 | 
			
		||||
import { TbPopoverService } from '@shared/components/popover.service';
 | 
			
		||||
import { SetValueAction, SetValueSettings, ValueToDataType } from '@shared/models/action-widget-settings.models';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { ValueType } from '@shared/models/constants';
 | 
			
		||||
import { IAliasController } from '@core/api/widget-api.models';
 | 
			
		||||
import { TargetDevice, widgetType } from '@shared/models/widget.models';
 | 
			
		||||
import { isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
@ -59,9 +58,6 @@ export class SetValueActionSettingsComponent implements OnInit, ControlValueAcce
 | 
			
		||||
  @Input()
 | 
			
		||||
  panelTitle: string;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  valueType: ValueType;
 | 
			
		||||
 | 
			
		||||
  @Input()
 | 
			
		||||
  aliasController: IAliasController;
 | 
			
		||||
 | 
			
		||||
@ -118,7 +114,6 @@ export class SetValueActionSettingsComponent implements OnInit, ControlValueAcce
 | 
			
		||||
      const ctx: any = {
 | 
			
		||||
        setValueSettings: this.modelValue,
 | 
			
		||||
        panelTitle: this.panelTitle,
 | 
			
		||||
        valueType: this.valueType,
 | 
			
		||||
        aliasController: this.aliasController,
 | 
			
		||||
        targetDevice: this.targetDevice,
 | 
			
		||||
        widgetType: this.widgetType
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,6 @@
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.turn-on-hint' | translate}}" translate>widgets.rpc-state.turn-on</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.rpc-state.turn-on"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
@ -45,7 +44,6 @@
 | 
			
		||||
      <div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.rpc-state.turn-off-hint' | translate}}" translate>widgets.rpc-state.turn-off</div>
 | 
			
		||||
      <tb-set-value-action-settings fxFlex
 | 
			
		||||
                                    panelTitle="widgets.rpc-state.turn-off"
 | 
			
		||||
                                    [valueType]="valueType.BOOLEAN"
 | 
			
		||||
                                    [aliasController]="aliasController"
 | 
			
		||||
                                    [targetDevice]="targetDevice"
 | 
			
		||||
                                    [widgetType]="widgetType"
 | 
			
		||||
 | 
			
		||||
@ -318,6 +318,9 @@ import {
 | 
			
		||||
import {
 | 
			
		||||
  ActionButtonWidgetSettingsComponent
 | 
			
		||||
} from '@home/components/widget/lib/settings/button/action-button-widget-settings.component';
 | 
			
		||||
import {
 | 
			
		||||
  CommandButtonWidgetSettingsComponent
 | 
			
		||||
} from '@home/components/widget/lib/settings/button/command-button-widget-settings.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
@ -432,7 +435,8 @@ import {
 | 
			
		||||
    RangeChartWidgetSettingsComponent,
 | 
			
		||||
    BarChartWithLabelsWidgetSettingsComponent,
 | 
			
		||||
    SingleSwitchWidgetSettingsComponent,
 | 
			
		||||
    ActionButtonWidgetSettingsComponent
 | 
			
		||||
    ActionButtonWidgetSettingsComponent,
 | 
			
		||||
    CommandButtonWidgetSettingsComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -552,7 +556,8 @@ import {
 | 
			
		||||
    RangeChartWidgetSettingsComponent,
 | 
			
		||||
    BarChartWithLabelsWidgetSettingsComponent,
 | 
			
		||||
    SingleSwitchWidgetSettingsComponent,
 | 
			
		||||
    ActionButtonWidgetSettingsComponent
 | 
			
		||||
    ActionButtonWidgetSettingsComponent,
 | 
			
		||||
    CommandButtonWidgetSettingsComponent
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export class WidgetSettingsModule {
 | 
			
		||||
@ -639,5 +644,6 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
 | 
			
		||||
  'tb-range-chart-widget-settings': RangeChartWidgetSettingsComponent,
 | 
			
		||||
  'tb-bar-chart-with-labels-widget-settings': BarChartWithLabelsWidgetSettingsComponent,
 | 
			
		||||
  'tb-single-switch-widget-settings': SingleSwitchWidgetSettingsComponent,
 | 
			
		||||
  'tb-action-button-widget-settings': ActionButtonWidgetSettingsComponent
 | 
			
		||||
  'tb-action-button-widget-settings': ActionButtonWidgetSettingsComponent,
 | 
			
		||||
  'tb-command-button-widget-settings': CommandButtonWidgetSettingsComponent
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,7 @@ import {
 | 
			
		||||
} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.component';
 | 
			
		||||
import { SingleSwitchWidgetComponent } from '@home/components/widget/lib/rpc/single-switch-widget.component';
 | 
			
		||||
import { ActionButtonWidgetComponent } from '@home/components/widget/lib/button/action-button-widget.component';
 | 
			
		||||
import { CommandButtonWidgetComponent } from '@home/components/widget/lib/button/command-button-widget.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations:
 | 
			
		||||
@ -116,7 +117,8 @@ import { ActionButtonWidgetComponent } from '@home/components/widget/lib/button/
 | 
			
		||||
      RangeChartWidgetComponent,
 | 
			
		||||
      BarChartWithLabelsWidgetComponent,
 | 
			
		||||
      SingleSwitchWidgetComponent,
 | 
			
		||||
      ActionButtonWidgetComponent
 | 
			
		||||
      ActionButtonWidgetComponent,
 | 
			
		||||
      CommandButtonWidgetComponent
 | 
			
		||||
    ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
@ -165,7 +167,8 @@ import { ActionButtonWidgetComponent } from '@home/components/widget/lib/button/
 | 
			
		||||
        RangeChartWidgetComponent,
 | 
			
		||||
        BarChartWithLabelsWidgetComponent,
 | 
			
		||||
        SingleSwitchWidgetComponent,
 | 
			
		||||
        ActionButtonWidgetComponent
 | 
			
		||||
        ActionButtonWidgetComponent,
 | 
			
		||||
        CommandButtonWidgetComponent
 | 
			
		||||
    ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    {provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule }
 | 
			
		||||
 | 
			
		||||
@ -5187,6 +5187,11 @@
 | 
			
		||||
            "on-click": "On click",
 | 
			
		||||
            "on-click-hint": "Action performed when the button is clicked."
 | 
			
		||||
        },
 | 
			
		||||
        "command-button": {
 | 
			
		||||
            "behavior": "Behavior",
 | 
			
		||||
            "on-click": "On click",
 | 
			
		||||
            "on-click-hint": "Action performed when the button is clicked."
 | 
			
		||||
        },
 | 
			
		||||
        "button": {
 | 
			
		||||
            "layout": "Layout",
 | 
			
		||||
            "outlined": "Outlined",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user