diff --git a/app/client/public/index.html b/app/client/public/index.html index c8b529591a..227aac35cb 100755 --- a/app/client/public/index.html +++ b/app/client/public/index.html @@ -14,6 +14,9 @@ background: #D7D7D7; transition: all ease-in 0.3s; } + #app-load-block { + visibility: hidden; + } - \ No newline at end of file + diff --git a/app/client/src/actions/initActions.ts b/app/client/src/actions/initActions.ts index 589d9a82e4..3f18b301da 100644 --- a/app/client/src/actions/initActions.ts +++ b/app/client/src/actions/initActions.ts @@ -2,12 +2,6 @@ import type { APP_MODE } from "entities/App"; import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; -export const initCurrentPage = () => { - return { - type: ReduxActionTypes.INITIALIZE_CURRENT_PAGE, - }; -}; - export type InitializeEditorPayload = { applicationId?: string; pageId?: string; diff --git a/app/client/src/ce/AppRouter.tsx b/app/client/src/ce/AppRouter.tsx index 2684a9475a..629843d2a2 100644 --- a/app/client/src/ce/AppRouter.tsx +++ b/app/client/src/ce/AppRouter.tsx @@ -1,4 +1,4 @@ -import React, { Suspense, useEffect } from "react"; +import React, { Suspense } from "react"; import history from "utils/history"; import AppHeader from "pages/common/AppHeader"; import { Redirect, Route, Router, Switch } from "react-router-dom"; @@ -38,35 +38,23 @@ import ErrorPage from "pages/common/ErrorPage"; import PageNotFound from "pages/common/ErrorPages/PageNotFound"; import PageLoadingBar from "pages/common/PageLoadingBar"; import ErrorPageHeader from "pages/common/ErrorPageHeader"; -import type { AppState } from "@appsmith/reducers"; -import { connect, useSelector } from "react-redux"; +import { useSelector } from "react-redux"; import * as Sentry from "@sentry/react"; import { getSafeCrash, getSafeCrashCode } from "selectors/errorSelectors"; import UserProfile from "pages/UserProfile"; -import { getCurrentUser } from "actions/authActions"; -import { getCurrentUserLoading } from "selectors/usersSelectors"; import Setup from "pages/setup"; import SettingsLoader from "pages/Settings/loader"; import SignupSuccess from "pages/setup/SignupSuccess"; import type { ERROR_CODES } from "@appsmith/constants/ApiConstants"; import TemplatesListLoader from "pages/Templates/loader"; -import { - fetchFeatureFlagsInit, - fetchProductAlertInit, -} from "actions/userActions"; -import { getCurrentTenant } from "@appsmith/actions/tenantActions"; import { getDefaultAdminSettingsPath } from "@appsmith/utils/adminSettingsHelpers"; import { getCurrentUser as getCurrentUserSelector } from "selectors/usersSelectors"; -import { - getTenantPermissions, - isTenantLoading, -} from "@appsmith/selectors/tenantSelectors"; -import useBrandingTheme from "utils/hooks/useBrandingTheme"; +import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; import RouteChangeListener from "RouteChangeListener"; -import { initCurrentPage } from "../actions/initActions"; import Walkthrough from "components/featureWalkthrough"; import ProductAlertBanner from "components/editorComponents/ProductAlertBanner"; +import { useFirstRouteLoad } from "../pages/loaderHooks"; export const SentryRoute = Sentry.withSentryRouting(Route); @@ -75,7 +63,6 @@ export const loadingIndicator = ; export function Routes() { const user = useSelector(getCurrentUserSelector); const tenantPermissions = useSelector(getTenantPermissions); - return ( @@ -131,60 +118,18 @@ export function Routes() { ); } -function AppRouter(props: { - safeCrash: boolean; - getCurrentUser: () => void; - getFeatureFlags: () => void; - getCurrentTenant: () => void; - initCurrentPage: () => void; - fetchProductAlert: () => void; - safeCrashCode?: ERROR_CODES; -}) { - const { - fetchProductAlert, - getCurrentTenant, - getCurrentUser, - getFeatureFlags, - initCurrentPage, - } = props; - const tenantIsLoading = useSelector(isTenantLoading); - const currentUserIsLoading = useSelector(getCurrentUserLoading); - - useEffect(() => { - getCurrentUser(); - getFeatureFlags(); - getCurrentTenant(); - initCurrentPage(); - fetchProductAlert(); - }, []); - - useBrandingTheme(); - - // hide the top loader once the tenant is loaded - useEffect(() => { - if (tenantIsLoading === false && currentUserIsLoading === false) { - const loader = document.getElementById("loader") as HTMLDivElement; - - if (loader) { - loader.style.width = "100vw"; - - setTimeout(() => { - loader.style.opacity = "0"; - }); - } - } - }, [tenantIsLoading, currentUserIsLoading]); - - if (tenantIsLoading || currentUserIsLoading) return null; - +function AppRouter() { + useFirstRouteLoad(); + const isSafeCrash = useSelector(getSafeCrash); + const safeCrashCode: ERROR_CODES | undefined = useSelector(getSafeCrashCode); return ( - {props.safeCrash && props.safeCrashCode ? ( + {isSafeCrash && safeCrashCode ? ( <> - + ) : ( <> @@ -200,17 +145,4 @@ function AppRouter(props: { ); } -const mapStateToProps = (state: AppState) => ({ - safeCrash: getSafeCrash(state), - safeCrashCode: getSafeCrashCode(state), -}); - -const mapDispatchToProps = (dispatch: any) => ({ - getCurrentUser: () => dispatch(getCurrentUser()), - getFeatureFlags: () => dispatch(fetchFeatureFlagsInit()), - getCurrentTenant: () => dispatch(getCurrentTenant(false)), - initCurrentPage: () => dispatch(initCurrentPage()), - fetchProductAlert: () => dispatch(fetchProductAlertInit()), -}); - -export default connect(mapStateToProps, mapDispatchToProps)(AppRouter); +export default AppRouter; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index ea3d34b087..a9c6d70787 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -151,7 +151,6 @@ const ActionTypes = { RESET_SNIPING_MODE: "RESET_SNIPING_MODE", RESET_EDITOR_REQUEST: "RESET_EDITOR_REQUEST", RESET_EDITOR_SUCCESS: "RESET_EDITOR_SUCCESS", - INITIALIZE_CURRENT_PAGE: "INITIALIZE_CURRENT_PAGE", INITIALIZE_EDITOR: "INITIALIZE_EDITOR", INITIALIZE_EDITOR_SUCCESS: "INITIALIZE_EDITOR_SUCCESS", REPORT_ERROR: "REPORT_ERROR", diff --git a/app/client/src/ce/selectors/tenantSelectors.tsx b/app/client/src/ce/selectors/tenantSelectors.tsx index 6f77dc9886..93ae9b73b0 100644 --- a/app/client/src/ce/selectors/tenantSelectors.tsx +++ b/app/client/src/ce/selectors/tenantSelectors.tsx @@ -27,7 +27,7 @@ export const isValidLicense = () => { return true; }; -export const isTenantLoading = (state: AppState) => { +export const getIsTenantLoading = (state: AppState) => { return state.tenant?.isLoading; }; diff --git a/app/client/src/pages/Settings/loader.tsx b/app/client/src/pages/Settings/loader.tsx index 72751e3882..c97f345d52 100644 --- a/app/client/src/pages/Settings/loader.tsx +++ b/app/client/src/pages/Settings/loader.tsx @@ -1,6 +1,9 @@ import React from "react"; import PageLoadingBar from "pages/common/PageLoadingBar"; import { retryPromise } from "utils/AppsmithUtils"; +import { useSelector } from "react-redux"; +import { getCurrentUserLoading } from "selectors/usersSelectors"; +import { getIsTenantLoading } from "@appsmith/selectors/tenantSelectors"; const Page = React.lazy(() => retryPromise( @@ -12,6 +15,9 @@ const Page = React.lazy(() => ); const AdminSettingsLoader = (props: any) => { + const tenantIsLoading = useSelector(getIsTenantLoading); + const currentUserIsLoading = useSelector(getCurrentUserLoading); + if (tenantIsLoading || currentUserIsLoading) return null; return ( }> diff --git a/app/client/src/pages/loaderHooks.ts b/app/client/src/pages/loaderHooks.ts new file mode 100644 index 0000000000..268f016839 --- /dev/null +++ b/app/client/src/pages/loaderHooks.ts @@ -0,0 +1,48 @@ +import { useEffect } from "react"; +import useBrandingTheme from "../utils/hooks/useBrandingTheme"; +import { useDispatch, useSelector } from "react-redux"; +import { getCurrentUser } from "../actions/authActions"; +import { + fetchFeatureFlagsInit, + fetchProductAlertInit, +} from "../actions/userActions"; +import { getCurrentTenant } from "@appsmith/actions/tenantActions"; +import { getIsTenantLoading } from "@appsmith/selectors/tenantSelectors"; +import { getCurrentUserLoading } from "../selectors/usersSelectors"; + +export const useFirstRouteLoad = () => { + const dispatch = useDispatch(); + const tenantIsLoading = useSelector(getIsTenantLoading); + const currentUserIsLoading = useSelector(getCurrentUserLoading); + + useEffect(() => { + dispatch(getCurrentUser()); + dispatch(fetchFeatureFlagsInit()); + dispatch(getCurrentTenant()); + dispatch(fetchProductAlertInit()); + }, []); + + useBrandingTheme(); + + // hide the top loader once the tenant is loaded + // Show app only after tenant is loaded (concerns theming and licence check) + useEffect(() => { + if (tenantIsLoading === false && currentUserIsLoading === false) { + const loader = document.getElementById("loader") as HTMLDivElement; + const appLoadBlock = document.getElementById( + "app-load-block", + ) as HTMLDivElement; + + if (loader) { + loader.style.width = "100vw"; + + setTimeout(() => { + loader.style.opacity = "0"; + }); + } + if (appLoadBlock) { + appLoadBlock.style.visibility = "visible"; + } + } + }, [tenantIsLoading, currentUserIsLoading]); +}; diff --git a/app/client/src/sagas/ErrorSagas.tsx b/app/client/src/sagas/ErrorSagas.tsx index d8a47371e3..1658311567 100644 --- a/app/client/src/sagas/ErrorSagas.tsx +++ b/app/client/src/sagas/ErrorSagas.tsx @@ -17,7 +17,7 @@ import { import { getSafeCrash } from "selectors/errorSelectors"; import { getCurrentUser } from "selectors/usersSelectors"; import { ANONYMOUS_USERNAME } from "constants/userConstants"; -import { put, takeLatest, call, select } from "redux-saga/effects"; +import { put, takeLatest, call, select, take } from "redux-saga/effects"; import { ERROR_401, ERROR_403, @@ -269,11 +269,15 @@ function logErrorSaga(action: ReduxAction<{ error: ErrorPayloadType }>) { * this saga do some logic before actually setting safeCrash to true */ function* safeCrashSagaRequest(action: ReduxAction<{ code?: ERROR_CODES }>) { - const user: User | undefined = yield select(getCurrentUser); + let user: User | undefined = yield select(getCurrentUser); + if (!user) { + yield take(ReduxActionTypes.FETCH_USER_DETAILS_SUCCESS); + user = yield select(getCurrentUser); + } const code = get(action, "payload.code"); // if user is not logged and the error is "PAGE_NOT_FOUND", - // redirecting user to login page with redirecTo param + // redirecting user to login page with redirectTo param if ( get(user, "email") === ANONYMOUS_USERNAME && code === ERROR_CODES.PAGE_NOT_FOUND diff --git a/app/client/src/sagas/InitSagas.ts b/app/client/src/sagas/InitSagas.ts index 84de28f7f7..cd6b26b83a 100644 --- a/app/client/src/sagas/InitSagas.ts +++ b/app/client/src/sagas/InitSagas.ts @@ -23,11 +23,7 @@ import { resetCurrentApplication } from "@appsmith/actions/applicationActions"; import log from "loglevel"; import * as Sentry from "@sentry/react"; import { resetRecentEntities } from "actions/globalSearchActions"; -import { - initAppViewer, - initEditor, - resetEditorSuccess, -} from "actions/initActions"; +import { resetEditorSuccess } from "actions/initActions"; import { getCurrentPageId, getIsEditorInitialized, @@ -42,7 +38,7 @@ import type AppEngine from "entities/Engine"; import { AppEngineApiError } from "entities/Engine"; import AppEngineFactory from "entities/Engine/factory"; import type { ApplicationPagePayload } from "@appsmith/api/ApplicationApi"; -import { getSearchQuery, updateSlugNamesInURL } from "utils/helpers"; +import { updateSlugNamesInURL } from "utils/helpers"; import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions"; import { safeCrashAppRequest } from "../actions/errorActions"; import { resetSnipingMode } from "actions/propertyPaneActions"; @@ -50,16 +46,7 @@ import { setExplorerActiveAction, setExplorerPinnedAction, } from "actions/explorerActions"; -import { - isEditorPath, - isViewerPath, -} from "@appsmith/pages/Editor/Explorer/helpers"; -import { APP_MODE } from "../entities/App"; -import { - GIT_BRANCH_QUERY_KEY, - matchBuilderPath, - matchViewerPath, -} from "../constants/routes"; +import type { APP_MODE } from "../entities/App"; import AnalyticsUtil from "utils/AnalyticsUtil"; import { getAppMode } from "@appsmith/selectors/applicationSelectors"; @@ -220,42 +207,6 @@ function* appEngineSaga(action: ReduxAction) { }); } -function* eagerPageInitSaga() { - const url = window.location.pathname; - const search = window.location.search; - if (isEditorPath(url)) { - const { - params: { applicationId, pageId }, - } = matchBuilderPath(url); - const branch = getSearchQuery(search, GIT_BRANCH_QUERY_KEY); - if (pageId) { - yield put( - initEditor({ - pageId, - applicationId, - branch, - mode: APP_MODE.EDIT, - }), - ); - } - } else if (isViewerPath(url)) { - const { - params: { applicationId, pageId }, - } = matchViewerPath(url); - const branch = getSearchQuery(search, GIT_BRANCH_QUERY_KEY); - if (applicationId || pageId) { - yield put( - initAppViewer({ - applicationId, - branch, - pageId, - mode: APP_MODE.PUBLISHED, - }), - ); - } - } -} - export default function* watchInitSagas() { yield all([ takeLeading( @@ -267,6 +218,5 @@ export default function* watchInitSagas() { ), takeLatest(ReduxActionTypes.RESET_EDITOR_REQUEST, resetEditorSaga), takeEvery(URL_CHANGE_ACTIONS, updateURLSaga), - takeEvery(ReduxActionTypes.INITIALIZE_CURRENT_PAGE, eagerPageInitSaga), ]); }