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