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