2021-01-04 10:16:08 +00:00
|
|
|
import {
|
|
|
|
|
actionChannel,
|
|
|
|
|
call,
|
|
|
|
|
fork,
|
|
|
|
|
put,
|
|
|
|
|
select,
|
|
|
|
|
take,
|
|
|
|
|
} from "redux-saga/effects";
|
2020-12-28 08:42:43 +00:00
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
import {
|
2020-11-03 10:16:11 +00:00
|
|
|
EvaluationReduxAction,
|
2020-10-21 04:25:32 +00:00
|
|
|
ReduxAction,
|
|
|
|
|
ReduxActionTypes,
|
2021-04-26 05:41:32 +00:00
|
|
|
ReduxActionWithoutPayload,
|
2020-10-21 04:25:32 +00:00
|
|
|
} from "constants/ReduxActionConstants";
|
2021-07-20 05:04:12 +00:00
|
|
|
import {
|
|
|
|
|
getDataTree,
|
|
|
|
|
getUnevaluatedDataTree,
|
|
|
|
|
} from "selectors/dataTreeSelectors";
|
2021-09-21 07:55:56 +00:00
|
|
|
import { getWidgets } from "sagas/selectors";
|
2020-10-21 04:25:32 +00:00
|
|
|
import WidgetFactory, { WidgetTypeConfigMap } from "../utils/WidgetFactory";
|
2021-02-22 05:00:16 +00:00
|
|
|
import { GracefulWorkerService } from "utils/WorkerUtil";
|
2020-10-21 04:25:32 +00:00
|
|
|
import Worker from "worker-loader!../workers/evaluation.worker";
|
2021-08-29 03:50:16 +00:00
|
|
|
import {
|
|
|
|
|
EVAL_WORKER_ACTIONS,
|
|
|
|
|
PropertyEvaluationErrorType,
|
|
|
|
|
} from "utils/DynamicBindingUtils";
|
2020-10-21 04:25:32 +00:00
|
|
|
import log from "loglevel";
|
2021-02-22 05:00:16 +00:00
|
|
|
import { WidgetProps } from "widgets/BaseWidget";
|
2020-11-03 10:16:11 +00:00
|
|
|
import PerformanceTracker, {
|
|
|
|
|
PerformanceTransactionName,
|
|
|
|
|
} from "../utils/PerformanceTracker";
|
2020-11-11 11:32:14 +00:00
|
|
|
import * as Sentry from "@sentry/react";
|
2020-12-30 13:26:44 +00:00
|
|
|
import { Action } from "redux";
|
2021-06-04 07:09:36 +00:00
|
|
|
import {
|
2021-07-20 10:02:56 +00:00
|
|
|
EVALUATE_REDUX_ACTIONS,
|
|
|
|
|
FIRST_EVAL_REDUX_ACTIONS,
|
|
|
|
|
setDependencyMap,
|
|
|
|
|
setEvaluatedTree,
|
|
|
|
|
shouldProcessBatchedAction,
|
|
|
|
|
} from "actions/evaluationActions";
|
2021-03-13 14:24:45 +00:00
|
|
|
import {
|
2021-07-20 10:02:56 +00:00
|
|
|
evalErrorHandler,
|
|
|
|
|
logSuccessfulBindings,
|
|
|
|
|
postEvalActionDispatcher,
|
|
|
|
|
updateTernDefinitions,
|
|
|
|
|
} from "./PostEvaluationSagas";
|
2021-09-08 17:32:22 +00:00
|
|
|
import { JSCollection, JSAction } from "entities/JSCollection";
|
2021-07-30 10:24:22 +00:00
|
|
|
import { getAppMode } from "selectors/applicationSelectors";
|
2021-08-06 09:17:56 +00:00
|
|
|
import { APP_MODE } from "entities/App";
|
2021-09-21 07:55:56 +00:00
|
|
|
import {
|
|
|
|
|
UndoRedoPayload,
|
|
|
|
|
openPropertyPaneSaga,
|
|
|
|
|
postUndoRedoSaga,
|
|
|
|
|
} from "./ReplaySaga";
|
|
|
|
|
|
|
|
|
|
import { updateAndSaveLayout } from "actions/pageActions";
|
|
|
|
|
import { get } from "lodash";
|
2021-08-29 03:50:16 +00:00
|
|
|
import {
|
|
|
|
|
setEvaluatedArgument,
|
|
|
|
|
setEvaluatedSnippet,
|
|
|
|
|
setGlobalSearchFilterContext,
|
|
|
|
|
} from "actions/globalSearchActions";
|
|
|
|
|
import { executeActionTriggers } from "./ActionExecution/ActionExecutionSagas";
|
|
|
|
|
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
|
|
|
|
import { Toaster } from "components/ads/Toast";
|
|
|
|
|
import { Variant } from "components/ads/common";
|
|
|
|
|
import {
|
|
|
|
|
createMessage,
|
|
|
|
|
SNIPPET_EXECUTION_FAILED,
|
|
|
|
|
SNIPPET_EXECUTION_SUCCESS,
|
|
|
|
|
} from "constants/messages";
|
|
|
|
|
import { validate } from "workers/validations";
|
2021-08-24 12:10:25 +00:00
|
|
|
import { diff } from "deep-diff";
|
2020-10-21 04:25:32 +00:00
|
|
|
|
2021-09-21 07:55:56 +00:00
|
|
|
import AnalyticsUtil from "../utils/AnalyticsUtil";
|
|
|
|
|
import { commentModeSelector } from "selectors/commentsSelectors";
|
|
|
|
|
import { snipingModeSelector } from "selectors/editorSelectors";
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
let widgetTypeConfigMap: WidgetTypeConfigMap;
|
|
|
|
|
|
2020-12-28 08:42:43 +00:00
|
|
|
const worker = new GracefulWorkerService(Worker);
|
2020-10-21 04:25:32 +00:00
|
|
|
|
2021-04-26 05:41:32 +00:00
|
|
|
function* evaluateTreeSaga(
|
|
|
|
|
postEvalActions?: Array<ReduxAction<unknown> | ReduxActionWithoutPayload>,
|
2021-09-21 07:55:56 +00:00
|
|
|
shouldReplay?: boolean,
|
2021-04-26 05:41:32 +00:00
|
|
|
) {
|
2021-03-31 07:40:59 +00:00
|
|
|
const unevalTree = yield select(getUnevaluatedDataTree);
|
2021-09-21 07:55:56 +00:00
|
|
|
const widgets = yield select(getWidgets);
|
2021-03-31 07:40:59 +00:00
|
|
|
log.debug({ unevalTree });
|
2020-11-03 10:16:11 +00:00
|
|
|
PerformanceTracker.startAsyncTracking(
|
|
|
|
|
PerformanceTransactionName.DATA_TREE_EVALUATION,
|
|
|
|
|
);
|
2020-12-28 08:42:43 +00:00
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.EVAL_TREE,
|
|
|
|
|
{
|
2021-01-04 10:16:08 +00:00
|
|
|
unevalTree,
|
2020-12-28 08:42:43 +00:00
|
|
|
widgetTypeConfigMap,
|
2021-09-21 07:55:56 +00:00
|
|
|
widgets,
|
|
|
|
|
shouldReplay,
|
2020-12-28 08:42:43 +00:00
|
|
|
},
|
|
|
|
|
);
|
2021-06-04 07:09:36 +00:00
|
|
|
const {
|
|
|
|
|
dataTree,
|
|
|
|
|
dependencies,
|
|
|
|
|
errors,
|
|
|
|
|
evaluationOrder,
|
|
|
|
|
logs,
|
2021-08-04 05:34:44 +00:00
|
|
|
unEvalUpdates,
|
2021-06-04 07:09:36 +00:00
|
|
|
} = workerResponse;
|
2021-03-31 07:40:59 +00:00
|
|
|
PerformanceTracker.stopAsyncTracking(
|
|
|
|
|
PerformanceTransactionName.DATA_TREE_EVALUATION,
|
|
|
|
|
);
|
|
|
|
|
PerformanceTracker.startAsyncTracking(
|
|
|
|
|
PerformanceTransactionName.SET_EVALUATED_TREE,
|
|
|
|
|
);
|
2021-08-24 12:10:25 +00:00
|
|
|
const oldDataTree = yield select(getDataTree);
|
|
|
|
|
|
|
|
|
|
const updates = diff(oldDataTree, dataTree) || [];
|
|
|
|
|
|
2021-07-20 10:02:56 +00:00
|
|
|
yield put(setEvaluatedTree(dataTree, updates));
|
2021-04-23 11:34:33 +00:00
|
|
|
PerformanceTracker.stopAsyncTracking(
|
2021-03-31 07:40:59 +00:00
|
|
|
PerformanceTransactionName.SET_EVALUATED_TREE,
|
|
|
|
|
);
|
2021-07-20 05:04:12 +00:00
|
|
|
|
|
|
|
|
const updatedDataTree = yield select(getDataTree);
|
|
|
|
|
|
|
|
|
|
log.debug({ dataTree: updatedDataTree });
|
|
|
|
|
logs.forEach((evalLog: any) => log.debug(evalLog));
|
|
|
|
|
yield call(evalErrorHandler, errors, updatedDataTree, evaluationOrder);
|
2021-07-30 10:24:22 +00:00
|
|
|
const appMode = yield select(getAppMode);
|
|
|
|
|
if (appMode !== APP_MODE.PUBLISHED) {
|
|
|
|
|
yield fork(
|
|
|
|
|
logSuccessfulBindings,
|
|
|
|
|
unevalTree,
|
|
|
|
|
updatedDataTree,
|
|
|
|
|
evaluationOrder,
|
|
|
|
|
);
|
|
|
|
|
|
2021-08-04 05:34:44 +00:00
|
|
|
yield fork(updateTernDefinitions, updatedDataTree, unEvalUpdates);
|
2021-07-30 10:24:22 +00:00
|
|
|
}
|
2021-07-20 05:04:12 +00:00
|
|
|
|
2021-07-20 10:02:56 +00:00
|
|
|
yield put(setDependencyMap(dependencies));
|
2020-11-03 10:16:11 +00:00
|
|
|
if (postEvalActions && postEvalActions.length) {
|
|
|
|
|
yield call(postEvalActionDispatcher, postEvalActions);
|
|
|
|
|
}
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-01-14 14:37:21 +00:00
|
|
|
export function* evaluateActionBindings(
|
|
|
|
|
bindings: string[],
|
|
|
|
|
executionParams: Record<string, any> | string = {},
|
2020-12-14 18:48:13 +00:00
|
|
|
) {
|
2020-12-28 08:42:43 +00:00
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
2021-01-14 14:37:21 +00:00
|
|
|
EVAL_WORKER_ACTIONS.EVAL_ACTION_BINDINGS,
|
2020-12-28 08:42:43 +00:00
|
|
|
{
|
2021-01-14 14:37:21 +00:00
|
|
|
bindings,
|
|
|
|
|
executionParams,
|
2020-12-28 08:42:43 +00:00
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
2021-01-14 14:37:21 +00:00
|
|
|
const { errors, values } = workerResponse;
|
2020-12-28 08:42:43 +00:00
|
|
|
|
2021-06-04 07:09:36 +00:00
|
|
|
yield call(evalErrorHandler, errors);
|
2021-01-14 14:37:21 +00:00
|
|
|
return values;
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* evaluateDynamicTrigger(
|
|
|
|
|
dynamicTrigger: string,
|
2020-11-20 09:30:50 +00:00
|
|
|
callbackData?: Array<any>,
|
2020-10-21 04:25:32 +00:00
|
|
|
) {
|
2020-12-28 08:42:43 +00:00
|
|
|
const unEvalTree = yield select(getUnevaluatedDataTree);
|
|
|
|
|
|
|
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.EVAL_TRIGGER,
|
|
|
|
|
{ dataTree: unEvalTree, dynamicTrigger, callbackData },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const { errors, triggers } = workerResponse;
|
2021-09-15 05:11:13 +00:00
|
|
|
|
2021-06-04 07:09:36 +00:00
|
|
|
yield call(evalErrorHandler, errors);
|
2021-09-15 05:11:13 +00:00
|
|
|
|
2020-12-28 08:42:43 +00:00
|
|
|
return triggers;
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* clearEvalCache() {
|
2020-12-28 08:42:43 +00:00
|
|
|
yield call(worker.request, EVAL_WORKER_ACTIONS.CLEAR_CACHE);
|
|
|
|
|
|
|
|
|
|
return true;
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-21 07:55:56 +00:00
|
|
|
/**
|
|
|
|
|
* saga that listen for UNDO_REDO_OPERATION
|
|
|
|
|
* it won't do anything in case of sniping/comment mode
|
|
|
|
|
*
|
|
|
|
|
* @param action
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
export function* undoRedoSaga(action: ReduxAction<UndoRedoPayload>) {
|
|
|
|
|
const isCommentMode: boolean = yield select(commentModeSelector);
|
|
|
|
|
const isSnipingMode: boolean = yield select(snipingModeSelector);
|
|
|
|
|
|
|
|
|
|
// if the app is in snipping or comments mode, don't do anything
|
|
|
|
|
if (isCommentMode || isSnipingMode) return;
|
|
|
|
|
try {
|
|
|
|
|
const workerResponse: any = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
action.payload.operation,
|
|
|
|
|
{},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// if there is no change, then don't do anything
|
|
|
|
|
if (!workerResponse) return;
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
event,
|
|
|
|
|
logs,
|
|
|
|
|
paths,
|
|
|
|
|
replay,
|
|
|
|
|
replayWidgetDSL,
|
|
|
|
|
timeTaken,
|
|
|
|
|
} = workerResponse;
|
|
|
|
|
|
|
|
|
|
logs && logs.forEach((evalLog: any) => log.debug(evalLog));
|
|
|
|
|
|
|
|
|
|
const isPropertyUpdate = replay.widgets && replay.propertyUpdates;
|
|
|
|
|
|
|
|
|
|
AnalyticsUtil.logEvent(event, { paths, timeTaken });
|
|
|
|
|
|
|
|
|
|
if (isPropertyUpdate) yield call(openPropertyPaneSaga, replay);
|
|
|
|
|
|
|
|
|
|
yield put(updateAndSaveLayout(replayWidgetDSL, false, false));
|
|
|
|
|
|
|
|
|
|
if (!isPropertyUpdate) yield call(postUndoRedoSaga, replay);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log.error(e);
|
|
|
|
|
Sentry.captureException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export function* clearEvalPropertyCache(propertyPath: string) {
|
2020-12-28 08:42:43 +00:00
|
|
|
yield call(worker.request, EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE, {
|
|
|
|
|
propertyPath,
|
|
|
|
|
});
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-08 17:32:22 +00:00
|
|
|
export function* parseJSCollection(body: string, jsAction: JSCollection) {
|
2021-09-21 06:02:45 +00:00
|
|
|
const path = jsAction.name + ".body";
|
|
|
|
|
const workerResponse = yield call(
|
2021-09-08 17:32:22 +00:00
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.PARSE_JS_FUNCTION_BODY,
|
|
|
|
|
{
|
|
|
|
|
body,
|
|
|
|
|
jsAction,
|
|
|
|
|
},
|
|
|
|
|
);
|
2021-09-21 06:02:45 +00:00
|
|
|
const { errors, evalTree, result } = workerResponse;
|
|
|
|
|
const dataTree = yield select(getDataTree);
|
|
|
|
|
const updates = diff(dataTree, evalTree) || [];
|
|
|
|
|
yield put(setEvaluatedTree(evalTree, updates));
|
|
|
|
|
yield call(evalErrorHandler, errors, evalTree, [path]);
|
|
|
|
|
return result;
|
2021-09-08 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* executeFunction(collectionName: string, action: JSAction) {
|
|
|
|
|
const unEvalTree = yield select(getUnevaluatedDataTree);
|
|
|
|
|
const dynamicTrigger = collectionName + "." + action.name + "()";
|
|
|
|
|
|
|
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.EVAL_TRIGGER,
|
|
|
|
|
{ dataTree: unEvalTree, dynamicTrigger, fullPropertyPath: dynamicTrigger },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const { errors, result, triggers } = workerResponse;
|
|
|
|
|
yield call(evalErrorHandler, errors);
|
|
|
|
|
return { triggers, result };
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 05:26:35 +00:00
|
|
|
/**
|
|
|
|
|
* clears all cache keys of a widget
|
|
|
|
|
*
|
|
|
|
|
* @param widgetName
|
|
|
|
|
*/
|
|
|
|
|
export function* clearEvalPropertyCacheOfWidget(widgetName: string) {
|
2020-12-28 08:42:43 +00:00
|
|
|
yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.CLEAR_PROPERTY_CACHE_OF_WIDGET,
|
|
|
|
|
{
|
2020-12-01 05:26:35 +00:00
|
|
|
widgetName,
|
2020-12-28 08:42:43 +00:00
|
|
|
},
|
|
|
|
|
);
|
2020-12-01 05:26:35 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export function* validateProperty(
|
|
|
|
|
property: string,
|
|
|
|
|
value: any,
|
|
|
|
|
props: WidgetProps,
|
|
|
|
|
) {
|
2021-04-21 14:34:25 +00:00
|
|
|
const unevalTree = yield select(getUnevaluatedDataTree);
|
|
|
|
|
const validation = unevalTree[props.widgetName].validationPaths[property];
|
2020-12-28 08:42:43 +00:00
|
|
|
return yield call(worker.request, EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY, {
|
|
|
|
|
property,
|
|
|
|
|
value,
|
|
|
|
|
props,
|
2021-04-21 14:34:25 +00:00
|
|
|
validation,
|
2020-12-28 08:42:43 +00:00
|
|
|
});
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-30 13:26:44 +00:00
|
|
|
function evalQueueBuffer() {
|
2021-01-04 10:16:08 +00:00
|
|
|
let canTake = false;
|
2020-12-30 13:26:44 +00:00
|
|
|
let postEvalActions: any = [];
|
|
|
|
|
const take = () => {
|
2021-01-04 10:16:08 +00:00
|
|
|
if (canTake) {
|
2020-12-30 13:26:44 +00:00
|
|
|
const resp = postEvalActions;
|
|
|
|
|
postEvalActions = [];
|
2021-01-04 10:16:08 +00:00
|
|
|
canTake = false;
|
|
|
|
|
return { postEvalActions: resp, type: "BUFFERED_ACTION" };
|
2020-12-30 13:26:44 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const flush = () => {
|
2021-01-04 10:16:08 +00:00
|
|
|
if (canTake) {
|
2020-12-30 13:26:44 +00:00
|
|
|
return [take() as Action];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const put = (action: EvaluationReduxAction<unknown | unknown[]>) => {
|
2021-07-20 10:02:56 +00:00
|
|
|
if (!shouldProcessBatchedAction(action)) {
|
2021-01-14 11:15:25 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2021-01-04 10:16:08 +00:00
|
|
|
canTake = true;
|
2021-01-14 11:15:25 +00:00
|
|
|
|
2020-12-30 13:26:44 +00:00
|
|
|
// TODO: If the action is the same as before, we can send only one and ignore duplicates.
|
|
|
|
|
if (action.postEvalActions) {
|
|
|
|
|
postEvalActions.push(...action.postEvalActions);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
take,
|
|
|
|
|
put,
|
|
|
|
|
isEmpty: () => {
|
2021-01-04 10:16:08 +00:00
|
|
|
return !canTake;
|
2020-12-30 13:26:44 +00:00
|
|
|
},
|
|
|
|
|
flush,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* evaluationChangeListenerSaga() {
|
|
|
|
|
// Explicitly shutdown old worker if present
|
|
|
|
|
yield call(worker.shutdown);
|
|
|
|
|
yield call(worker.start);
|
|
|
|
|
widgetTypeConfigMap = WidgetFactory.getWidgetTypeConfigMap();
|
2021-01-04 10:16:08 +00:00
|
|
|
const initAction = yield take(FIRST_EVAL_REDUX_ACTIONS);
|
2021-08-04 05:34:44 +00:00
|
|
|
yield fork(evaluateTreeSaga, initAction.postEvalActions);
|
2020-12-30 13:26:44 +00:00
|
|
|
const evtActionChannel = yield actionChannel(
|
|
|
|
|
EVALUATE_REDUX_ACTIONS,
|
|
|
|
|
evalQueueBuffer(),
|
|
|
|
|
);
|
|
|
|
|
while (true) {
|
|
|
|
|
const action: EvaluationReduxAction<unknown | unknown[]> = yield take(
|
|
|
|
|
evtActionChannel,
|
|
|
|
|
);
|
2021-08-04 05:34:44 +00:00
|
|
|
if (shouldProcessBatchedAction(action)) {
|
2021-09-21 07:55:56 +00:00
|
|
|
yield call(
|
|
|
|
|
evaluateTreeSaga,
|
|
|
|
|
action.postEvalActions,
|
|
|
|
|
get(action, "payload.shouldReplay"),
|
|
|
|
|
);
|
2021-01-14 11:15:25 +00:00
|
|
|
}
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-29 03:50:16 +00:00
|
|
|
export function* evaluateSnippetSaga(action: any) {
|
|
|
|
|
try {
|
|
|
|
|
let { expression } = action.payload;
|
|
|
|
|
const { dataType, isTrigger } = action.payload;
|
|
|
|
|
if (isTrigger) {
|
|
|
|
|
expression = `function() { ${expression} }`;
|
|
|
|
|
}
|
|
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.EVAL_EXPRESSION,
|
|
|
|
|
{
|
|
|
|
|
expression,
|
|
|
|
|
dataType,
|
|
|
|
|
isTrigger,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
const { errors, result, triggers } = workerResponse;
|
|
|
|
|
if (triggers && triggers.length > 0) {
|
|
|
|
|
yield call(
|
|
|
|
|
executeActionTriggers,
|
|
|
|
|
triggers[0],
|
|
|
|
|
EventType.ON_SNIPPET_EXECUTE,
|
2021-09-23 07:21:57 +00:00
|
|
|
{},
|
2021-08-29 03:50:16 +00:00
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
yield put(
|
|
|
|
|
setEvaluatedSnippet(
|
|
|
|
|
result
|
|
|
|
|
? JSON.stringify(result, null, 2)
|
|
|
|
|
: errors && errors.length
|
|
|
|
|
? JSON.stringify(errors, null, 2)
|
|
|
|
|
: "",
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
Toaster.show({
|
|
|
|
|
text: createMessage(
|
|
|
|
|
result || triggers
|
|
|
|
|
? SNIPPET_EXECUTION_SUCCESS
|
|
|
|
|
: SNIPPET_EXECUTION_FAILED,
|
|
|
|
|
),
|
|
|
|
|
variant: result || triggers ? Variant.success : Variant.danger,
|
|
|
|
|
});
|
|
|
|
|
yield put(
|
|
|
|
|
setGlobalSearchFilterContext({
|
|
|
|
|
executionInProgress: false,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
yield put(
|
|
|
|
|
setGlobalSearchFilterContext({
|
|
|
|
|
executionInProgress: false,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
log.error(e);
|
|
|
|
|
Sentry.captureException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* evaluateArgumentSaga(action: any) {
|
|
|
|
|
const { name, type, value } = action.payload;
|
|
|
|
|
try {
|
|
|
|
|
const workerResponse = yield call(
|
|
|
|
|
worker.request,
|
|
|
|
|
EVAL_WORKER_ACTIONS.EVAL_EXPRESSION,
|
|
|
|
|
{
|
|
|
|
|
expression: value,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
const lintErrors = (workerResponse.errors || []).filter(
|
|
|
|
|
(error: any) => error.errorType !== PropertyEvaluationErrorType.LINT,
|
|
|
|
|
);
|
|
|
|
|
if (workerResponse.result) {
|
|
|
|
|
const validation = validate({ type }, workerResponse.result, {});
|
|
|
|
|
if (!validation.isValid)
|
|
|
|
|
lintErrors.unshift({
|
|
|
|
|
...validation,
|
|
|
|
|
...{
|
|
|
|
|
errorType: PropertyEvaluationErrorType.VALIDATION,
|
|
|
|
|
errorMessage: validation.message,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
yield put(
|
|
|
|
|
setEvaluatedArgument({
|
|
|
|
|
[name]: {
|
|
|
|
|
type,
|
|
|
|
|
value: workerResponse.result,
|
|
|
|
|
name,
|
|
|
|
|
errors: lintErrors,
|
|
|
|
|
isInvalid: lintErrors.length > 0,
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log.error(e);
|
|
|
|
|
Sentry.captureException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 04:25:32 +00:00
|
|
|
export default function* evaluationSagaListeners() {
|
2020-12-30 13:26:44 +00:00
|
|
|
yield take(ReduxActionTypes.START_EVALUATION);
|
|
|
|
|
while (true) {
|
|
|
|
|
try {
|
|
|
|
|
yield call(evaluationChangeListenerSaga);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log.error(e);
|
|
|
|
|
Sentry.captureException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-21 04:25:32 +00:00
|
|
|
}
|