Add support for run time params in action execution (#98)
Adds a third parameter to the Action.run function that can be referenced inside an action config
Usage
`{{ Api1.run(...,...,{key: value}) }}` inside property pane
`{{this.params.key}}` inside action pane
* You can reference data tree properties in the params values:
`{{ Api1.run(..., ..., { key: "Input1.text.toUpperCase()" })`
* Bindings can have both params and data tree values referenced.
* Param values can be javascript functions
`body: {{ this.params.list.map(i => Input1.text + i ) }}`
This commit is contained in:
parent
70c4dd5964
commit
b6c710cfa2
|
|
@ -28,13 +28,14 @@ export type RunActionPayload = {
|
||||||
actionId: string;
|
actionId: string;
|
||||||
onSuccess: string;
|
onSuccess: string;
|
||||||
onError: string;
|
onError: string;
|
||||||
|
params: Record<string, any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DataTreeAction extends Omit<ActionData, "data" | "config"> {
|
export interface DataTreeAction extends Omit<ActionData, "data" | "config"> {
|
||||||
data: ActionResponse["body"];
|
data: ActionResponse["body"];
|
||||||
actionId: string;
|
actionId: string;
|
||||||
config: Partial<ActionConfig>;
|
config: Partial<ActionConfig>;
|
||||||
run: ActionDispatcher<RunActionPayload, [string, string]> | {};
|
run: ActionDispatcher<RunActionPayload, [string, string, string]> | {};
|
||||||
dynamicBindingPathList: Property[];
|
dynamicBindingPathList: Property[];
|
||||||
ENTITY_TYPE: ENTITY_TYPE.ACTION;
|
ENTITY_TYPE: ENTITY_TYPE.ACTION;
|
||||||
}
|
}
|
||||||
|
|
@ -103,13 +104,19 @@ export class DataTreeFactory {
|
||||||
dynamicBindingPathList,
|
dynamicBindingPathList,
|
||||||
data: a.data ? a.data.body : {},
|
data: a.data ? a.data.body : {},
|
||||||
run: withFunctions
|
run: withFunctions
|
||||||
? function(this: DataTreeAction, onSuccess: string, onError: string) {
|
? function(
|
||||||
|
this: DataTreeAction,
|
||||||
|
onSuccess: string,
|
||||||
|
onError: string,
|
||||||
|
params = "",
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: "RUN_ACTION",
|
type: "RUN_ACTION",
|
||||||
payload: {
|
payload: {
|
||||||
actionId: this.actionId,
|
actionId: this.actionId,
|
||||||
onSuccess: onSuccess ? `{{${onSuccess.toString()}}}` : "",
|
onSuccess: onSuccess ? `{{${onSuccess.toString()}}}` : "",
|
||||||
onError: onError ? `{{${onError.toString()}}}` : "",
|
onError: onError ? `{{${onError.toString()}}}` : "",
|
||||||
|
params,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,20 +143,68 @@ export function* evaluateDynamicBoundValueSaga(path: string): any {
|
||||||
return dynamicResult.result;
|
return dynamicResult.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
const EXECUTION_PARAM_PATH = "this.params";
|
||||||
if (_.isNil(jsonPathKeys)) return [];
|
const getExecutionParamPath = (key: string) => `${EXECUTION_PARAM_PATH}.${key}`;
|
||||||
|
|
||||||
|
export function* getActionParams(
|
||||||
|
bindings: string[] | undefined,
|
||||||
|
executionParams?: Record<string, any>,
|
||||||
|
) {
|
||||||
|
if (_.isNil(bindings)) return [];
|
||||||
|
let dataTreeBindings = bindings;
|
||||||
|
|
||||||
|
if (executionParams && Object.keys(executionParams).length) {
|
||||||
|
// List of params in the path format
|
||||||
|
const executionParamsPathList = Object.keys(executionParams).map(
|
||||||
|
getExecutionParamPath,
|
||||||
|
);
|
||||||
|
const paramSearchRegex = new RegExp(executionParamsPathList.join("|"), "g");
|
||||||
|
// Bindings with references to execution params
|
||||||
|
const executionBindings = bindings.filter(binding =>
|
||||||
|
paramSearchRegex.test(binding),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Replace references with values
|
||||||
|
const replacedBindings = executionBindings.map(binding => {
|
||||||
|
let replaced = binding;
|
||||||
|
const matches = binding.match(paramSearchRegex);
|
||||||
|
if (matches && matches.length) {
|
||||||
|
matches.forEach(match => {
|
||||||
|
// we add one for substring index to account for '.'
|
||||||
|
const paramKey = match.substring(EXECUTION_PARAM_PATH.length + 1);
|
||||||
|
let paramValue = executionParams[paramKey];
|
||||||
|
if (paramValue) {
|
||||||
|
if (typeof paramValue === "object") {
|
||||||
|
paramValue = JSON.stringify(paramValue);
|
||||||
|
}
|
||||||
|
replaced = replaced.replace(match, paramValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return replaced;
|
||||||
|
});
|
||||||
|
// Replace binding with replaced bindings for evaluation
|
||||||
|
dataTreeBindings = dataTreeBindings.map(key => {
|
||||||
|
if (executionBindings.includes(key)) {
|
||||||
|
return replacedBindings[executionBindings.indexOf(key)];
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Evaluate all values
|
||||||
const values: any = yield all(
|
const values: any = yield all(
|
||||||
jsonPathKeys.map((jsonPath: string) => {
|
dataTreeBindings.map((binding: string) => {
|
||||||
return call(evaluateDynamicBoundValueSaga, jsonPath);
|
return call(evaluateDynamicBoundValueSaga, binding);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const dynamicBindings: Record<string, string> = {};
|
// convert to object and transform non string values
|
||||||
jsonPathKeys.forEach((key, i) => {
|
const actionParams: Record<string, string> = {};
|
||||||
|
bindings.forEach((key, i) => {
|
||||||
let value = values[i];
|
let value = values[i];
|
||||||
if (typeof value === "object") value = JSON.stringify(value);
|
if (typeof value === "object") value = JSON.stringify(value);
|
||||||
dynamicBindings[key] = value;
|
actionParams[key] = value;
|
||||||
});
|
});
|
||||||
return mapToPropList(dynamicBindings);
|
return mapToPropList(actionParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractBindingsFromAction(action: Action) {
|
export function extractBindingsFromAction(action: Action) {
|
||||||
|
|
@ -175,11 +223,15 @@ export function* executeActionSaga(
|
||||||
apiAction: RunActionPayload,
|
apiAction: RunActionPayload,
|
||||||
event: ExecuteActionPayloadEvent,
|
event: ExecuteActionPayloadEvent,
|
||||||
) {
|
) {
|
||||||
const { actionId, onSuccess, onError } = apiAction;
|
const { actionId, onSuccess, onError, params } = apiAction;
|
||||||
try {
|
try {
|
||||||
yield put(executeApiActionRequest({ id: apiAction.actionId }));
|
yield put(executeApiActionRequest({ id: apiAction.actionId }));
|
||||||
const api: RestAction = yield select(getAction, actionId);
|
const api: RestAction = yield select(getAction, actionId);
|
||||||
const params: Property[] = yield call(getActionParams, api.jsonPathKeys);
|
const actionParams: Property[] = yield call(
|
||||||
|
getActionParams,
|
||||||
|
api.jsonPathKeys,
|
||||||
|
params,
|
||||||
|
);
|
||||||
const pagination =
|
const pagination =
|
||||||
event.type === EventType.ON_NEXT_PAGE
|
event.type === EventType.ON_NEXT_PAGE
|
||||||
? "NEXT"
|
? "NEXT"
|
||||||
|
|
@ -188,7 +240,7 @@ export function* executeActionSaga(
|
||||||
: undefined;
|
: undefined;
|
||||||
const executeActionRequest: ExecuteActionRequest = {
|
const executeActionRequest: ExecuteActionRequest = {
|
||||||
action: { id: actionId },
|
action: { id: actionId },
|
||||||
params,
|
params: actionParams,
|
||||||
paginationField: pagination,
|
paginationField: pagination,
|
||||||
};
|
};
|
||||||
const timeout = yield select(getActionTimeout, actionId);
|
const timeout = yield select(getActionTimeout, actionId);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user