Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExecuteScriptAsync added on Action configuration #1035

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions shesha-reactjs/src/interfaces/configurableAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export interface FormMarkupFactoryArgs {
exposedVariables?: ICodeExposedVariable[];
}
export type FormMarkupFactory = (factoryArgs: FormMarkupFactoryArgs) => FormMarkup;
export type FormMarkupFactoryWithExpressionName<T = string> = (
factoryArgs: FormMarkupFactoryArgs,
expressionName?: T
) => FormMarkup;

export type IConfigurableActionArgumentsFormFactory<TModel = IConfigurableActionArguments> = (
props: ISettingsFormFactoryArgs<TModel>
Expand Down
34 changes: 27 additions & 7 deletions shesha-reactjs/src/providers/form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export const getReadOnlyBool = (editMode: EditMode, parentReadOnly: boolean) =>
* @param allData - all form, contexts data and other data/objects/functions needed to calculate Actual Model
* @returns - converted model
*/
export const getActualModel = <T>(model: T, allData: any, parentReadOnly: boolean = undefined): T => {
export const getActualModel = <T>(model: T, allData: any, parentReadOnly: boolean = undefined): T => {
const m = {} as T;
for (var propName in model) {
if (!model.hasOwnProperty(propName)) continue;
Expand All @@ -239,7 +239,7 @@ const updateConfigurableActionParent = (model: any, parentId: string) => {
for (const key in model) {
if (model.hasOwnProperty(key) && typeof model[key] === 'object') {
const config = model[key] as IConfigurableActionConfiguration;

if (config?._type === StandardNodeTypes.ConfigurableActionConfig) {
// skip SheshaActionOwners actions since they are common
if (Object.values(SheshaActionOwners).filter(i => i === config.actionOwner)?.length > 0)
Expand Down Expand Up @@ -268,12 +268,12 @@ export const getActualModelWithParent = <T>(
? `${parent?.model?.componentName}.${actualModel['componentName']}`
: actualModel['componentName'];

actualModel['context'] =
actualModel['context'] =
!!actualModel['context']
&& parent?.context !== actualModel['context'] // If the subForm has the same context then don't update context name
&& !isCommonContext(actualModel['context']) // If a common context then don't update context name
? `${parent?.subFormIdPrefix}.${actualModel['context']}`
: actualModel['context'];
&& parent?.context !== actualModel['context'] // If the subForm has the same context then don't update context name
&& !isCommonContext(actualModel['context']) // If a common context then don't update context name
? `${parent?.subFormIdPrefix}.${actualModel['context']}`
: actualModel['context'];
updateConfigurableActionParent(actualModel, parent?.subFormIdPrefix);
}
return actualModel;
Expand Down Expand Up @@ -727,6 +727,26 @@ export function executeScript<TResult = any>(
});
}

export function executeScriptAsync<TResult = any>(
expression: string,
expressionArgs: IExpressionExecuterArguments
): Promise<TResult> {
if (!expression) Promise.reject('Expression must be defined');

let argsDefinition = '';
const argList: any[] = [];
for (const argumentName in expressionArgs) {
if (expressionArgs.hasOwnProperty(argumentName)) {
argsDefinition += (argsDefinition ? ', ' : '') + argumentName;
argList.push(expressionArgs[argumentName]);
}
}

const expressionExecuter = new Function(argsDefinition, expression);

return expressionExecuter.apply(null, argList);
}

export function executeScriptSync<TResult = any>(expression: string, context: IExpressionExecuterArguments): TResult {
if (!expression) throw new Error('Expression must be defined');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { ICodeExposedVariable } from '@/components/codeVariablesTable';
import { FormMarkupFactory } from '@/interfaces/configurableAction';
import { FormMarkupFactoryWithExpressionName } from '@/interfaces/configurableAction';
import { nanoid } from '@/utils/uuid';
import { useSheshaApplication } from '@/providers';
import { DesignerToolbarSettings } from '@/interfaces/toolbarSettings';
import { useConfigurableAction } from '@/providers/configurableActionsDispatcher';
import { SheshaActionOwners } from '../../configurableActionsDispatcher/models';
import { executeScript } from '../../form/utils';
import { executeScript, executeScriptAsync } from '../../form/utils';

export interface IExecuteScriptArguments {
expression: string;
expressionAsync: string;
}

const executeScriptArgumentsForm: FormMarkupFactory = (props) => {
const executeScriptArgumentsForm: FormMarkupFactoryWithExpressionName<keyof IExecuteScriptArguments> = (
props,
propertyName = 'expression'
) => {
const standardVariables: ICodeExposedVariable[] = [
{
id: '3b19a708-e81a-4625-bcbb-3fe8451d0491',
Expand Down Expand Up @@ -85,7 +89,7 @@ const executeScriptArgumentsForm: FormMarkupFactory = (props) => {
return new DesignerToolbarSettings()
.addCodeEditor({
id: nanoid(),
propertyName: 'expression',
propertyName,
label: 'Expression',
mode: 'dialog',
exposedVariables: variables,
Expand All @@ -111,4 +115,21 @@ export const useExecuteScriptAction = () => {
},
[backendUrl, httpHeaders]
);

useConfigurableAction<IExecuteScriptArguments>(
{
owner: 'Common',
ownerUid: SheshaActionOwners.Common,
name: 'Execute Script Async',
hasArguments: true,
argumentsFormMarkup: (formArgs) => executeScriptArgumentsForm(formArgs, 'expressionAsync'),
executer: (actionArgs, context) => {
if (!actionArgs.expressionAsync)
return Promise.reject('Expected expression to be defined but it was found to be empty.');

return executeScriptAsync(actionArgs.expressionAsync, context);
},
},
[backendUrl, httpHeaders]
);
};