Merge pull request #14342 from appsmithorg/hotfix/JSActionandEvalFixes

fix: for onPageLoad false errors and crash due to evalMetaUpdate
This commit is contained in:
Shrikant Sharat Kandula 2022-06-07 17:34:20 +05:30 committed by GitHub
commit 436ff0609f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 824 additions and 107 deletions

View File

@ -0,0 +1,651 @@
{
"clientSchemaVersion": 1,
"serverSchemaVersion": 4,
"exportedApplication": {
"name": "Execute Action Test",
"isPublic": false,
"appIsExample": false,
"unreadCommentThreads": 0,
"color": "#D9E7FF",
"icon": "camera",
"slug": "execute-action-test",
"evaluationVersion": 2,
"applicationVersion": 2,
"isManualUpdate": false,
"new": true
},
"datasourceList": [],
"pageList": [
{
"userPermissions": [
"read:pages",
"manage:pages"
],
"gitSyncId": "62987c9ec43c3d0bd6572220_62987c9ec43c3d0bd6572222",
"unpublishedPage": {
"name": "Page1",
"slug": "page1",
"layouts": [
{
"id": "Page1",
"userPermissions": [],
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 4896.0,
"snapColumns": 64.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 1290.0,
"containerStyle": "none",
"snapRows": 125.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 59.0,
"minHeight": 1292.0,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1.0,
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": [
{
"widgetName": "Text1",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b52.svg",
"topRow": 26.0,
"bottomRow": 36.0,
"parentRowSpace": 10.0,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 23.0,
"dynamicBindingPathList": [
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "#FFC13D",
"text": "User count :{{Api1.data.users.length}}",
"key": "i4b3tj04fv",
"isDeprecated": false,
"rightColumn": 38.0,
"textAlign": "LEFT",
"widgetId": "feinx8nce5",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1.0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"fontSize": "1rem"
}
]
},
"layoutOnLoadActions": [
[
{
"id": "Page1_Api1",
"name": "Api1",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
}
]
],
"new": false
}
],
"userPermissions": []
},
"publishedPage": {
"name": "Page1",
"slug": "page1",
"layouts": [
{
"id": "Page1",
"userPermissions": [],
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 4896.0,
"snapColumns": 64.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 1290.0,
"containerStyle": "none",
"snapRows": 125.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 59.0,
"minHeight": 1292.0,
"dynamicTriggerPathList": [],
"parentColumnSpace": 1.0,
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": [
{
"widgetName": "Text1",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b52.svg",
"topRow": 26.0,
"bottomRow": 36.0,
"parentRowSpace": 10.0,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 23.0,
"dynamicBindingPathList": [
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "#FFC13D",
"text": "User count :{{Api1.data.users.length}}",
"key": "i4b3tj04fv",
"isDeprecated": false,
"rightColumn": 38.0,
"textAlign": "LEFT",
"widgetId": "feinx8nce5",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1.0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"fontSize": "1rem"
}
]
},
"layoutOnLoadActions": [
[
{
"id": "Page1_Api1",
"name": "Api1",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
}
]
],
"new": false
}
],
"userPermissions": []
},
"new": true
},
{
"userPermissions": [
"read:pages",
"manage:pages"
],
"gitSyncId": "62987c9ec43c3d0bd6572220_62987cdac43c3d0bd6572227",
"unpublishedPage": {
"name": "Page2",
"slug": "page2",
"layouts": [
{
"id": "Page2",
"userPermissions": [],
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 1224.0,
"snapColumns": 64.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 730.0,
"containerStyle": "none",
"snapRows": 70.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 59.0,
"minHeight": 710.0,
"parentColumnSpace": 1.0,
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": [
{
"widgetName": "Text1",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b52.svg",
"topRow": 31.0,
"bottomRow": 41.0,
"parentRowSpace": 10.0,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 23.0,
"dynamicBindingPathList": [
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "#FFC13D",
"text": "User count :{{Api1.data.users.length}}",
"key": "i4b3tj04fv",
"isDeprecated": false,
"rightColumn": 38.0,
"textAlign": "LEFT",
"widgetId": "31eat3ae9u",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1.0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"fontSize": "1rem"
}
]
},
"layoutOnLoadActions": [
[
{
"id": "Page2_Api1",
"name": "Api1",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
}
]
],
"new": false
}
],
"userPermissions": []
},
"publishedPage": {
"name": "Page2",
"slug": "page2",
"layouts": [
{
"id": "Page2",
"userPermissions": [],
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 1224.0,
"snapColumns": 64.0,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0.0,
"bottomRow": 730.0,
"containerStyle": "none",
"snapRows": 70.0,
"parentRowSpace": 1.0,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 59.0,
"minHeight": 710.0,
"parentColumnSpace": 1.0,
"dynamicBindingPathList": [],
"leftColumn": 0.0,
"children": [
{
"widgetName": "Text1",
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b52.svg",
"topRow": 31.0,
"bottomRow": 41.0,
"parentRowSpace": 10.0,
"type": "TEXT_WIDGET",
"hideCard": false,
"animateLoading": true,
"overflow": "NONE",
"fontFamily": "{{appsmith.theme.fontFamily.appFont}}",
"parentColumnSpace": 20.0625,
"dynamicTriggerPathList": [],
"leftColumn": 23.0,
"dynamicBindingPathList": [
{
"key": "fontFamily"
},
{
"key": "borderRadius"
},
{
"key": "text"
}
],
"shouldTruncate": false,
"truncateButtonColor": "#FFC13D",
"text": "User count :{{Api1.data.users.length}}",
"key": "i4b3tj04fv",
"isDeprecated": false,
"rightColumn": 38.0,
"textAlign": "LEFT",
"widgetId": "31eat3ae9u",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1.0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}",
"fontSize": "1rem"
}
]
},
"layoutOnLoadActions": [
[
{
"id": "Page2_Api1",
"name": "Api1",
"confirmBeforeExecute": false,
"pluginType": "API",
"jsonPathKeys": [],
"timeoutInMillisecond": 10000
}
]
],
"new": false
}
],
"userPermissions": []
},
"new": true
}
],
"pageOrder": [
"Page1",
"Page2"
],
"publishedPageOrder": [
"Page1",
"Page2"
],
"publishedDefaultPageName": "Page1",
"unpublishedDefaultPageName": "Page1",
"actionList": [
{
"id": "Page1_Api1",
"userPermissions": [
"read:actions",
"execute:actions",
"manage:actions"
],
"gitSyncId": "62987c9ec43c3d0bd6572220_62987cafc43c3d0bd6572224",
"pluginType": "API",
"pluginId": "restapi-plugin",
"unpublishedAction": {
"name": "Api1",
"datasource": {
"userPermissions": [],
"name": "DEFAULT_REST_DATASOURCE",
"pluginId": "restapi-plugin",
"datasourceConfiguration": {
"url": "https://mock-api.appsmith.com"
},
"invalids": [],
"messages": [],
"isValid": true,
"new": true
},
"pageId": "Page1",
"actionConfiguration": {
"timeoutInMillisecond": 10000,
"paginationType": "NONE",
"path": "/users",
"headers": [],
"encodeParamsToggle": true,
"queryParameters": [
{
"key": "pageSize",
"value": "5"
}
],
"bodyFormData": [],
"httpMethod": "GET",
"pluginSpecifiedTemplates": [
{
"value": true
}
],
"formData": {
"apiContentType": "none"
}
},
"executeOnLoad": true,
"dynamicBindingPathList": [],
"isValid": true,
"invalids": [],
"messages": [],
"jsonPathKeys": [],
"confirmBeforeExecute": false,
"userPermissions": [],
"validName": "Api1"
},
"publishedAction": {
"name": "Api1",
"datasource": {
"userPermissions": [],
"name": "DEFAULT_REST_DATASOURCE",
"pluginId": "restapi-plugin",
"datasourceConfiguration": {
"url": "https://mock-api.appsmith.com"
},
"invalids": [],
"messages": [],
"isValid": true,
"new": true
},
"pageId": "Page1",
"actionConfiguration": {
"timeoutInMillisecond": 10000,
"paginationType": "NONE",
"path": "/users",
"headers": [],
"encodeParamsToggle": true,
"queryParameters": [
{
"key": "pageSize",
"value": "5"
}
],
"bodyFormData": [],
"httpMethod": "GET",
"pluginSpecifiedTemplates": [
{
"value": true
}
],
"formData": {
"apiContentType": "none"
}
},
"executeOnLoad": true,
"dynamicBindingPathList": [],
"isValid": true,
"invalids": [],
"messages": [],
"jsonPathKeys": [],
"confirmBeforeExecute": false,
"userPermissions": [],
"validName": "Api1"
},
"new": false
},
{
"id": "Page2_Api1",
"userPermissions": [
"read:actions",
"execute:actions",
"manage:actions"
],
"gitSyncId": "62987c9ec43c3d0bd6572220_62987ce3c43c3d0bd657222a",
"pluginType": "API",
"pluginId": "restapi-plugin",
"unpublishedAction": {
"name": "Api1",
"datasource": {
"userPermissions": [],
"name": "DEFAULT_REST_DATASOURCE",
"pluginId": "restapi-plugin",
"datasourceConfiguration": {
"url": "https://mock-api.appsmith.com"
},
"invalids": [],
"messages": [],
"isValid": true,
"new": true
},
"pageId": "Page2",
"actionConfiguration": {
"timeoutInMillisecond": 10000,
"paginationType": "NONE",
"path": "/users",
"headers": [],
"encodeParamsToggle": true,
"queryParameters": [
{
"key": "pageSize",
"value": "10"
}
],
"bodyFormData": [],
"httpMethod": "GET",
"pluginSpecifiedTemplates": [
{
"value": true
}
],
"formData": {
"apiContentType": "none"
}
},
"executeOnLoad": true,
"dynamicBindingPathList": [],
"isValid": true,
"invalids": [],
"messages": [],
"jsonPathKeys": [],
"confirmBeforeExecute": false,
"userPermissions": [],
"validName": "Api1"
},
"publishedAction": {
"name": "Api1",
"datasource": {
"userPermissions": [],
"name": "DEFAULT_REST_DATASOURCE",
"pluginId": "restapi-plugin",
"datasourceConfiguration": {
"url": "https://mock-api.appsmith.com"
},
"invalids": [],
"messages": [],
"isValid": true,
"new": true
},
"pageId": "Page2",
"actionConfiguration": {
"timeoutInMillisecond": 10000,
"paginationType": "NONE",
"path": "/users",
"headers": [],
"encodeParamsToggle": true,
"queryParameters": [
{
"key": "pageSize",
"value": "10"
}
],
"bodyFormData": [],
"httpMethod": "GET",
"pluginSpecifiedTemplates": [
{
"value": true
}
],
"formData": {
"apiContentType": "none"
}
},
"executeOnLoad": true,
"dynamicBindingPathList": [],
"isValid": true,
"invalids": [],
"messages": [],
"jsonPathKeys": [],
"confirmBeforeExecute": false,
"userPermissions": [],
"validName": "Api1"
},
"new": false
}
],
"actionCollectionList": [],
"invisibleActionFields": {
"Page1_Api1": {
"unpublishedUserSetOnLoad": true,
"publishedUserSetOnLoad": true
},
"Page2_Api1": {
"unpublishedUserSetOnLoad": true,
"publishedUserSetOnLoad": true
}
},
"editModeTheme": {
"name": "Classic",
"displayName": "Classic",
"new": true,
"isSystemTheme": true
},
"publishedTheme": {
"name": "Classic",
"displayName": "Classic",
"new": true,
"isSystemTheme": true
},
"publishedLayoutmongoEscapedWidgets": {},
"unpublishedLayoutmongoEscapedWidgets": {}
}

