UI: Improve mobile action
This commit is contained in:
		
							parent
							
								
									609a68c991
								
							
						
					
					
						commit
						c24401603a
					
				@ -35,117 +35,73 @@
 | 
			
		||||
      </mat-icon>
 | 
			
		||||
    </mat-form-field>
 | 
			
		||||
  </div>
 | 
			
		||||
  <ng-container [formGroup]="mobileActionTypeFormGroup" [ngSwitch]="mobileActionFormGroup.get('type').value">
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionType.deviceProvision">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="handleProvisionSuccessFunction"
 | 
			
		||||
        functionName="handleProvisionSuccess"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['deviceName', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionFormGroup.get('type').value === mobileActionType.mapDirection ||
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value === mobileActionType.mapLocation ?
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value : ''">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="getLocationFunction"
 | 
			
		||||
        functionName="getLocation"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_get_location_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionType.makePhoneCall">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="getPhoneNumberFunction"
 | 
			
		||||
        functionName="getPhoneNumber"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_get_phone_number_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionFormGroup.get('type').value === mobileActionType.takePhoto ||
 | 
			
		||||
  <ng-container [formGroup]="mobileActionTypeFormGroup">
 | 
			
		||||
    @if (mobileActionFormGroup.get('type').value === mobileActionType.takePhoto ||
 | 
			
		||||
      mobileActionFormGroup.get('type').value === mobileActionType.takePictureFromGallery ||
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value === mobileActionType.takeScreenshot ?
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value : ''">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="processImageFunction"
 | 
			
		||||
        functionName="processImage"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['imageUrl', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_process_image_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionType.scanQrCode">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="processQrCodeFunction"
 | 
			
		||||
        functionName="processQrCode"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['code', 'format', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_process_qr_code_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionType.getLocation">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="processLocationFunction"
 | 
			
		||||
        functionName="processLocation"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['latitude', 'longitude', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_process_location_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    <ng-template [ngSwitchCase]="mobileActionFormGroup.get('type').value === mobileActionType.mapDirection ||
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value === mobileActionType.mapLocation ||
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value === mobileActionType.makePhoneCall ?
 | 
			
		||||
                                 mobileActionFormGroup.get('type').value : ''">
 | 
			
		||||
      <tb-js-func
 | 
			
		||||
        formControlName="processLaunchResultFunction"
 | 
			
		||||
        functionName="processLaunchResult"
 | 
			
		||||
        withModules
 | 
			
		||||
        [functionArgs]="['launched', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
        [globalVariables]="functionScopeVariables"
 | 
			
		||||
        [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
        hideBrackets
 | 
			
		||||
        helpId="widget/action/mobile_process_launch_result_fn"
 | 
			
		||||
      ></tb-js-func>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
  <tb-js-func *ngIf="mobileActionFormGroup.get('type').value"
 | 
			
		||||
              formControlName="handleEmptyResultFunction"
 | 
			
		||||
              functionName="handleEmptyResult"
 | 
			
		||||
              withModules
 | 
			
		||||
              [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
              [globalVariables]="functionScopeVariables"
 | 
			
		||||
              [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
              hideBrackets
 | 
			
		||||
              helpId="widget/action/mobile_handle_empty_result_fn"
 | 
			
		||||
  ></tb-js-func>
 | 
			
		||||
  <tb-js-func *ngIf="mobileActionFormGroup.get('type').value"
 | 
			
		||||
              formControlName="handleErrorFunction"
 | 
			
		||||
              functionName="handleError"
 | 
			
		||||
              withModules
 | 
			
		||||
              [functionArgs]="['error', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
 | 
			
		||||
              [globalVariables]="functionScopeVariables"
 | 
			
		||||
              [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
              hideBrackets
 | 
			
		||||
              helpId="widget/action/mobile_handle_error_fn"
 | 
			
		||||
  ></tb-js-func>
 | 
			
		||||
      mobileActionFormGroup.get('type').value === mobileActionType.takeScreenshot) {
 | 
			
		||||
      <div class="tb-form-row">
 | 
			
		||||
        <mat-slide-toggle class="mat-slide" formControlName="saveToGallery">
 | 
			
		||||
          {{ 'widget-action.mobile.save-to-gallery' | translate }}
 | 
			
		||||
        </mat-slide-toggle>
 | 
			
		||||
      </div>
 | 
			
		||||
    }
 | 
			
		||||
    @if (mobileActionFormGroup.get('type').value === mobileActionType.deviceProvision) {
 | 
			
		||||
      <div class="tb-form-row">
 | 
			
		||||
        <div class="fixed-title-width">{{ 'widget-action.mobile.provision-type' | translate }}*</div>
 | 
			
		||||
        <mat-form-field class="flex-1" appearance="outline" subscriptSizing="dynamic">
 | 
			
		||||
          <mat-select formControlName="provisionType">
 | 
			
		||||
            <mat-option *ngFor="let type of provisionTypes" [value]="type">
 | 
			
		||||
              {{ provisionTypeTranslationMap.get(type) | translate }}
 | 
			
		||||
            </mat-option>
 | 
			
		||||
          </mat-select>
 | 
			
		||||
        </mat-form-field>
 | 
			
		||||
      </div>
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @for (config of actionConfig; track config.formControlName) {
 | 
			
		||||
      <div class="tb-form-panel stroked">
 | 
			
		||||
        <mat-expansion-panel class="tb-settings">
 | 
			
		||||
          <mat-expansion-panel-header>
 | 
			
		||||
            <mat-panel-description class="flex items-stretch justify-start">
 | 
			
		||||
              {{ config.title | translate }}
 | 
			
		||||
            </mat-panel-description>
 | 
			
		||||
          </mat-expansion-panel-header>
 | 
			
		||||
          <tb-js-func
 | 
			
		||||
            [formControlName]="config.formControlName"
 | 
			
		||||
            [functionName]="config.functionName"
 | 
			
		||||
            withModules
 | 
			
		||||
            [functionArgs]="config.functionArgs"
 | 
			
		||||
            [globalVariables]="functionScopeVariables"
 | 
			
		||||
            [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
            hideBrackets
 | 
			
		||||
            [helpId]="config.helpId"
 | 
			
		||||
          ></tb-js-func>
 | 
			
		||||
        </mat-expansion-panel>
 | 
			
		||||
      </div>
 | 
			
		||||
    }
 | 
			
		||||
  </ng-container>
 | 
			
		||||
 | 
			
		||||
  @if(mobileActionFormGroup.get('type').value) {
 | 
			
		||||
    @for (config of commonActionConfig; track config.formControlName) {
 | 
			
		||||
      <div class="tb-form-panel stroked">
 | 
			
		||||
        <mat-expansion-panel class="tb-settings">
 | 
			
		||||
          <mat-expansion-panel-header>
 | 
			
		||||
            <mat-panel-description class="flex items-stretch justify-start">
 | 
			
		||||
              {{ config.title | translate }}
 | 
			
		||||
            </mat-panel-description>
 | 
			
		||||
          </mat-expansion-panel-header>
 | 
			
		||||
          <tb-js-func
 | 
			
		||||
            [formControlName]="config.formControlName"
 | 
			
		||||
            [functionName]="config.functionName"
 | 
			
		||||
            withModules
 | 
			
		||||
            [functionArgs]="config.functionArgs"
 | 
			
		||||
            [globalVariables]="functionScopeVariables"
 | 
			
		||||
            [editorCompleter]="customActionEditorCompleter"
 | 
			
		||||
            hideBrackets
 | 
			
		||||
            [helpId]="config.helpId"
 | 
			
		||||
          ></tb-js-func>
 | 
			
		||||
        </mat-expansion-panel>
 | 
			
		||||
      </div>
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,9 @@ import {
 | 
			
		||||
} from '@angular/forms';
 | 
			
		||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
 | 
			
		||||
import {
 | 
			
		||||
  ActionConfig,
 | 
			
		||||
  ProvisionType,
 | 
			
		||||
  provisionTypeTranslationMap,
 | 
			
		||||
  WidgetActionType,
 | 
			
		||||
  WidgetMobileActionDescriptor,
 | 
			
		||||
  WidgetMobileActionType,
 | 
			
		||||
@ -35,6 +38,7 @@ import {
 | 
			
		||||
  getDefaultGetPhoneNumberFunction,
 | 
			
		||||
  getDefaultHandleEmptyResultFunction,
 | 
			
		||||
  getDefaultHandleErrorFunction,
 | 
			
		||||
  getDefaultHandleNonMobileFallBackFunction,
 | 
			
		||||
  getDefaultProcessImageFunction,
 | 
			
		||||
  getDefaultProcessLaunchResultFunction,
 | 
			
		||||
  getDefaultProcessLocationFunction,
 | 
			
		||||
@ -68,6 +72,12 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
 | 
			
		||||
  functionScopeVariables: string[];
 | 
			
		||||
 | 
			
		||||
  actionConfig: ActionConfig[];
 | 
			
		||||
  commonActionConfig: ActionConfig[];
 | 
			
		||||
 | 
			
		||||
  provisionTypes: string[] = Object.keys(ProvisionType);
 | 
			
		||||
  provisionTypeTranslationMap = provisionTypeTranslationMap;
 | 
			
		||||
 | 
			
		||||
  private requiredValue: boolean;
 | 
			
		||||
  get required(): boolean {
 | 
			
		||||
    return this.requiredValue;
 | 
			
		||||
@ -99,8 +109,10 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
    this.mobileActionFormGroup = this.fb.group({
 | 
			
		||||
      type: [null, Validators.required],
 | 
			
		||||
      handleEmptyResultFunction: [null],
 | 
			
		||||
      handleErrorFunction: [null]
 | 
			
		||||
      handleErrorFunction: [null],
 | 
			
		||||
      handleNonMobileFallbackFunction: [null]
 | 
			
		||||
    });
 | 
			
		||||
    this.getCommonActionConfigs();
 | 
			
		||||
    this.mobileActionFormGroup.get('type').valueChanges.pipe(
 | 
			
		||||
      takeUntilDestroyed(this.destroyRef)
 | 
			
		||||
    ).subscribe((type: WidgetMobileActionType) => {
 | 
			
		||||
@ -109,6 +121,7 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
        action = {...action, ...this.mobileActionTypeFormGroup.value};
 | 
			
		||||
      }
 | 
			
		||||
      this.updateMobileActionType(type, action);
 | 
			
		||||
      this.getActionConfigs();
 | 
			
		||||
    });
 | 
			
		||||
    this.mobileActionFormGroup.valueChanges.pipe(
 | 
			
		||||
      takeUntilDestroyed(this.destroyRef)
 | 
			
		||||
@ -133,10 +146,14 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  writeValue(value: WidgetMobileActionDescriptor | null): void {
 | 
			
		||||
    this.mobileActionFormGroup.patchValue({type: value?.type,
 | 
			
		||||
    this.mobileActionFormGroup.patchValue({
 | 
			
		||||
      type: value?.type,
 | 
			
		||||
      handleEmptyResultFunction: value?.handleEmptyResultFunction,
 | 
			
		||||
                                                 handleErrorFunction: value?.handleErrorFunction}, {emitEvent: false});
 | 
			
		||||
      handleErrorFunction: value?.handleErrorFunction,
 | 
			
		||||
      handleNonMobileFallbackFunction: value?.handleNonMobileFallbackFunction
 | 
			
		||||
    }, {emitEvent: false});
 | 
			
		||||
    this.updateMobileActionType(value?.type, value);
 | 
			
		||||
    this.getActionConfigs();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private updateModel() {
 | 
			
		||||
@ -164,6 +181,12 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
        handleErrorFunction = getDefaultHandleErrorFunction(type);
 | 
			
		||||
        this.mobileActionFormGroup.patchValue({handleErrorFunction}, {emitEvent: false});
 | 
			
		||||
      }
 | 
			
		||||
      let handleNonMobileFallbackFunction = action?.handleNonMobileFallbackFunction;
 | 
			
		||||
      const defaultHandleNonMobileFallbackFunction = getDefaultHandleNonMobileFallBackFunction();
 | 
			
		||||
      if (defaultHandleNonMobileFallbackFunction !== handleNonMobileFallbackFunction) {
 | 
			
		||||
        handleNonMobileFallbackFunction = getDefaultHandleNonMobileFallBackFunction();
 | 
			
		||||
        this.mobileActionFormGroup.patchValue({handleNonMobileFallbackFunction}, {emitEvent: false});
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.mobileActionTypeFormGroup = this.fb.group({});
 | 
			
		||||
    if (type) {
 | 
			
		||||
@ -183,6 +206,10 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
            'processImageFunction',
 | 
			
		||||
            this.fb.control(processImageFunction, [])
 | 
			
		||||
          );
 | 
			
		||||
          this.mobileActionTypeFormGroup.addControl(
 | 
			
		||||
            'saveToGallery',
 | 
			
		||||
            this.fb.control(action?.saveToGallery || false, [])
 | 
			
		||||
          );
 | 
			
		||||
          break;
 | 
			
		||||
        case WidgetMobileActionType.mapDirection:
 | 
			
		||||
        case WidgetMobileActionType.mapLocation:
 | 
			
		||||
@ -267,6 +294,10 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
            'handleProvisionSuccessFunction',
 | 
			
		||||
            this.fb.control(handleProvisionSuccessFunction, [Validators.required])
 | 
			
		||||
          );
 | 
			
		||||
          this.mobileActionTypeFormGroup.addControl(
 | 
			
		||||
            'provisionType',
 | 
			
		||||
            this.fb.control(action?.provisionType || ProvisionType.auto, [])
 | 
			
		||||
          );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.mobileActionTypeFormGroup.valueChanges.pipe(
 | 
			
		||||
@ -276,5 +307,108 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getActionConfigs() {
 | 
			
		||||
    const type = this.mobileActionFormGroup.get('type').value;
 | 
			
		||||
    this.actionConfig = [];
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case this.mobileActionType.deviceProvision:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.handle-provision-success-function',
 | 
			
		||||
          formControlName: 'handleProvisionSuccessFunction',
 | 
			
		||||
          functionName: 'handleProvisionSuccess',
 | 
			
		||||
          functionArgs: ['deviceName', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case this.mobileActionType.mapDirection:
 | 
			
		||||
      case this.mobileActionType.mapLocation:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.get-location-function',
 | 
			
		||||
          formControlName: 'getLocationFunction',
 | 
			
		||||
          functionName: 'getLocation',
 | 
			
		||||
          functionArgs: ['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_get_location_fn'
 | 
			
		||||
        });
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.process-launch-result-function',
 | 
			
		||||
          formControlName: 'processLaunchResultFunction',
 | 
			
		||||
          functionName: 'processLaunchResult',
 | 
			
		||||
          functionArgs: ['launched', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_process_launch_result_fn'
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case this.mobileActionType.makePhoneCall:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.get-phone-number-function',
 | 
			
		||||
          formControlName: 'getPhoneNumberFunction',
 | 
			
		||||
          functionName: 'getPhoneNumber',
 | 
			
		||||
          functionArgs: ['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_get_phone_number_fn'
 | 
			
		||||
        });
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.process-launch-result-function',
 | 
			
		||||
          formControlName: 'processLaunchResultFunction',
 | 
			
		||||
          functionName: 'processLaunchResult',
 | 
			
		||||
          functionArgs: ['launched', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_process_launch_result_fn'
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case this.mobileActionType.takePhoto:
 | 
			
		||||
      case this.mobileActionType.takePictureFromGallery:
 | 
			
		||||
      case this.mobileActionType.takeScreenshot:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.process-image-function',
 | 
			
		||||
          formControlName: 'processImageFunction',
 | 
			
		||||
          functionName: 'processImage',
 | 
			
		||||
          functionArgs: ['imageUrl', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_process_image_fn'
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case this.mobileActionType.scanQrCode:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.process-qr-code-function',
 | 
			
		||||
          formControlName: 'processQrCodeFunction',
 | 
			
		||||
          functionName: 'processQrCode',
 | 
			
		||||
          functionArgs: ['code', 'format', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_process_qr_code_fn'
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      case this.mobileActionType.getLocation:
 | 
			
		||||
        this.actionConfig.push({
 | 
			
		||||
          title: 'widget-action.mobile.process-location-function',
 | 
			
		||||
          formControlName: 'processLocationFunction',
 | 
			
		||||
          functionName: 'processLocation',
 | 
			
		||||
          functionArgs: ['latitude', 'longitude', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
          helpId: 'widget/action/mobile_process_location_fn'
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getCommonActionConfigs() {
 | 
			
		||||
    this.commonActionConfig = [
 | 
			
		||||
      {
 | 
			
		||||
        title: 'widget-action.mobile.handle-empty-result-function',
 | 
			
		||||
        formControlName: 'handleEmptyResultFunction',
 | 
			
		||||
        functionName: 'handleEmptyResult',
 | 
			
		||||
        functionArgs: ['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
        helpId: 'widget/action/mobile_handle_empty_result_fn'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        title: 'widget-action.mobile.handle-error-function',
 | 
			
		||||
        formControlName: 'handleErrorFunction',
 | 
			
		||||
        functionName: 'handleError',
 | 
			
		||||
        functionArgs: ['error', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel'],
 | 
			
		||||
        helpId: 'widget/action/mobile_handle_error_fn'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        title: 'widget-action.mobile.handle-non-mobile-fallback-function',
 | 
			
		||||
        formControlName: 'handleNonMobileFallbackFunction',
 | 
			
		||||
        functionName: 'handleNonMobileFallback',
 | 
			
		||||
        functionArgs: ['$event', 'widgetContext'],
 | 
			
		||||
        helpId: 'widget/action/mobile_handle_non_mobile_fallback_fn'
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected readonly WidgetActionType = WidgetActionType;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -172,6 +172,14 @@ const handleErrorFunctionTemplate: TbFunction =
 | 
			
		||||
  '    }, 100);\n' +
 | 
			
		||||
  '}\n';
 | 
			
		||||
 | 
			
		||||
const handleNonMobileFallbackFunctionTemplate: TbFunction =
 | 
			
		||||
  '// Optional function body to handle non-mobile fallback \n' +
 | 
			
		||||
  'showFallbackToast();\n' +
 | 
			
		||||
  '\n' +
 | 
			
		||||
  'function showFallbackToast(title, error) {\n' +
 | 
			
		||||
  '    widgetContext.showWarnToast(\'This action is only available in the mobile application.\');\n' +
 | 
			
		||||
  '}\n';
 | 
			
		||||
 | 
			
		||||
const getLocationFunctionTemplate: TbFunction =
 | 
			
		||||
  '// Function body that should return location as array of two numbers (latitude, longitude) for further processing by mobile action.\n' +
 | 
			
		||||
  '// Usually location can be obtained from entity attributes/telemetry. \n\n' +
 | 
			
		||||
@ -326,3 +334,5 @@ export const getDefaultHandleErrorFunction = (type: WidgetMobileActionType): TbF
 | 
			
		||||
  }
 | 
			
		||||
  return handleErrorFunctionTemplate.replace('--TITLE--', title);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const getDefaultHandleNonMobileFallBackFunction = () => handleNonMobileFallbackFunctionTemplate;
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ import {
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { DashboardWidget } from '@home/models/dashboard-component.models';
 | 
			
		||||
import {
 | 
			
		||||
  MobileImageResult,
 | 
			
		||||
  Widget,
 | 
			
		||||
  WidgetAction,
 | 
			
		||||
  WidgetActionDescriptor,
 | 
			
		||||
@ -126,6 +127,7 @@ import { IModulesMap } from '@modules/common/modules-map.models';
 | 
			
		||||
import { DashboardUtilsService } from '@core/services/dashboard-utils.service';
 | 
			
		||||
import { CompiledTbFunction, compileTbFunction, isNotEmptyTbFunction } from '@shared/models/js-function.models';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { addDiagnosticChain } from '@angular/compiler-cli/src/ngtsc/diagnostics';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-widget',
 | 
			
		||||
@ -1222,12 +1224,16 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
 | 
			
		||||
    switch (type) {
 | 
			
		||||
      case WidgetMobileActionType.takePictureFromGallery:
 | 
			
		||||
      case WidgetMobileActionType.takePhoto:
 | 
			
		||||
      case WidgetMobileActionType.takeScreenshot:
 | 
			
		||||
        argsObservable = of([mobileAction.saveToGallery]);
 | 
			
		||||
        break;
 | 
			
		||||
      case WidgetMobileActionType.scanQrCode:
 | 
			
		||||
      case WidgetMobileActionType.getLocation:
 | 
			
		||||
      case WidgetMobileActionType.takeScreenshot:
 | 
			
		||||
      case WidgetMobileActionType.deviceProvision:
 | 
			
		||||
        argsObservable = of([]);
 | 
			
		||||
        break;
 | 
			
		||||
      case WidgetMobileActionType.deviceProvision:
 | 
			
		||||
        argsObservable = of([mobileAction.provisionType]);
 | 
			
		||||
        break;
 | 
			
		||||
      case WidgetMobileActionType.mapDirection:
 | 
			
		||||
      case WidgetMobileActionType.mapLocation:
 | 
			
		||||
        argsObservable = compileTbFunction(this.http, mobileAction.getLocationFunction, '$event', 'widgetContext', 'entityId',
 | 
			
		||||
@ -1297,6 +1303,10 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
 | 
			
		||||
                    case WidgetMobileActionType.takePhoto:
 | 
			
		||||
                    case WidgetMobileActionType.takeScreenshot:
 | 
			
		||||
                      const imageUrl = actionResult.imageUrl;
 | 
			
		||||
                      if (!additionalParams) {
 | 
			
		||||
                        additionalParams = {};
 | 
			
		||||
                      }
 | 
			
		||||
                      additionalParams.imageInfo = actionResult.imageInfo;
 | 
			
		||||
                      if (isNotEmptyTbFunction(mobileAction.processImageFunction)) {
 | 
			
		||||
                        compileTbFunction(this.http, mobileAction.processImageFunction, 'imageUrl', '$event', 'widgetContext', 'entityId',
 | 
			
		||||
                          'entityName', 'additionalParams', 'entityLabel').subscribe(
 | 
			
		||||
@ -1421,6 +1431,23 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
 | 
			
		||||
                    );
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              } else if (!this.mobileService.isMobileApp()) {
 | 
			
		||||
                if (isNotEmptyTbFunction(mobileAction.handleNonMobileFallbackFunction)) {
 | 
			
		||||
                  compileTbFunction(this.http, mobileAction.handleNonMobileFallbackFunction, '$event', 'widgetContext',).subscribe(
 | 
			
		||||
                    {
 | 
			
		||||
                      next: (compiled) => {
 | 
			
		||||
                        try {
 | 
			
		||||
                          compiled.execute($event, this.widgetContext);
 | 
			
		||||
                        } catch (e) {
 | 
			
		||||
                          console.error(e);
 | 
			
		||||
                        }
 | 
			
		||||
                      },
 | 
			
		||||
                      error: (err) => {
 | 
			
		||||
                        console.error(err);
 | 
			
		||||
                      }
 | 
			
		||||
                    }
 | 
			
		||||
                  );
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { AfterViewInit, DestroyRef, Directive, EventEmitter, inject, Inject, OnInit, Type } from '@angular/core';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { AbstractControl, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
import { AbstractControl, UntypedFormGroup, ValidatorFn } from '@angular/forms';
 | 
			
		||||
import { Observable } from 'rxjs';
 | 
			
		||||
import { Dashboard } from '@shared/models/dashboard.models';
 | 
			
		||||
import { IAliasController } from '@core/api/widget-api.models';
 | 
			
		||||
@ -51,6 +51,7 @@ import { TbFunction } from '@shared/models/js-function.models';
 | 
			
		||||
import { FormProperty, jsonFormSchemaToFormProperties } from '@shared/models/dynamic-form.models';
 | 
			
		||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
 | 
			
		||||
import { TbUnit } from '@shared/models/unit.models';
 | 
			
		||||
import { ImageResourceInfo } from '@shared/models/resource.models';
 | 
			
		||||
 | 
			
		||||
export enum widgetType {
 | 
			
		||||
  timeseries = 'timeseries',
 | 
			
		||||
@ -622,6 +623,30 @@ export enum WidgetMobileActionType {
 | 
			
		||||
  deviceProvision = 'deviceProvision',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ActionConfig {
 | 
			
		||||
  title: string,
 | 
			
		||||
  formControlName: string,
 | 
			
		||||
  functionName: string,
 | 
			
		||||
  functionArgs: string[],
 | 
			
		||||
  helpId?: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum ProvisionType {
 | 
			
		||||
  auto = 'auto',
 | 
			
		||||
  wiFi = 'wiFi',
 | 
			
		||||
  ble = 'ble',
 | 
			
		||||
  softAp = 'softAp'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const provisionTypeTranslationMap = new Map<ProvisionType, string>(
 | 
			
		||||
  [
 | 
			
		||||
    [ ProvisionType.auto, 'widget-action.mobile.auto' ],
 | 
			
		||||
    [ ProvisionType.wiFi, 'widget-action.mobile.wi-fi' ],
 | 
			
		||||
    [ ProvisionType.ble, 'widget-action.mobile.ble' ],
 | 
			
		||||
    [ ProvisionType.softAp, 'widget-action.mobile.soft-ap' ],
 | 
			
		||||
  ]
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export enum MapItemType {
 | 
			
		||||
  marker = 'marker',
 | 
			
		||||
  polygon = 'polygon',
 | 
			
		||||
@ -675,6 +700,7 @@ export interface MobileLaunchResult {
 | 
			
		||||
 | 
			
		||||
export interface MobileImageResult {
 | 
			
		||||
  imageUrl: string;
 | 
			
		||||
  imageInfo?: ImageResourceInfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface MobileQrCodeResult {
 | 
			
		||||
@ -706,10 +732,12 @@ export interface WidgetMobileActionResult<T extends MobileActionResult> {
 | 
			
		||||
 | 
			
		||||
export interface ProvisionSuccessDescriptor {
 | 
			
		||||
  handleProvisionSuccessFunction: TbFunction;
 | 
			
		||||
  provisionType?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ProcessImageDescriptor {
 | 
			
		||||
  processImageFunction: TbFunction;
 | 
			
		||||
  saveToGallery?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ProcessLaunchResultDescriptor {
 | 
			
		||||
@ -743,6 +771,7 @@ export interface WidgetMobileActionDescriptor extends WidgetMobileActionDescript
 | 
			
		||||
  type: WidgetMobileActionType;
 | 
			
		||||
  handleErrorFunction?: TbFunction;
 | 
			
		||||
  handleEmptyResultFunction?: TbFunction;
 | 
			
		||||
  handleNonMobileFallbackFunction?: TbFunction;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface CustomActionDescriptor {
 | 
			
		||||
 | 
			
		||||
@ -6868,7 +6868,23 @@
 | 
			
		||||
          "scan-qr-code": "Scan QR Code",
 | 
			
		||||
          "make-phone-call": "Make phone call",
 | 
			
		||||
          "get-location": "Get phone location",
 | 
			
		||||
          "take-screenshot": "Take screenshot"
 | 
			
		||||
          "take-screenshot": "Take screenshot",
 | 
			
		||||
          "handle-provision-success-function": "Handle provision success function",
 | 
			
		||||
          "get-location-function": "Get location function",
 | 
			
		||||
          "process-launch-result-function": "Process launch result function",
 | 
			
		||||
          "get-phone-number-function": "Get phone number function",
 | 
			
		||||
          "process-image-function": "Process image function",
 | 
			
		||||
          "process-qr-code-function": "Process QR code function",
 | 
			
		||||
          "process-location-function": "Process location function",
 | 
			
		||||
          "handle-empty-result-function": "Handle empty result function",
 | 
			
		||||
          "handle-error-function": "Handle error function",
 | 
			
		||||
          "handle-non-mobile-fallback-function": "Handle Non-Mobile fallback function",
 | 
			
		||||
          "save-to-gallery": "Save to gallery",
 | 
			
		||||
          "provision-type": "Provision type",
 | 
			
		||||
          "auto": "Auto",
 | 
			
		||||
          "wi-fi": "Wi-Fi",
 | 
			
		||||
          "ble": "BLE",
 | 
			
		||||
          "soft-ap": "Soft AP"
 | 
			
		||||
        },
 | 
			
		||||
        "custom-action-function": "Custom action function",
 | 
			
		||||
        "custom-pretty-function": "Custom action (with HTML template) function",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user