Merge pull request #12467 from maxunbearable/task/5416-mobile-action-device-provisioning

Added device provision mobile action
This commit is contained in:
Igor Kulikov 2025-03-13 18:44:58 +02:00 committed by GitHub
commit a90cdd38e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 86 additions and 7 deletions

View File

@ -36,6 +36,17 @@
</mat-form-field>
</div>
<ng-container [formGroup]="mobileActionTypeFormGroup" [ngSwitch]="mobileActionFormGroup.get('type').value">
<ng-template [ngSwitchCase]="mobileActionType.deviceProvision">
<tb-js-func
formControlName="handleProvisionSuccessFunction"
functionName="handleProvisionSuccess"
withModules
[functionArgs]="['deviceName', '$event', 'widgetContext', 'entityId', 'entityName', 'additionalParams', 'entityLabel']"
[globalVariables]="functionScopeVariables"
[editorCompleter]="customActionEditorCompleter"
hideBrackets
></tb-js-func>
</ng-template>
<ng-template [ngSwitchCase]="mobileActionFormGroup.get('type').value === mobileActionType.mapDirection ||
mobileActionFormGroup.get('type').value === mobileActionType.mapLocation ?
mobileActionFormGroup.get('type').value : ''">

View File

@ -27,7 +27,7 @@ import {
WidgetActionType,
WidgetMobileActionDescriptor,
WidgetMobileActionType,
widgetMobileActionTypeTranslationMap
widgetMobileActionTypeTranslationMap,
} from '@shared/models/widget.models';
import { CustomActionEditorCompleter } from '@home/components/widget/lib/settings/common/action/custom-action.models';
import {
@ -38,7 +38,8 @@ import {
getDefaultProcessImageFunction,
getDefaultProcessLaunchResultFunction,
getDefaultProcessLocationFunction,
getDefaultProcessQrCodeFunction
getDefaultProcessQrCodeFunction,
getDefaultProvisionSuccessFunction
} from '@home/components/widget/lib/settings/common/action/mobile-action-editor.models';
import { WidgetService } from '@core/http/widget.service';
import { TbFunction } from '@shared/models/js-function.models';
@ -254,6 +255,18 @@ export class MobileActionEditorComponent implements ControlValueAccessor, OnInit
this.fb.control(processLocationFunction, [Validators.required])
);
break;
case WidgetMobileActionType.deviceProvision:
let handleProvisionSuccessFunction = action?.handleProvisionSuccessFunction;
if (changed) {
const defaultProvisionSuccessFunction = getDefaultProvisionSuccessFunction();
if (defaultProvisionSuccessFunction !== handleProvisionSuccessFunction) {
handleProvisionSuccessFunction = defaultProvisionSuccessFunction;
}
}
this.mobileActionTypeFormGroup.addControl(
'handleProvisionSuccessFunction',
this.fb.control(handleProvisionSuccessFunction, [Validators.required])
);
}
}
this.mobileActionTypeFormGroup.valueChanges.pipe(

View File

@ -138,6 +138,18 @@ const processLocationFunction: TbFunction =
' }, 100);\n' +
'}';
const provisionSuccessFunction: TbFunction =
'// Function body to handle device provision success. \n' +
'// - deviceName - name of device that was successfully provisioned.\n' +
'\n' +
'showDeviceProvisionSuccess(deviceName);\n' +
'\n' +
'function showDeviceProvisionSuccess(deviceName) {\n' +
' setTimeout(function() {\n' +
' widgetContext.showSuccessToast(`Device ` + deviceName + ` was successfully provisioned`).subscribe();\n' +
' }, 100);\n' +
'}\n';
const handleEmptyResultFunctionTemplate: TbFunction =
'// 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' +
@ -145,7 +157,7 @@ const handleEmptyResultFunctionTemplate: TbFunction =
'\n' +
'function showEmptyResultDialog(message) {\n' +
' setTimeout(function() {\n' +
' widgetContext.dialogs.alert(\'Empty result\', message).subscribe();\n' +
' widgetContext.showInfoToast(message).subscribe();\n' +
' }, 100);\n' +
'}\n';
@ -241,6 +253,8 @@ export const getDefaultProcessQrCodeFunction = () => processQrCodeFunction;
export const getDefaultProcessLocationFunction = () => processLocationFunction;
export const getDefaultProvisionSuccessFunction = () => provisionSuccessFunction;
export const getDefaultGetLocationFunction = () => getLocationFunctionTemplate;
export const getDefaultGetPhoneNumberFunction = () => getPhoneNumberFunctionTemplate;
@ -272,6 +286,9 @@ export const getDefaultHandleEmptyResultFunction = (type: WidgetMobileActionType
case WidgetMobileActionType.takeScreenshot:
message = 'Take screenshot action was cancelled!';
break;
case WidgetMobileActionType.deviceProvision:
message = 'Device provision was not invoked!';
break;
}
return handleEmptyResultFunctionTemplate.replace('--MESSAGE--', message);
};
@ -303,6 +320,9 @@ export const getDefaultHandleErrorFunction = (type: WidgetMobileActionType): TbF
case WidgetMobileActionType.takeScreenshot:
title = 'Failed to take screenshot';
break;
case WidgetMobileActionType.deviceProvision:
title = 'Failed to make device provision';
break;
}
return handleErrorFunctionTemplate.replace('--TITLE--', title);
};