View File

@ -0,0 +1,54 @@
import homePage from "../../../../locators/HomePage";
describe("Execute Action Functionality", function() {
// before(() => {
// cy.get(homePage.homeIcon).click();
// cy.get(homePage.optionsIcon)
// .first()
// .click();
// // Importing the App from the sample application
// cy.get(homePage.orgImportAppOption).click({ force: true });
// cy.get(homePage.orgImportAppModal).should("be.visible");
// cy.xpath(homePage.uploadLogo).attachFile("executeAction.json");
// cy.get(homePage.importAppProgressWrapper).should("be.visible");
// });
it.skip("checks whether execute action is getting called on page load only once", function() {
// Open deployed version
cy.get(homePage.deployPopupOptionTrigger).click({ force: true });
cy.get(homePage.currentDeployedPreviewBtn)
.invoke("removeAttr", "target")
.click();
let completedIds = [];
cy.get("@postExecute.all")
.then((respBody) => {
const totalRequests = [
...new Set(respBody.map((req) => req.browserRequestId)),
];
completedIds = totalRequests;
return totalRequests;
})
.should("have.length", 1);
cy.wait(500);
cy.get(".t--page-switch-tab")
.contains("Page2")
.click({ force: true });
cy.wait(1000);
cy.get("@postExecute.all")
.then((respBody) => {
const totalRequests = [
...new Set(respBody.map((req) => req.browserRequestId)),
];
return totalRequests.filter((reqId) => !completedIds.includes(reqId));
})
.should("have.length", 1);
cy.wait(2000);
});
});

