UI: Add JS modules support for mobile action functions.

This commit is contained in:
Igor Kulikov 2024-12-03 13:23:22 +02:00
parent a411213d6c
commit 3db9d68c12
5 changed files with 225 additions and 157 deletions

View File

@ -42,6 +42,7 @@
<tb-js-func <tb-js-func
formControlName="getLocationFunction" formControlName="getLocationFunction"
functionName="getLocation" functionName="getLocation"
withModules
[functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -53,6 +54,7 @@
<tb-js-func <tb-js-func
formControlName="getPhoneNumberFunction" formControlName="getPhoneNumberFunction"
functionName="getPhoneNumber" functionName="getPhoneNumber"
withModules
[functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -67,6 +69,7 @@
<tb-js-func <tb-js-func
formControlName="processImageFunction" formControlName="processImageFunction"
functionName="processImage" functionName="processImage"
withModules
[functionArgs]="['imageUrl', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['imageUrl', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -78,6 +81,7 @@
<tb-js-func <tb-js-func
formControlName="processQrCodeFunction" formControlName="processQrCodeFunction"
functionName="processQrCode" functionName="processQrCode"
withModules
[functionArgs]="['code', 'format', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['code', 'format', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -89,6 +93,7 @@
<tb-js-func <tb-js-func
formControlName="processLocationFunction" formControlName="processLocationFunction"
functionName="processLocation" functionName="processLocation"
withModules
[functionArgs]="['latitude', 'longitude', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['latitude', 'longitude', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -103,6 +108,7 @@
<tb-js-func <tb-js-func
formControlName="processLaunchResultFunction" formControlName="processLaunchResultFunction"
functionName="processLaunchResult" functionName="processLaunchResult"
withModules
[functionArgs]="['launched', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['launched', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -114,6 +120,7 @@
<tb-js-func *ngIf="mobileActionFormGroup.get('type').value" <tb-js-func *ngIf="mobileActionFormGroup.get('type').value"
formControlName="handleEmptyResultFunction" formControlName="handleEmptyResultFunction"
functionName="handleEmptyResult" functionName="handleEmptyResult"
withModules
[functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"
@ -123,6 +130,7 @@
<tb-js-func *ngIf="mobileActionFormGroup.get('type').value" <tb-js-func *ngIf="mobileActionFormGroup.get('type').value"
formControlName="handleErrorFunction" formControlName="handleErrorFunction"
functionName="handleError" functionName="handleError"
withModules
[functionArgs]="['error', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']" [functionArgs]="['error', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter" [editorCompleter]="customActionEditorCompleter"

View File

@ -41,6 +41,7 @@ import {
getDefaultProcessQrCodeFunction getDefaultProcessQrCodeFunction
} from '@home/components/widget/lib/settings/common/action/mobile-action-editor.models'; } from '@home/components/widget/lib/settings/common/action/mobile-action-editor.models';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { TbFunction } from '@shared/models/js-function.models';
@Component({ @Component({
selector: 'tb-mobile-action-editor', selector: 'tb-mobile-action-editor',
@ -159,7 +160,7 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
} }
this.mobileActionTypeFormGroup = this.fb.group({}); this.mobileActionTypeFormGroup = this.fb.group({});
if (type) { if (type) {
let processLaunchResultFunction: string; let processLaunchResultFunction: TbFunction;
switch (type) { switch (type) {
case WidgetMobileActionType.takePictureFromGallery: case WidgetMobileActionType.takePictureFromGallery:
case WidgetMobileActionType.takePhoto: case WidgetMobileActionType.takePhoto:

View File

@ -15,8 +15,9 @@
/// ///
import { WidgetMobileActionType } from '@shared/models/widget.models'; import { WidgetMobileActionType } from '@shared/models/widget.models';
import { TbFunction } from '@shared/models/js-function.models';
const processImageFunctionTemplate = const processImageFunctionTemplate: TbFunction =
'// Function body to process image obtained as a result of mobile action (take photo, take image from gallery, etc.). \n' + '// Function body to process image obtained as a result of mobile action (take photo, take image from gallery, etc.). \n' +
'// - imageUrl - image URL in base64 data format\n\n' + '// - imageUrl - image URL in base64 data format\n\n' +
'showImageDialog(\'--TITLE--\', imageUrl);\n' + 'showImageDialog(\'--TITLE--\', imageUrl);\n' +
@ -82,7 +83,7 @@ const processImageFunctionTemplate =
' }\n' + ' }\n' +
'}\n'; '}\n';
const processLaunchResultFunctionTemplate = const processLaunchResultFunctionTemplate: TbFunction =
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
'// Optional function body to process result of attempt to launch external mobile application (for ex. map application or phone call application). \n' + '// Optional function body to process result of attempt to launch external mobile application (for ex. map application or phone call application). \n' +
'// - launched - boolean value indicating if the external application was successfully launched.\n\n' + '// - launched - boolean value indicating if the external application was successfully launched.\n\n' +
@ -94,7 +95,7 @@ const processLaunchResultFunctionTemplate =
' }, 100);\n' + ' }, 100);\n' +
'}\n'; '}\n';
const processQrCodeFunction = const processQrCodeFunction: TbFunction =
'// Function body to process result of QR code scanning. \n' + '// Function body to process result of QR code scanning. \n' +
'// - code - scanned QR code\n' + '// - code - scanned QR code\n' +
'// - format - scanned QR code format\n\n' + '// - format - scanned QR code format\n\n' +
@ -106,7 +107,7 @@ const processQrCodeFunction =
' }, 100);\n' + ' }, 100);\n' +
'}\n'; '}\n';
const processLocationFunction = const processLocationFunction: TbFunction =
'// Function body to process current location of the phone. \n' + '// Function body to process current location of the phone. \n' +
'// - latitude - phone location latitude\n' + '// - latitude - phone location latitude\n' +
'// - longitude - phone location longitude\n\n' + '// - longitude - phone location longitude\n\n' +
@ -137,7 +138,7 @@ const processLocationFunction =
' }, 100);\n' + ' }, 100);\n' +
'}'; '}';
const handleEmptyResultFunctionTemplate = const handleEmptyResultFunctionTemplate: TbFunction =
'// Optional function body to handle empty result. \n' + '// Optional function body to handle empty result. \n' +
'// Usually this happens when user cancels the action (for ex. by pressing phone back button). \n\n' + '// Usually this happens when user cancels the action (for ex. by pressing phone back button). \n\n' +
'showEmptyResultDialog(\'--MESSAGE--\');\n' + 'showEmptyResultDialog(\'--MESSAGE--\');\n' +
@ -148,7 +149,7 @@ const handleEmptyResultFunctionTemplate =
' }, 100);\n' + ' }, 100);\n' +
'}\n'; '}\n';
const handleErrorFunctionTemplate = const handleErrorFunctionTemplate: TbFunction =
'// Optional function body to handle error occurred while mobile action execution \n' + '// Optional function body to handle error occurred while mobile action execution \n' +
'// - error - Error message\n\n' + '// - error - Error message\n\n' +
'showErrorDialog(\'--TITLE--\', error);\n' + 'showErrorDialog(\'--TITLE--\', error);\n' +
@ -159,7 +160,7 @@ const handleErrorFunctionTemplate =
' }, 100);\n' + ' }, 100);\n' +
'}\n'; '}\n';
const getLocationFunctionTemplate = 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' +
'return getLocationFromEntityAttributes();\n' + 'return getLocationFromEntityAttributes();\n' +
@ -182,7 +183,7 @@ const getLocationFunctionTemplate =
' }\n' + ' }\n' +
'}\n'; '}\n';
const getPhoneNumberFunctionTemplate = const getPhoneNumberFunctionTemplate: TbFunction =
'// Function body that should return phone number for further processing by mobile action.\n' + '// Function body that should return phone number for further processing by mobile action.\n' +
'// Usually phone number can be obtained from entity attributes/telemetry. \n\n' + '// Usually phone number can be obtained from entity attributes/telemetry. \n\n' +
'return getPhoneNumberFromEntityAttributes();\n' + 'return getPhoneNumberFromEntityAttributes();\n' +
@ -204,7 +205,7 @@ const getPhoneNumberFunctionTemplate =
' }\n' + ' }\n' +
'}\n'; '}\n';
export const getDefaultProcessImageFunction = (type: WidgetMobileActionType): string => { export const getDefaultProcessImageFunction = (type: WidgetMobileActionType): TbFunction => {
let title: string; let title: string;
switch (type) { switch (type) {
case WidgetMobileActionType.takePictureFromGallery: case WidgetMobileActionType.takePictureFromGallery:
@ -220,7 +221,7 @@ export const getDefaultProcessImageFunction = (type: WidgetMobileActionType): st
return processImageFunctionTemplate.replace('--TITLE--', title); return processImageFunctionTemplate.replace('--TITLE--', title);
}; };
export const getDefaultProcessLaunchResultFunction = (type: WidgetMobileActionType): string => { export const getDefaultProcessLaunchResultFunction = (type: WidgetMobileActionType): TbFunction => {
let title: string; let title: string;
switch (type) { switch (type) {
case WidgetMobileActionType.mapLocation: case WidgetMobileActionType.mapLocation:
@ -244,7 +245,7 @@ export const getDefaultGetLocationFunction = () => getLocationFunctionTemplate;
export const getDefaultGetPhoneNumberFunction = () => getPhoneNumberFunctionTemplate; export const getDefaultGetPhoneNumberFunction = () => getPhoneNumberFunctionTemplate;
export const getDefaultHandleEmptyResultFunction = (type: WidgetMobileActionType): string => { export const getDefaultHandleEmptyResultFunction = (type: WidgetMobileActionType): TbFunction => {
let message = 'Mobile action was cancelled!'; let message = 'Mobile action was cancelled!';
switch (type) { switch (type) {
case WidgetMobileActionType.takePictureFromGallery: case WidgetMobileActionType.takePictureFromGallery:
@ -275,7 +276,7 @@ export const getDefaultHandleEmptyResultFunction = (type: WidgetMobileActionType
return handleEmptyResultFunctionTemplate.replace('--MESSAGE--', message); return handleEmptyResultFunctionTemplate.replace('--MESSAGE--', message);
}; };
export const getDefaultHandleErrorFunction = (type: WidgetMobileActionType): string => { export const getDefaultHandleErrorFunction = (type: WidgetMobileActionType): TbFunction => {
let title = 'Mobile action failed'; let title = 'Mobile action failed';
switch (type) { switch (type) {
case WidgetMobileActionType.takePictureFromGallery: case WidgetMobileActionType.takePictureFromGallery:

View File

@ -70,9 +70,12 @@ import {
IDynamicWidgetComponent, IDynamicWidgetComponent,
ShowWidgetHeaderActionFunction, ShowWidgetHeaderActionFunction,
updateEntityParams, updateEntityParams,
WidgetContext, widgetContextToken, widgetErrorMessagesToken, WidgetContext,
widgetContextToken,
widgetErrorMessagesToken,
WidgetHeaderAction, WidgetHeaderAction,
WidgetInfo, widgetTitlePanelToken, WidgetInfo,
widgetTitlePanelToken,
WidgetTypeInstance WidgetTypeInstance
} from '@home/models/widget-component.models'; } from '@home/models/widget-component.models';
import { import {
@ -1204,16 +1207,17 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
break; break;
case WidgetMobileActionType.mapDirection: case WidgetMobileActionType.mapDirection:
case WidgetMobileActionType.mapLocation: case WidgetMobileActionType.mapLocation:
const getLocationFunctionString = mobileAction.getLocationFunction; argsObservable = compileTbFunction(this.http, mobileAction.getLocationFunction, '$event', 'widgetContext', 'entityId',
const getLocationFunction = new Function('$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel').pipe(
'entityName', 'additionalParams', 'entityLabel', getLocationFunctionString); switchMap(getLocationFunction => {
const locationArgs = getLocationFunction($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel); const locationArgs = getLocationFunction.execute($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
if (locationArgs && locationArgs instanceof Observable) { if (locationArgs && locationArgs instanceof Observable) {
argsObservable = locationArgs; return locationArgs;
} else { } else {
argsObservable = of(locationArgs); return of(locationArgs);
} }
argsObservable = argsObservable.pipe(map(latLng => { }),
map(latLng => {
let valid = false; let valid = false;
if (Array.isArray(latLng) && latLng.length === 2) { if (Array.isArray(latLng) && latLng.length === 2) {
if (typeof latLng[0] === 'number' && typeof latLng[1] === 'number') { if (typeof latLng[0] === 'number' && typeof latLng[1] === 'number') {
@ -1225,19 +1229,21 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
} else { } else {
throw new Error('Location function did not return valid array of latitude/longitude!'); throw new Error('Location function did not return valid array of latitude/longitude!');
} }
})); })
);
break; break;
case WidgetMobileActionType.makePhoneCall: case WidgetMobileActionType.makePhoneCall:
const getPhoneNumberFunctionString = mobileAction.getPhoneNumberFunction; argsObservable = compileTbFunction(this.http, mobileAction.getPhoneNumberFunction, '$event', 'widgetContext', 'entityId',
const getPhoneNumberFunction = new Function('$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel').pipe(
'entityName', 'additionalParams', 'entityLabel', getPhoneNumberFunctionString); switchMap(getPhoneNumberFunction => {
const phoneNumberArg = getPhoneNumberFunction($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel); const phoneNumberArg = getPhoneNumberFunction.execute($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
if (phoneNumberArg && phoneNumberArg instanceof Observable) { if (phoneNumberArg && phoneNumberArg instanceof Observable) {
argsObservable = phoneNumberArg.pipe(map(phoneNumber => [phoneNumber])); return phoneNumberArg.pipe(map(phoneNumber => [phoneNumber]));
} else { } else {
argsObservable = of([phoneNumberArg]); return of([phoneNumberArg]);
} }
argsObservable = argsObservable.pipe(map(phoneNumberArr => { }),
map(phoneNumberArr => {
let valid = false; let valid = false;
if (Array.isArray(phoneNumberArr) && phoneNumberArr.length === 1) { if (Array.isArray(phoneNumberArr) && phoneNumberArr.length === 1) {
if (phoneNumberArr[0] !== null) { if (phoneNumberArr[0] !== null) {
@ -1249,10 +1255,13 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
} else { } else {
throw new Error('Phone number function did not return valid number!'); throw new Error('Phone number function did not return valid number!');
} }
})); })
);
break; break;
} }
argsObservable.subscribe((args) => { argsObservable.subscribe(
{
next: (args) => {
this.mobileService.handleWidgetMobileAction(type, ...args).subscribe( this.mobileService.handleWidgetMobileAction(type, ...args).subscribe(
(result) => { (result) => {
if (result) { if (result) {
@ -1265,76 +1274,116 @@ 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 (mobileAction.processImageFunction && mobileAction.processImageFunction.length) { if (isNotEmptyTbFunction(mobileAction.processImageFunction)) {
compileTbFunction(this.http, mobileAction.processImageFunction, 'imageUrl', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const processImageFunction = new Function('imageUrl', '$event', 'widgetContext', 'entityId', compiled.execute(imageUrl, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
'entityName', 'additionalParams', 'entityLabel', mobileAction.processImageFunction);
processImageFunction(imageUrl, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
break; break;
case WidgetMobileActionType.scanQrCode: case WidgetMobileActionType.scanQrCode:
const code = actionResult.code; const code = actionResult.code;
const format = actionResult.format; const format = actionResult.format;
if (mobileAction.processQrCodeFunction && mobileAction.processQrCodeFunction.length) { if (isNotEmptyTbFunction(mobileAction.processQrCodeFunction)) {
compileTbFunction(this.http, mobileAction.processQrCodeFunction, 'code', 'format', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const processQrCodeFunction = new Function('code', 'format', '$event', 'widgetContext', 'entityId', compiled.execute(code, format, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
'entityName', 'additionalParams', 'entityLabel', mobileAction.processQrCodeFunction);
processQrCodeFunction(code, format, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
break; break;
case WidgetMobileActionType.getLocation: case WidgetMobileActionType.getLocation:
const latitude = actionResult.latitude; const latitude = actionResult.latitude;
const longitude = actionResult.longitude; const longitude = actionResult.longitude;
if (mobileAction.processLocationFunction && mobileAction.processLocationFunction.length) { if (isNotEmptyTbFunction(mobileAction.processLocationFunction)) {
compileTbFunction(this.http, mobileAction.processLocationFunction, 'latitude', 'longitude', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const processLocationFunction = new Function('latitude', 'longitude', '$event', 'widgetContext', 'entityId', compiled.execute(latitude, longitude, $event, this.widgetContext,
'entityName', 'additionalParams', 'entityLabel', mobileAction.processLocationFunction);
processLocationFunction(latitude, longitude, $event, this.widgetContext,
entityId, entityName, additionalParams, entityLabel); entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
break; break;
case WidgetMobileActionType.mapDirection: case WidgetMobileActionType.mapDirection:
case WidgetMobileActionType.mapLocation: case WidgetMobileActionType.mapLocation:
case WidgetMobileActionType.makePhoneCall: case WidgetMobileActionType.makePhoneCall:
const launched = actionResult.launched; const launched = actionResult.launched;
if (mobileAction.processLaunchResultFunction && mobileAction.processLaunchResultFunction.length) { if (isNotEmptyTbFunction(mobileAction.processLaunchResultFunction)) {
compileTbFunction(this.http, mobileAction.processLaunchResultFunction, 'launched', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const processLaunchResultFunction = new Function('launched', '$event', 'widgetContext', 'entityId', compiled.execute(launched, $event, this.widgetContext,
'entityName', 'additionalParams', 'entityLabel', mobileAction.processLaunchResultFunction);
processLaunchResultFunction(launched, $event, this.widgetContext,
entityId, entityName, additionalParams, entityLabel); entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
break; break;
} }
} else { } else {
if (mobileAction.handleEmptyResultFunction && mobileAction.handleEmptyResultFunction.length) { if (isNotEmptyTbFunction(mobileAction.handleEmptyResultFunction)) {
compileTbFunction(this.http, mobileAction.handleEmptyResultFunction, '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const handleEmptyResultFunction = new Function('$event', 'widgetContext', 'entityId', compiled.execute($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
'entityName', 'additionalParams', 'entityLabel', mobileAction.handleEmptyResultFunction);
handleEmptyResultFunction($event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
} }
} }
} }
); );
}, },
(err) => { error: err => {
let errorMessage; let errorMessage: string;
if (err && typeof err === 'string') { if (err && typeof err === 'string') {
errorMessage = err; errorMessage = err;
} else if (err && err.message) { } else if (err && err.message) {
@ -1342,19 +1391,28 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
} }
errorMessage = `Failed to get mobile action arguments${errorMessage ? `: ${errorMessage}` : '!'}`; errorMessage = `Failed to get mobile action arguments${errorMessage ? `: ${errorMessage}` : '!'}`;
this.handleWidgetMobileActionError(errorMessage, $event, mobileAction, entityId, entityName, additionalParams, entityLabel); this.handleWidgetMobileActionError(errorMessage, $event, mobileAction, entityId, entityName, additionalParams, entityLabel);
}
}); });
} }
private handleWidgetMobileActionError(error: string, $event: Event, mobileAction: WidgetMobileActionDescriptor, private handleWidgetMobileActionError(error: string, $event: Event, mobileAction: WidgetMobileActionDescriptor,
entityId?: EntityId, entityName?: string, additionalParams?: any, entityLabel?: string) { entityId?: EntityId, entityName?: string, additionalParams?: any, entityLabel?: string) {
if (mobileAction.handleErrorFunction && mobileAction.handleErrorFunction.length) { if (isNotEmptyTbFunction(mobileAction.handleErrorFunction)) {
compileTbFunction(this.http, mobileAction.handleErrorFunction, 'error', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try { try {
const handleErrorFunction = new Function('error', '$event', 'widgetContext', 'entityId', compiled.execute(error, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
'entityName', 'additionalParams', 'entityLabel', mobileAction.handleErrorFunction);
handleErrorFunction(error, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
},
error: (err) => {
console.error(err);
}
}
);
} }
} }

View File

@ -621,27 +621,27 @@ export interface WidgetMobileActionResult<T extends MobileActionResult> {
} }
export interface ProcessImageDescriptor { export interface ProcessImageDescriptor {
processImageFunction: string; processImageFunction: TbFunction;
} }
export interface ProcessLaunchResultDescriptor { export interface ProcessLaunchResultDescriptor {
processLaunchResultFunction?: string; processLaunchResultFunction?: TbFunction;
} }
export interface LaunchMapDescriptor extends ProcessLaunchResultDescriptor { export interface LaunchMapDescriptor extends ProcessLaunchResultDescriptor {
getLocationFunction: string; getLocationFunction: TbFunction;
} }
export interface ScanQrCodeDescriptor { export interface ScanQrCodeDescriptor {
processQrCodeFunction: string; processQrCodeFunction: TbFunction;
} }
export interface MakePhoneCallDescriptor extends ProcessLaunchResultDescriptor { export interface MakePhoneCallDescriptor extends ProcessLaunchResultDescriptor {
getPhoneNumberFunction: string; getPhoneNumberFunction: TbFunction;
} }
export interface GetLocationDescriptor { export interface GetLocationDescriptor {
processLocationFunction: string; processLocationFunction: TbFunction;
} }
export type WidgetMobileActionDescriptors = ProcessImageDescriptor & export type WidgetMobileActionDescriptors = ProcessImageDescriptor &
@ -652,8 +652,8 @@ export type WidgetMobileActionDescriptors = ProcessImageDescriptor &
export interface WidgetMobileActionDescriptor extends WidgetMobileActionDescriptors { export interface WidgetMobileActionDescriptor extends WidgetMobileActionDescriptors {
type: WidgetMobileActionType; type: WidgetMobileActionType;
handleErrorFunction?: string; handleErrorFunction?: TbFunction;
handleEmptyResultFunction?: string; handleEmptyResultFunction?: TbFunction;
} }
export interface CustomActionDescriptor { export interface CustomActionDescriptor {