View File

@ -1177,6 +1177,7 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
case WidgetMobileActionType.scanQrCode:
case WidgetMobileActionType.getLocation:
case WidgetMobileActionType.takeScreenshot:
case WidgetMobileActionType.deviceProvision:
argsObservable = of([]);
break;
case WidgetMobileActionType.mapDirection:
@ -1266,6 +1267,26 @@ export class WidgetComponent extends PageComponent implements OnInit, OnChanges,
);
}
break;
case WidgetMobileActionType.deviceProvision:
const deviceName = actionResult.deviceName;
if (isNotEmptyTbFunction(mobileAction.handleProvisionSuccessFunction)) {
compileTbFunction(this.http, mobileAction.handleProvisionSuccessFunction, 'deviceName', '$event', 'widgetContext', 'entityId',
'entityName', 'additionalParams', 'entityLabel').subscribe(
{
next: (compiled) => {
try {
compiled.execute(deviceName, $event, this.widgetContext, entityId, entityName, additionalParams, entityLabel);
} catch (e) {
console.error(e);
}
},
error: (err) => {
console.error(err);
}
}
);
}
break;
case WidgetMobileActionType.scanQrCode:
const code = actionResult.code;
const format = actionResult.format;

View File

@ -47,6 +47,7 @@ import { WidgetConfigCallbacks } from '@home/components/widget/config/widget-con
import { TbFunction } from '@shared/models/js-function.models';
import { FormProperty, jsonFormSchemaToFormProperties } from '@shared/models/dynamic-form.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Device } from '@shared/models/device.models';
export enum widgetType {
timeseries = 'timeseries',
@ -589,7 +590,8 @@ export enum WidgetMobileActionType {
scanQrCode = 'scanQrCode',
makePhoneCall = 'makePhoneCall',
getLocation = 'getLocation',
takeScreenshot = 'takeScreenshot'
takeScreenshot = 'takeScreenshot',
deviceProvision = 'deviceProvision',
}
export enum MapItemType {
@ -625,7 +627,8 @@ export const widgetMobileActionTypeTranslationMap = new Map<WidgetMobileActionTy
[ WidgetMobileActionType.scanQrCode, 'widget-action.mobile.scan-qr-code' ],
[ WidgetMobileActionType.makePhoneCall, 'widget-action.mobile.make-phone-call' ],
[ WidgetMobileActionType.getLocation, 'widget-action.mobile.get-location' ],
[ WidgetMobileActionType.takeScreenshot, 'widget-action.mobile.take-screenshot' ]
[ WidgetMobileActionType.takeScreenshot, 'widget-action.mobile.take-screenshot' ],
[ WidgetMobileActionType.deviceProvision, 'widget-action.mobile.device-provision' ]
]
);
@ -656,10 +659,15 @@ export interface MobileLocationResult {
longitude: number;
}
export interface MobileDeviceProvisionResult {
deviceName: string;
}
export type MobileActionResult = MobileLaunchResult &
MobileImageResult &
MobileQrCodeResult &
MobileLocationResult;
MobileLocationResult &
MobileDeviceProvisionResult;
export interface WidgetMobileActionResult<T extends MobileActionResult> {
result?: T;
@ -668,6 +676,10 @@ export interface WidgetMobileActionResult<T extends MobileActionResult> {
hasError: boolean;
}
export interface ProvisionSuccessDescriptor {
handleProvisionSuccessFunction: TbFunction;
}
export interface ProcessImageDescriptor {
processImageFunction: TbFunction;
}
@ -696,7 +708,8 @@ export type WidgetMobileActionDescriptors = ProcessImageDescriptor &
LaunchMapDescriptor &
ScanQrCodeDescriptor &
MakePhoneCallDescriptor &
GetLocationDescriptor;
GetLocationDescriptor &
ProvisionSuccessDescriptor;
export interface WidgetMobileActionDescriptor extends WidgetMobileActionDescriptors {
type: WidgetMobileActionType;

View File

@ -6569,6 +6569,7 @@
"URL": "URL",
"url-required": "URL is required.",
"mobile": {
"device-provision": "Device provision",
"action-type": "Mobile action type",
"select-action-type": "Select mobile action type",
"action-type-required": "Mobile action type is required",