View File

@ -11,8 +11,9 @@ import { QueryActionConfig } from "entities/Action";
export const FIRST_EVAL_REDUX_ACTIONS = [
// Pages
ReduxActionTypes.FETCH_PAGE_SUCCESS,
ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
// ReduxActionTypes.FETCH_PAGE_SUCCESS,
// ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
ReduxActionTypes.FETCH_ALL_PAGE_ENTITY_COMPLETION,
];
export const EVALUATE_REDUX_ACTIONS = [
...FIRST_EVAL_REDUX_ACTIONS,

View File

@ -134,6 +134,12 @@ export const fetchJSCollectionsForPageSuccess = (actions: JSCollection[]) => {
};
};
export const fetchJSCollectionsForPageError = () => {
return {
type: ReduxActionErrorTypes.FETCH_JS_ACTIONS_FOR_PAGE_ERROR,
};
};
export const fetchJSCollectionsForView = ({
applicationId,
}: {

View File

@ -5,9 +5,9 @@ import {
ReduxActionTypes,
UpdateCanvasPayload,
ReduxActionErrorTypes,
AnyReduxAction,
WidgetReduxActionTypes,
ReplayReduxActionTypes,
AnyReduxAction,
} from "@appsmith/constants/ReduxActionConstants";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { WidgetOperation } from "widgets/BaseWidget";
@ -62,20 +62,29 @@ export const fetchPublishedPage = (
},
});
export const fetchPageSuccess = (
postEvalActions: Array<AnyReduxAction>,
): EvaluationReduxAction<undefined> => {
export const fetchPageSuccess = (): EvaluationReduxAction<undefined> => {
return {
type: ReduxActionTypes.FETCH_PAGE_SUCCESS,
postEvalActions,
payload: undefined,
};
};
export const fetchPublishedPageSuccess = (
postEvalActions: Array<AnyReduxAction>,
): EvaluationReduxAction<undefined> => ({
export const fetchPublishedPageSuccess = (): EvaluationReduxAction<undefined> => ({
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
payload: undefined,
});
/**
* After all page entities are fetched like DSL, actions and JsObjects,
* we trigger evaluation using this redux action, here we supply postEvalActions
* to trigger action after evaluation has been completed like executeOnPageLoadAction
*
* @param {Array<AnyReduxAction>} postEvalActions
*/
export const fetchAllPageEntityCompletion = (
postEvalActions: Array<AnyReduxAction>,
) => ({
type: ReduxActionTypes.FETCH_ALL_PAGE_ENTITY_COMPLETION,
postEvalActions,
payload: undefined,
});

View File

@ -54,23 +54,25 @@ export const fetchActionsForView = ({
export const fetchActionsForPage = (
pageId: string,
postEvalActions: Array<AnyReduxAction> = [],
): EvaluationReduxAction<unknown> => {
return {
type: ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_INIT,
payload: { pageId },
postEvalActions,
};
};
export const fetchActionsForPageSuccess = (
actions: Action[],
postEvalActions?: Array<AnyReduxAction>,
): EvaluationReduxAction<unknown> => {
return {
type: ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_SUCCESS,
payload: actions,
postEvalActions,
};
};
export const fetchActionsForPageError = () => {
return {
type: ReduxActionErrorTypes.FETCH_ACTIONS_FOR_PAGE_ERROR,
};
};

View File

@ -207,6 +207,7 @@ export const ReduxActionTypes = {
CLEAR_CANVAS: "CLEAR_CANVAS",
FETCH_PAGE_INIT: "FETCH_PAGE_INIT",
FETCH_PAGE_SUCCESS: "FETCH_PAGE_SUCCESS",
FETCH_ALL_PAGE_ENTITY_COMPLETION: "FETCH_ALL_PAGE_ENTITY_COMPLETION",
DROP_WIDGET_CANVAS: "DROP_WIDGET_CANVAS",
REMOVE_WIDGET_CANVAS: "REMOVE_WIDGET_CANVAS",
LOAD_WIDGET_PANE: "LOAD_WIDGET_PANE",

View File

@ -1,6 +1,6 @@
import React, { useEffect, useMemo } from "react";
import React, { useMemo } from "react";
import { Link, RouteComponentProps, withRouter } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { useSelector } from "react-redux";
import { getIsFetchingPage } from "selectors/appViewSelectors";
import styled from "styled-components";
import { AppViewerRouteParams } from "constants/routes";
@ -19,7 +19,6 @@ import {
isPermitted,
PERMISSION_TYPE,
} from "../Applications/permissionHelpers";
import { fetchPublishedPage } from "actions/pageActions";
import { builderURL } from "RouteBuilder";
const Section = styled.section<{
@ -36,19 +35,13 @@ const Section = styled.section<{
type AppViewerPageContainerProps = RouteComponentProps<AppViewerRouteParams>;
function AppViewerPageContainer(props: AppViewerPageContainerProps) {
const dispatch = useDispatch();
const currentPageName = useSelector(getCurrentPageName);
const widgets = useSelector(getCanvasWidgetDsl);
const isFetchingPage = useSelector(getIsFetchingPage);
const currentApplication = useSelector(getCurrentApplication);
const { match } = props;
const { pageId } = match.params;
const { applicationSlug, pageSlug } = useSelector(selectURLSlugs);
useEffect(() => {
pageId && dispatch(fetchPublishedPage(pageId, true));
}, [pageId, location.pathname]);
// get appsmith editr link
const appsmithEditorLink = useMemo(() => {
if (

View File

@ -285,9 +285,8 @@ export function* fetchActionsForPageSaga(
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put(
fetchActionsForPageSuccess(response.data, action.postEvalActions),
);
yield put(fetchActionsForPageSuccess(response.data));
// wait for success of
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
);

View File

@ -127,7 +127,7 @@ function* evaluateTreeSaga(
dataTree,
dependencies,
errors,
evalMetaUpdates,
evalMetaUpdates = [],
evaluationOrder,
jsUpdates,
logs,

View File

@ -20,6 +20,7 @@ import { ERROR_CODES } from "@appsmith/constants/ApiConstants";
import {
fetchPage,
fetchPageSuccess,
fetchPublishedPage,
fetchPublishedPageSuccess,
resetApplicationWidgets,
@ -87,6 +88,7 @@ import { isURLDeprecated, getUpdatedRoute } from "utils/helpers";
import { fillPathname, viewerURL, builderURL } from "RouteBuilder";
import { enableGuidedTour } from "actions/onboardingActions";
import { setPreviewModeAction } from "actions/editorActions";
import { fetchAllPageEntityCompletion } from "actions/pageActions";
import {
fetchSelectedAppThemeAction,
fetchAppThemesAction,
@ -97,17 +99,9 @@ export function* failFastApiCalls(
successActions: string[],
failureActions: string[],
) {
const triggerEffects = [];
for (const triggerAction of triggerActions) {
triggerEffects.push(put(triggerAction));
}
const successEffects = [];
for (const successAction of successActions) {
successEffects.push(take(successAction));
}
yield all(triggerEffects);
yield all(triggerActions.map((triggerAction) => put(triggerAction)));
const effectRaceResult = yield race({
success: all(successEffects),
success: all(successActions.map((successAction) => take(successAction))),
failure: take(failureActions),
});
if (effectRaceResult.failure) {
@ -230,19 +224,12 @@ function* initiateEditorApplicationAndPages(payload: InitializeEditorPayload) {
yield call(initiateURLUpdate, toLoadPageId, APP_MODE.EDIT, payload.pageId);
const fetchPageCallResult: boolean = yield failFastApiCalls(
[fetchPage(toLoadPageId, true)],
[ReduxActionTypes.FETCH_PAGE_SUCCESS],
[ReduxActionErrorTypes.FETCH_PAGE_ERROR],
);
if (!fetchPageCallResult) return;
return toLoadPageId;
}
function* initiateEditorActions(applicationId: string) {
function* initiateEditorActions(toLoadPageId: string, applicationId: string) {
const initActionsCalls = [
fetchPage(toLoadPageId, true),
fetchActions({ applicationId }, []),
fetchJSCollections({ applicationId }),
fetchSelectedAppThemeAction(applicationId),
@ -254,12 +241,14 @@ function* initiateEditorActions(applicationId: string) {
ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
ReduxActionTypes.FETCH_APP_THEMES_SUCCESS,
ReduxActionTypes.FETCH_SELECTED_APP_THEME_SUCCESS,
fetchPageSuccess().type,
];
const failureActionEffects = [
ReduxActionErrorTypes.FETCH_JS_ACTIONS_ERROR,
ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
ReduxActionErrorTypes.FETCH_APP_THEMES_ERROR,
ReduxActionErrorTypes.FETCH_SELECTED_APP_THEME_ERROR,
ReduxActionErrorTypes.FETCH_PAGE_ERROR,
];
const allActionCalls: boolean = yield failFastApiCalls(
initActionsCalls,
@ -273,7 +262,7 @@ function* initiateEditorActions(applicationId: string) {
yield put({
type: ReduxActionTypes.FETCH_PLUGIN_AND_JS_ACTIONS_SUCCESS,
});
yield put(executePageLoadActions());
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
}
}
@ -337,7 +326,8 @@ function* initializeEditorSaga(
PerformanceTransactionName.INIT_EDIT_APP,
);
yield call(initiateEditorApplicationAndPages, payload);
const toLoadPageId = yield call(initiateEditorApplicationAndPages, payload);
if (!toLoadPageId) return;
const { id: applicationId, name }: ApplicationPayload = yield select(
getCurrentApplication,
@ -348,7 +338,7 @@ function* initializeEditorSaga(
);
yield all([
call(initiateEditorActions, applicationId),
call(initiateEditorActions, toLoadPageId, applicationId),
call(initiatePluginsAndDatasources),
call(populatePageDSLsSaga),
]);
@ -430,15 +420,16 @@ export function* initializeAppViewerSaga(
[
fetchActionsForView({ applicationId }),
fetchJSCollectionsForView({ applicationId }),
fetchPublishedPage(toLoadPageId, true, true),
fetchSelectedAppThemeAction(applicationId),
fetchAppThemesAction(applicationId),
fetchPublishedPage(toLoadPageId, true, true),
],
[
ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS,
ReduxActionTypes.FETCH_JS_ACTIONS_VIEW_MODE_SUCCESS,
ReduxActionTypes.FETCH_APP_THEMES_SUCCESS,
ReduxActionTypes.FETCH_SELECTED_APP_THEME_SUCCESS,
fetchPublishedPageSuccess().type,
],
[
ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
@ -451,34 +442,7 @@ export function* initializeAppViewerSaga(
if (!resultOfPrimaryCalls) return;
//Delay page load actions till all actions are retrieved.
yield put(fetchPublishedPageSuccess([executePageLoadActions()]));
if (toLoadPageId) {
yield put(fetchPublishedPage(toLoadPageId, true));
const resultOfFetchPage: {
success: boolean;
failure: boolean;
} = yield race({
success: take(ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS),
failure: take(ReduxActionErrorTypes.FETCH_PUBLISHED_PAGE_ERROR),
});
if (resultOfFetchPage.failure) {
yield put({
type: ReduxActionTypes.SAFE_CRASH_APPSMITH_REQUEST,
payload: {
code: get(
resultOfFetchPage,
"failure.payload.error.code",
ERROR_CODES.SERVER_ERROR,
),
},
});
return;
}
}
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
yield put(fetchCommentThreadsInit());

View File

@ -24,6 +24,9 @@ import {
setLastUpdatedTime,
ClonePageActionPayload,
CreatePageActionPayload,
generateTemplateError,
generateTemplateSuccess,
fetchAllPageEntityCompletion,
} from "actions/pageActions";
import PageApi, {
ClonePageRequest,
@ -76,6 +79,8 @@ import {
fetchActionsForPage,
setActionsToExecuteOnPageLoad,
setJSActionsToExecuteOnPageLoad,
fetchActionsForPageSuccess,
fetchActionsForPageError,
} from "actions/pluginActionActions";
import { UrlDataState } from "reducers/entityReducers/appReducer";
import { APP_MODE } from "entities/App";
@ -93,10 +98,7 @@ import { ERROR_CODES } from "@appsmith/constants/ApiConstants";
import AnalyticsUtil from "utils/AnalyticsUtil";
import DEFAULT_TEMPLATE from "templates/default";
import { GenerateTemplatePageRequest } from "api/PageApi";
import {
generateTemplateError,
generateTemplateSuccess,
} from "actions/pageActions";
import { getAppMode } from "selectors/applicationSelectors";
import { setCrudInfoModalData } from "actions/crudInfoModalActions";
import { selectMultipleWidgetsAction } from "actions/widgetSelectionActions";
@ -105,11 +107,16 @@ import {
getFirstTimeUserOnboardingApplicationId,
inGuidedTour,
} from "selectors/onboardingSelectors";
import { fetchJSCollectionsForPage } from "actions/jsActionActions";
import {
fetchJSCollectionsForPage,
fetchJSCollectionsForPageSuccess,
fetchJSCollectionsForPageError,
} from "actions/jsActionActions";
import WidgetFactory from "utils/WidgetFactory";
import { toggleShowDeviationDialog } from "actions/onboardingActions";
import { builderURL, generateTemplateURL } from "RouteBuilder";
import { failFastApiCalls } from "./InitSagas";
const WidgetTypes = WidgetFactory.widgetTypes;
@ -223,12 +230,15 @@ export function* handleFetchedPage({
// set current page
yield put(updateCurrentPage(pageId, pageSlug));
// dispatch fetch page success
yield put(
fetchPageSuccess(
// Execute page load actions post page load
isFirstLoad ? [] : [executePageLoadActions()],
),
);
yield put(fetchPageSuccess());
/* Currently, All Actions are fetched in initSagas and on pageSwitch we only fetch page
*/
// Hence, if is not isFirstLoad then trigger evaluation with execute pageLoad action
if (!isFirstLoad) {
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
}
// Sets last updated time
yield put(setLastUpdatedTime(lastUpdatedTime));
const extractedDSL = extractCurrentDSL(fetchPageResponse);
@ -321,15 +331,16 @@ export function* fetchPublishedPageSaga(
// set current page
yield put(updateCurrentPage(pageId, response.data.slug));
// dispatch fetch page success
yield put(fetchPublishedPageSuccess());
/* Currently, All Actions are fetched in initSagas and on pageSwitch we only fetch page
*/
// Hence, if is not isFirstLoad then trigger evaluation with execute pageLoad action
if (!firstLoad) {
// dispatch fetch page success
yield put(
fetchPublishedPageSuccess(
// Execute page load actions post published page eval
[executePageLoadActions()],
),
);
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
}
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
);
@ -977,6 +988,15 @@ export function* generateTemplatePageSaga(
const isValidResponse: boolean = yield validateResponse(response);
if (isValidResponse) {
const pageId = response.data.page.id;
yield put(
generateTemplateSuccess({
page: response.data.page,
isNewPage: !request.pageId,
// if pageId if not defined, that means a new page is generated.
}),
);
yield handleFetchedPage({
fetchPageResponse: {
data: response.data.page,
@ -986,16 +1006,30 @@ export function* generateTemplatePageSaga(
isFirstLoad: true,
});
// TODO : Add this to onSuccess (Redux Action)
yield put(
generateTemplateSuccess({
page: response.data.page,
isNewPage: !request.pageId, // if pageId if not defined, that means a new page is generated.
}),
// trigger evaluation after completion of page success & fetch actions for page + fetch jsobject for page
const triggersAfterPageFetch = [
fetchActionsForPage(pageId),
fetchJSCollectionsForPage(pageId),
];
const afterActionsFetch = yield failFastApiCalls(
triggersAfterPageFetch,
[
fetchActionsForPageSuccess([]).type,
fetchJSCollectionsForPageSuccess([]).type,
],
[
fetchActionsForPageError().type,
fetchJSCollectionsForPageError().type,
],
);
// TODO : Add this to onSuccess (Redux Action)
yield put(fetchActionsForPage(pageId, [executePageLoadActions()]));
// TODO : Add it to onSuccessCallback
if (!afterActionsFetch) {
throw new Error("Failed generating template");
}
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
history.replace(
builderURL({
pageSlug: response.data.page.slug,

View File

@ -149,7 +149,6 @@ ctx.addEventListener(
evaluationOrder = dataTreeEvaluator.sortedDependencies;
dataTree = dataTreeResponse.evalTree;
jsUpdates = dataTreeResponse.jsUpdates;
evalMetaUpdates = dataTreeResponse.evalMetaUpdates;
dataTree = dataTree && JSON.parse(JSON.stringify(dataTree));
} else {
if (dataTreeEvaluator && !isEmpty(allActionValidationConfig)) {
@ -166,7 +165,11 @@ ctx.addEventListener(
unEvalUpdates = updateResponse.unEvalUpdates;
dataTree = JSON.parse(JSON.stringify(dataTreeEvaluator.evalTree));
jsUpdates = updateResponse.jsUpdates;
evalMetaUpdates = updateResponse.evalMetaUpdates;
// evalMetaUpdates can have moment object as value which will cause DataCloneError
// hence, stringify and parse to avoid such errors
evalMetaUpdates = JSON.parse(
JSON.stringify(updateResponse.evalMetaUpdates),
);
}
dependencies = dataTreeEvaluator.inverseDependencyMap;
errors = dataTreeEvaluator.errors;