diff --git a/app/client/src/ce/actions/environmentAction.ts b/app/client/src/ce/actions/environmentAction.ts index 6e283a7ef0..9736308933 100644 --- a/app/client/src/ce/actions/environmentAction.ts +++ b/app/client/src/ce/actions/environmentAction.ts @@ -1,2 +1,8 @@ // Redux action to show the environment info modal before deploy export const showEnvironmentDeployInfoModal = () => ({}); + +// Redux action to update the current editing environment ID +export const setCurrentEditingEnvironmentID = (currentEditingId: string) => ({ + type: "", + payload: { currentEditingId }, +}); diff --git a/app/client/src/ce/api/ApiUtils.ts b/app/client/src/ce/api/ApiUtils.ts index f13d6e1c60..79aa94da28 100644 --- a/app/client/src/ce/api/ApiUtils.ts +++ b/app/client/src/ce/api/ApiUtils.ts @@ -26,10 +26,7 @@ import { getAppsmithConfigs } from "@appsmith/configs"; import * as Sentry from "@sentry/react"; import { CONTENT_TYPE_HEADER_KEY } from "constants/ApiEditorConstants/CommonApiConstants"; import { isAirgapped } from "@appsmith/utils/airgapHelpers"; -import { - getCurrentEnvironment, - getCurrentEditingEnvID, -} from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const executeActionRegex = /actions\/execute/; const timeoutErrorRegex = /timeout of (\d+)ms exceeded/; @@ -49,6 +46,17 @@ export const BLOCKED_ROUTES_REGEX = new RegExp( `^(${BLOCKED_ROUTES.join("|")})($|/)`, ); +export const ENV_ENABLED_ROUTES = [ + "v1/datasources/[a-z0-9]+/structure", + "/v1/datasources/[a-z0-9]+/trigger", + "v1/actions/execute", + "v1/saas", +]; + +export const ENV_ENABLED_ROUTES_REGEX = new RegExp( + `^(${ENV_ENABLED_ROUTES.join("|")})($|/)`, +); + const makeExecuteActionResponse = (response: any): ActionExecutionResponse => ({ ...response.data, clientMeta: { @@ -86,8 +94,8 @@ export const apiRequestInterceptor = (config: AxiosRequestConfig) => { config.headers["X-Requested-By"] = "Appsmith"; } - const branch = - getCurrentGitBranch(store.getState()) || getQueryParamsObject().branch; + const state = store.getState(); + const branch = getCurrentGitBranch(state) || getQueryParamsObject().branch; if (branch && config.headers) { config.headers.branchName = branch; } @@ -95,13 +103,11 @@ export const apiRequestInterceptor = (config: AxiosRequestConfig) => { config.timeout = 1000 * 120; // increase timeout for git specific APIs } - // Add header for environment name - const activeEnv = getCurrentEnvironment(); + if (ENV_ENABLED_ROUTES_REGEX.test(config.url?.split("?")[0] || "")) { + // Add header for environment name + const activeEnv = getCurrentEnvironmentId(state); - if (activeEnv && config.headers) { - if (config.url?.indexOf("/code") !== -1) { - config.headers.environmentId = getCurrentEditingEnvID(); - } else { + if (activeEnv && config.headers) { config.headers.environmentId = activeEnv; } } diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 408f1bdccb..38233cde38 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1973,10 +1973,10 @@ export const MOVE_TO_BUSINESS_EDITION = (trailingChar: string) => //Datasource environment export const START_SWITCH_ENVIRONMENT = (environment: string) => - `Switching your environment to ${environment}, and running all associated pageload actions`; + `Switching your environment to ${environment.toLowerCase()}, and running all associated pageload actions`; export const SWITCH_ENVIRONMENT_SUCCESS = (environment: string) => - `Environment switched to ${environment} successfully`; -export const SWITCH_ENV_DISABLED_TOOLTIP_TEXT = () => + `Environment switched to ${environment.toLowerCase()} successfully`; +export const SWITCH_ENV_DISABLED_TOOLTIP_TEXT = (): string => "To access environments for datasources, try out our "; export const TEST_DATASOURCE_SUCCESS = ( @@ -1984,7 +1984,7 @@ export const TEST_DATASOURCE_SUCCESS = ( environmentName: string, ) => { return environmentName - ? `Test was successful, ${datasourceName} ${environmentName} environment is correctly configured.` + ? `Test was successful, ${datasourceName} ${environmentName.toLowerCase()} environment is correctly configured.` : `Test was successful, ${datasourceName} is correctly configured.`; }; diff --git a/app/client/src/ce/sagas/ApplicationSagas.tsx b/app/client/src/ce/sagas/ApplicationSagas.tsx index 214cc05e85..fbe440fc4f 100644 --- a/app/client/src/ce/sagas/ApplicationSagas.tsx +++ b/app/client/src/ce/sagas/ApplicationSagas.tsx @@ -122,10 +122,10 @@ import { keysOfNavigationSetting, } from "constants/AppConstants"; import { setAllEntityCollapsibleStates } from "actions/editorContextActions"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { generateReactKey } from "utils/generators"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; export const getDefaultPageId = ( pages?: ApplicationPagePayload[], @@ -877,7 +877,7 @@ export function* fetchUnconfiguredDatasourceList( } export function* initializeDatasourceWithDefaultValues(datasource: Datasource) { - let currentEnvironment = getCurrentEnvironment(); + let currentEnvironment: string = yield select(getCurrentEnvironmentId); if (!datasource.datasourceStorages.hasOwnProperty(currentEnvironment)) { // if the currentEnvironemnt is not present for use here, take the first key from datasourceStorages currentEnvironment = Object.keys(datasource.datasourceStorages)[0]; diff --git a/app/client/src/ce/sagas/EnvironmentSagas.ts b/app/client/src/ce/sagas/EnvironmentSagas.ts new file mode 100644 index 0000000000..231df5bed1 --- /dev/null +++ b/app/client/src/ce/sagas/EnvironmentSagas.ts @@ -0,0 +1,3 @@ +export function* waitForFetchEnvironments() { + yield true; +} diff --git a/app/client/src/ce/selectors/environmentSelectors.tsx b/app/client/src/ce/selectors/environmentSelectors.tsx index a8ba79fee5..d4c7453b8b 100644 --- a/app/client/src/ce/selectors/environmentSelectors.tsx +++ b/app/client/src/ce/selectors/environmentSelectors.tsx @@ -1,5 +1,19 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import type { AppState } from "@appsmith/reducers"; -// eslint-disable-next-line @typescript-eslint/no-unused-vars export const areEnvironmentsFetched = (state: AppState, workspaceId: string) => true; + +export const getDefaultEnvironmentId = (state: AppState) => "unused_env"; + +export const getCurrentEnvironmentId = (state: AppState) => "unused_env"; + +export const getCurrentEnvironmentName = (state: AppState) => ""; + +export const getCurrentEditingEnvironmentId = (state: AppState) => "unused_env"; + +export const getCurrentEnvironmentDetails = (state: AppState) => ({ + id: "unused_env", + name: "", + editingId: "unused_env", +}); diff --git a/app/client/src/ce/utils/Environments/index.tsx b/app/client/src/ce/utils/Environments/index.tsx index 92c5ce2465..64d1de2013 100644 --- a/app/client/src/ce/utils/Environments/index.tsx +++ b/app/client/src/ce/utils/Environments/index.tsx @@ -7,27 +7,11 @@ export const getUserPreferenceFromStorage = () => { return "true"; }; -export const getCurrentEditingEnvID = () => { - // Get the values of environment ID being edited - return getCurrentEnvironment(); -}; - -// function to get the current environment from the URL -export const getCurrentEnvironment = () => { - return "unused_env"; -}; - -// function to get the current environment from the URL -export const getCurrentEnvName = () => { - return ""; -}; - // function to check if the datasource is created for the current environment export const isStorageEnvironmentCreated = ( datasource: Datasource | null, - environment?: string, + environment: string, ) => { - !environment && (environment = getCurrentEnvironment()); return ( !!datasource && datasource.hasOwnProperty("datasourceStorages") && @@ -43,9 +27,8 @@ export const isStorageEnvironmentCreated = ( // function to check if the datasource is configured for the current environment export const isEnvironmentConfigured = ( datasource: Datasource | null, - environment?: string, + environment: string, ) => { - !environment && (environment = getCurrentEnvironment()); const isConfigured = !!datasource && !!datasource.datasourceStorages && @@ -54,11 +37,7 @@ export const isEnvironmentConfigured = ( }; // function to check if the datasource is configured for any environment -export const doesAnyDsConfigExist = ( - datasource: Datasource | null, - environment?: string, -) => { - !environment && (environment = getCurrentEnvironment()); +export const doesAnyDsConfigExist = (datasource: Datasource | null) => { let isConfigured = false; if (!!datasource && !!datasource.datasourceStorages) { const envsList = Object.keys(datasource.datasourceStorages); @@ -76,9 +55,8 @@ export const doesAnyDsConfigExist = ( // function to check if the datasource is valid for the current environment export const isEnvironmentValid = ( datasource: Datasource | null, - environment?: string, + environment: string, ) => { - !environment && (environment = getCurrentEnvironment()); const isValid = datasource && datasource.datasourceStorages && @@ -86,16 +64,12 @@ export const isEnvironmentValid = ( return isValid ? isValid : false; }; -export const onUpdateFilterSuccess = (id: string) => { - return id; -}; - /* * Functiont to check get the datasource configuration for current ENV */ export const getEnvironmentConfiguration = ( datasource: Datasource | null, - environment = getCurrentEnvironment(), + environment: string, ) => { return datasource?.datasourceStorages?.[environment]?.datasourceConfiguration; }; diff --git a/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/CommonControls/DatasourceDropdown/useDatasource.tsx b/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/CommonControls/DatasourceDropdown/useDatasource.tsx index 2a7707b6cb..587225493b 100644 --- a/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/CommonControls/DatasourceDropdown/useDatasource.tsx +++ b/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/CommonControls/DatasourceDropdown/useDatasource.tsx @@ -37,12 +37,12 @@ import type { AppState } from "@appsmith/reducers"; import { DatasourceCreateEntryPoints } from "constants/Datasource"; import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors"; import { - getCurrentEnvironment, getEnvironmentConfiguration, isEnvironmentValid, } from "@appsmith/utils/Environments"; import type { ActionDataState } from "reducers/entityReducers/actionsReducer"; import { getDatatype } from "utils/AppsmithUtils"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; enum SortingWeights { alphabetical = 1, @@ -131,6 +131,7 @@ export function useDatasource(searchText: string) { const plugins = useSelector(getPlugins); const workspaceId = useSelector(getCurrentWorkspaceId); + const currentEnvironment: string = useSelector(getCurrentEnvironmentId); const [actualDatasourceOptions, mockDatasourceOptions] = useMemo(() => { const availableDatasources = datasources.filter(({ pluginId }) => @@ -147,12 +148,12 @@ export function useDatasource(searchText: string) { value: datasource.name, data: { pluginId: datasource.pluginId, - isValid: isEnvironmentValid(datasource, getCurrentEnvironment()), + isValid: isEnvironmentValid(datasource, currentEnvironment), pluginPackageName: pluginsPackageNamesMap[datasource.pluginId], isSample: false, connectionMode: getEnvironmentConfiguration( datasource, - getCurrentEnvironment(), + currentEnvironment, )?.connection?.mode, }, icon: ( diff --git a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx index 4f3ac47ad4..f0a946dd2a 100644 --- a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx +++ b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @@ -54,12 +54,10 @@ import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import LazyCodeEditor from "components/editorComponents/LazyCodeEditor"; import { getCodeMirrorNamespaceFromEditor } from "utils/getCodeMirrorNamespace"; import { isDynamicValue } from "utils/DynamicBindingUtils"; -import { - getCurrentEnvironment, - isEnvironmentValid, -} from "@appsmith/utils/Environments"; +import { isEnvironmentValid } from "@appsmith/utils/Environments"; import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants"; import { isString } from "lodash"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; type ReduxStateProps = { workspaceId: string; @@ -590,7 +588,7 @@ const mapStateToProps = ( const datasourceFromAction = apiFormValueSelector(state, "datasource"); let datasourceMerged = datasourceFromAction || {}; let datasourceFromDataSourceList: Datasource | undefined; - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment = getCurrentEnvironmentId(state); // Todo: fix this properly later in #2164 if (datasourceFromAction && "id" in datasourceFromAction) { datasourceFromDataSourceList = getDatasource( diff --git a/app/client/src/components/formControls/utils.ts b/app/client/src/components/formControls/utils.ts index 389fb6a667..6b8135f427 100644 --- a/app/client/src/components/formControls/utils.ts +++ b/app/client/src/components/formControls/utils.ts @@ -19,7 +19,6 @@ import { createMessage, } from "@appsmith/constants/messages"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; -import { getCurrentEditingEnvID } from "@appsmith/utils/Environments"; // This function checks if the form is dirty // We needed this in the cases where datasources are created from APIs and the initial value @@ -29,11 +28,12 @@ export const getIsFormDirty = ( formData: any, isNewDatasource: boolean, isRestPlugin: boolean, + currentEditingEnvId: string, ) => { const url = isRestPlugin ? get( formData, - `datastoreStorages.${getCurrentEditingEnvID}.datasourceConfiguration.url`, + `datastoreStorages.${currentEditingEnvId}.datasourceConfiguration.url`, "", ) : ""; diff --git a/app/client/src/ee/sagas/EnvironmentSagas.ts b/app/client/src/ee/sagas/EnvironmentSagas.ts new file mode 100644 index 0000000000..9eed998dc6 --- /dev/null +++ b/app/client/src/ee/sagas/EnvironmentSagas.ts @@ -0,0 +1 @@ +export * from "ce/sagas/EnvironmentSagas"; diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts index 24c5d65c3c..7b518ec235 100644 --- a/app/client/src/entities/Engine/AppEditorEngine.ts +++ b/app/client/src/entities/Engine/AppEditorEngine.ts @@ -65,6 +65,7 @@ import { isAirgapped } from "@appsmith/utils/airgapHelpers"; import { getAIPromptTriggered } from "utils/storage"; import { trackOpenEditorTabs } from "../../utils/editor/browserTabsTracking"; import { EditorModes } from "components/editorComponents/CodeEditor/EditorConfig"; +import { waitForFetchEnvironments } from "@appsmith/sagas/EnvironmentSagas"; export default class AppEditorEngine extends AppEngine { constructor(mode: APP_MODE) { @@ -149,6 +150,7 @@ export default class AppEditorEngine extends AppEngine { yield call(waitForFetchUserSuccess); yield call(waitForSegmentInit, true); + yield call(waitForFetchEnvironments); yield put(fetchAllPageEntityCompletion([executePageLoadActions()])); } diff --git a/app/client/src/entities/Engine/AppViewerEngine.ts b/app/client/src/entities/Engine/AppViewerEngine.ts index 7bb0224ed3..bfa4d02bad 100644 --- a/app/client/src/entities/Engine/AppViewerEngine.ts +++ b/app/client/src/entities/Engine/AppViewerEngine.ts @@ -33,6 +33,7 @@ import { waitForSegmentInit, waitForFetchUserSuccess, } from "@appsmith/sagas/userSagas"; +import { waitForFetchEnvironments } from "@appsmith/sagas/EnvironmentSagas"; export default class AppViewerEngine extends AppEngine { constructor(mode: APP_MODE) { @@ -119,6 +120,7 @@ export default class AppViewerEngine extends AppEngine { yield call(waitForFetchUserSuccess); yield call(waitForSegmentInit, true); + yield call(waitForFetchEnvironments); yield put(fetchAllPageEntityCompletion([executePageLoadActions()])); } } diff --git a/app/client/src/pages/Editor/APIEditor/ApiAuthentication.tsx b/app/client/src/pages/Editor/APIEditor/ApiAuthentication.tsx index a875e4fea0..9ca2be99d5 100644 --- a/app/client/src/pages/Editor/APIEditor/ApiAuthentication.tsx +++ b/app/client/src/pages/Editor/APIEditor/ApiAuthentication.tsx @@ -20,7 +20,7 @@ import { hasManageDatasourcePermission, } from "@appsmith/utils/permissionHelpers"; import { Icon, Text } from "design-system"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; interface ReduxStateProps { datasource: EmbeddedRestDatasource; } @@ -129,7 +129,7 @@ function ApiAuthentication(props: Props): JSX.Element { const mapStateToProps = (state: AppState, ownProps: any): ReduxStateProps => { const apiFormValueSelector = formValueSelector(ownProps.formName); const datasourceFromAction = apiFormValueSelector(state, "datasource"); - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment = getCurrentEnvironmentId(state); let datasourceMerged: EmbeddedRestDatasource = datasourceFromAction; if (datasourceFromAction && "id" in datasourceFromAction) { const datasourceFromDataSourceList = state.entities.datasources.list.find( diff --git a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx index 64cdc98ccb..0186f7e9d6 100644 --- a/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx +++ b/app/client/src/pages/Editor/APIEditor/ApiRightPane.tsx @@ -17,7 +17,7 @@ import isUndefined from "lodash/isUndefined"; import { Button, Tab, TabPanel, Tabs, TabsList, Tag } from "design-system"; import { DatasourceStructureContext } from "../Explorer/Datasources/DatasourceStructureContainer"; import type { Datasource } from "entities/Datasource"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const EmptyDatasourceContainer = styled.div` display: flex; @@ -189,7 +189,7 @@ function ApiRightPane(props: any) { const dispatch = useDispatch(); const { hasDependencies } = useEntityDependencies(props.actionName); const selectedTab = useSelector(getApiRightPaneSelectedTab); - const currentEnvironmentId = getCurrentEnvironment(); + const currentEnvironmentId = useSelector(getCurrentEnvironmentId); const setSelectedTab = useCallback((selectedIndex: string) => { dispatch(setApiRightPaneSelectedTab(selectedIndex)); diff --git a/app/client/src/pages/Editor/APIEditor/RestAPIForm.tsx b/app/client/src/pages/Editor/APIEditor/RestAPIForm.tsx index 2beffe8c0a..92deb7b850 100644 --- a/app/client/src/pages/Editor/APIEditor/RestAPIForm.tsx +++ b/app/client/src/pages/Editor/APIEditor/RestAPIForm.tsx @@ -23,7 +23,7 @@ import { isEmpty } from "lodash"; import type { CommonFormProps } from "./CommonEditorForm"; import CommonEditorForm from "./CommonEditorForm"; import Pagination from "./Pagination"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const NoBodyMessage = styled.div` margin-top: 20px; @@ -101,7 +101,7 @@ export default connect((state: AppState, props: { pluginId: string }) => { // get messages from action itself const actionId = selector(state, "id"); const action = getAction(state, actionId); - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment = getCurrentEnvironmentId(state); const hintMessages = action?.messages; const datasourceHeaders = diff --git a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx index 4f3ef6331a..b4d25e33f9 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx @@ -28,6 +28,7 @@ import { } from "@appsmith/constants/messages"; import { isEnvironmentValid } from "@appsmith/utils/Environments"; import { setDatasourceViewModeFlag } from "actions/datasourceActions"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const { cloudHosting } = getAppsmithConfigs(); @@ -222,7 +223,9 @@ const mapStateToProps = (state: AppState, props: any) => { const hintMessages = datasource && datasource.messages; - const isDatasourceValid = isEnvironmentValid(datasource) || false; + const currentEnvironmentId = getCurrentEnvironmentId(state); + const isDatasourceValid = + isEnvironmentValid(datasource, currentEnvironmentId) || false; return { messages: hintMessages, diff --git a/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx b/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx index af541950c1..8f9d478d5a 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx @@ -8,14 +8,12 @@ import { ComparisonOperationsEnum } from "components/formControls/BaseControl"; import type { AppState } from "@appsmith/reducers"; import { connect } from "react-redux"; import { datasourceEnvEnabled } from "@appsmith/selectors/featureFlagsSelectors"; -import { - DB_NOT_SUPPORTED, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; +import { DB_NOT_SUPPORTED } from "@appsmith/utils/Environments"; import { getPlugin } from "selectors/entitiesSelector"; import type { PluginType } from "entities/Action"; import { getDefaultEnvId } from "@appsmith/api/ApiUtils"; import { EnvConfigSection } from "@appsmith/components/EnvConfigSection"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const Key = styled.div` color: var(--ads-v2-color-fg-muted); @@ -259,8 +257,9 @@ const mapStateToProps = (state: AppState, ownProps: any) => { const isEnvEnabled = DB_NOT_SUPPORTED.includes(pluginType as PluginType) ? false : datasourceEnvEnabled(state); + const currentEnvironmentId = getCurrentEnvironmentId(state); return { - currentEnv: isEnvEnabled ? getCurrentEnvironment() : getDefaultEnvId(), + currentEnv: isEnvEnabled ? currentEnvironmentId : getDefaultEnvId(), isEnvEnabled, }; }; diff --git a/app/client/src/pages/Editor/DataSourceEditor/NewActionButton.tsx b/app/client/src/pages/Editor/DataSourceEditor/NewActionButton.tsx index f2db296646..d13ab3bc34 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/NewActionButton.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/NewActionButton.tsx @@ -13,7 +13,7 @@ import { getCurrentPageId } from "selectors/editorSelectors"; import type { Datasource } from "entities/Datasource"; import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes"; import { noop } from "utils/AppsmithUtils"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import WalkthroughContext from "components/featureWalkthrough/walkthroughContext"; import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; import { getFeatureWalkthroughShown } from "utils/storage"; @@ -39,7 +39,7 @@ function NewActionButton(props: NewActionButtonProps) { const dispatch = useDispatch(); const actionExist = useSelector(actionsExistInCurrentPage); const currentPageId = useSelector(getCurrentPageId); - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment = useSelector(getCurrentEnvironmentId); const signpostingEnabled = useSelector(getIsFirstTimeUserOnboardingEnabled); const adapativeSignposting = useSelector(adaptiveSignpostingEnabled); diff --git a/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx index a3d6c1c5c2..2daa8245fc 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx @@ -42,10 +42,6 @@ import { ENTITY_TYPE } from "entities/AppsmithConsole"; import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { hasManageDatasourcePermission } from "@appsmith/utils/permissionHelpers"; import { Form } from "./DBForm"; -import { - getCurrentEnvName, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; interface DatasourceRestApiEditorProps { initializeReplayEntity: (id: string, data: any) => void; @@ -55,6 +51,7 @@ interface DatasourceRestApiEditorProps { onSuccess?: ReduxAction, ) => void; currentEnvironment: string; + currentEnvironmentName: string; isSaving: boolean; applicationId: string; datasourceId: string; @@ -204,7 +201,11 @@ class DatasourceRestAPIEditor extends React.Component { }; getSanitizedFormData = () => - formValuesToDatasource(this.props.datasource, this.props.formData); + formValuesToDatasource( + this.props.datasource, + this.props.formData, + this.props.currentEnvironment, + ); save = (onSuccess?: ReduxAction) => { this.props.toggleSaveActionFlag(true); @@ -213,8 +214,8 @@ class DatasourceRestAPIEditor extends React.Component { AnalyticsUtil.logEvent("SAVE_DATA_SOURCE_CLICK", { pageId: this.props.pageId, appId: this.props.applicationId, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: this.props.currentEnvironment, + environmentName: this.props.currentEnvironmentName, pluginName: this.props.pluginName || "", pluginPackageName: this.props.pluginPackageName || "", }); @@ -1035,11 +1036,11 @@ class DatasourceRestAPIEditor extends React.Component { } const mapStateToProps = (state: AppState, props: any) => { - const { datasource, formName } = props; + const { currentEnvironment, datasource, formName } = props; const hintMessages = datasource && datasource.messages; return { - initialValues: datasourceToFormValues(datasource), + initialValues: datasourceToFormValues(datasource, currentEnvironment), formMeta: getFormMeta(formName)(state), messages: hintMessages, datasourceName: datasource?.name ?? "", diff --git a/app/client/src/pages/Editor/DataSourceEditor/index.tsx b/app/client/src/pages/Editor/DataSourceEditor/index.tsx index b5a0cecab9..2ae1bd43a9 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/index.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/index.tsx @@ -90,15 +90,14 @@ import type { PluginType } from "entities/Action"; import { PluginPackageName } from "entities/Action"; import DSDataFilter from "@appsmith/components/DSDataFilter"; import { DEFAULT_ENV_ID } from "@appsmith/api/ApiUtils"; -import { - isStorageEnvironmentCreated, - onUpdateFilterSuccess, -} from "@appsmith/utils/Environments"; +import { isStorageEnvironmentCreated } from "@appsmith/utils/Environments"; import type { CalloutKind } from "design-system"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors"; import AnalyticsUtil from "utils/AnalyticsUtil"; import { DATASOURCES_ALLOWED_FOR_PREVIEW_MODE } from "constants/QueryEditorConstants"; +import { setCurrentEditingEnvironmentID } from "@appsmith/actions/environmentAction"; +import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors"; interface ReduxStateProps { canCreateDatasourceActions: boolean; @@ -215,6 +214,7 @@ export interface DatasourcePaneFunctions { resetForm: (formName: string) => void; initializeFormWithDefaults: (pluginType: string) => void; datasourceDiscardAction: (pluginId: string) => void; + setCurrentEditingEnvironmentID: (id: string) => void; } class DatasourceEditorRouter extends React.Component { @@ -508,28 +508,33 @@ class DatasourceEditorRouter extends React.Component { } updateFilter = (id: string, name: string, userPermissions: string[]) => { - if (id.length > 0 && this.state.filterParams.id !== id) { - if ( - !isEmpty(this.props.formData) && - this.props.isFormDirty && - this.state.filterParams.id.length > 0 - ) { - this.setState({ - showDialog: true, - switchFilterBlocked: true, - navigation: () => { - this.updateFilterSuccess(id, name, userPermissions); - }, - }); - return false; - } else { - this.props.resetForm(this.props.formName); + if (id.length > 0) { + if (!this.props.viewMode) { + this.props.setCurrentEditingEnvironmentID(id); + } + if (this.state.filterParams.id !== id) { + if ( + !isEmpty(this.props.formData) && + this.props.isFormDirty && + this.state.filterParams.id.length > 0 + ) { + this.setState({ + showDialog: true, + switchFilterBlocked: true, + navigation: () => { + this.updateFilterSuccess(id, name, userPermissions); + }, + }); + return false; + } else { + this.props.resetForm(this.props.formName); + } + return this.updateFilterSuccess(id, name, userPermissions); + } else if ( + !isStorageEnvironmentCreated(this.props.formData as Datasource, id) + ) { + return this.updateFilterSuccess(id, name, userPermissions); } - return this.updateFilterSuccess(id, name, userPermissions); - } else if ( - !isStorageEnvironmentCreated(this.props.formData as Datasource, id) - ) { - return this.updateFilterSuccess(id, name, userPermissions); } return true; }; @@ -539,7 +544,6 @@ class DatasourceEditorRouter extends React.Component { name: string, userPermissions: string[], ) => { - onUpdateFilterSuccess(id); const { datasourceStorages } = this.props.datasource as Datasource; // check all datasource storages and remove the ones which do not have an id object const datasourceStoragesWithId = Object.keys(datasourceStorages).reduce( @@ -706,6 +710,7 @@ class DatasourceEditorRouter extends React.Component { { return formValuesToDatasource( this.props.datasource as Datasource, this.props.formData as ApiDatasourceForm, + this.state.filterParams.id, ); else return getTrimmedData({ @@ -945,11 +951,13 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => { const isNewDatasource = datasourcePane.newDatasource === TEMP_DATASOURCE_ID; const pluginDatasourceForm = plugin?.datasourceComponent ?? DatasourceComponentTypes.AutoForm; + const currentEnvDetails = getCurrentEnvironmentDetails(state); const isFormDirty = getIsFormDirty( isDirty(formName)(state), formData, isNewDatasource, pluginDatasourceForm === DatasourceComponentTypes.RestAPIDatasourceForm, + currentEnvDetails.editingId, ); const initialValue = getFormInitialValues(formName)(state) as | Datasource @@ -979,7 +987,11 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => { const isPluginAuthorized = pluginPackageName === PluginPackageName.GOOGLE_SHEETS ? plugin && - isDatasourceAuthorizedForQueryCreation(formData as Datasource, plugin) + isDatasourceAuthorizedForQueryCreation( + formData as Datasource, + plugin, + currentEnvDetails.id, + ) : true; const datasourceButtonConfiguration = getDatasourceFormButtonConfig( @@ -1064,6 +1076,8 @@ const mapDispatchToProps = ( dispatch(initializeDatasourceFormDefaults(pluginType)), datasourceDiscardAction: (pluginId) => dispatch(datasourceDiscardAction(pluginId)), + setCurrentEditingEnvironmentID: (id: string) => + dispatch(setCurrentEditingEnvironmentID(id)), }); export default connect( diff --git a/app/client/src/pages/Editor/FormControl.tsx b/app/client/src/pages/Editor/FormControl.tsx index cbf7def2a3..1aa5d09546 100644 --- a/app/client/src/pages/Editor/FormControl.tsx +++ b/app/client/src/pages/Editor/FormControl.tsx @@ -29,8 +29,8 @@ import { get } from "lodash"; import { SQL_PLUGINS_DEFAULT_TEMPLATE_TYPE } from "constants/Datasource"; import TemplateMenu from "./QueryEditor/TemplateMenu"; import { SQL_DATASOURCES } from "../../constants/QueryEditorConstants"; -import { getCurrentEditingEnvID } from "@appsmith/utils/Environments"; import type { Datasource, DatasourceStructure } from "entities/Datasource"; +import { getCurrentEditingEnvironmentId } from "@appsmith/selectors/environmentSelectors"; export interface FormControlProps { config: ControlProps; @@ -47,6 +47,7 @@ function FormControl(props: FormControlProps) { ); const dispatch = useDispatch(); + const currentEditingEnvId = useSelector(getCurrentEditingEnvironmentId); // adding this to prevent excessive rerendering const [convertFormToRaw, setConvertFormToRaw] = useState(false); @@ -55,7 +56,7 @@ function FormControl(props: FormControlProps) { let formValueForEvaluatingHiddenObj = formValues; if (!!formValues && formValues.hasOwnProperty("datasourceStorages")) { formValueForEvaluatingHiddenObj = (formValues as Datasource) - .datasourceStorages[getCurrentEditingEnvID()]; + .datasourceStorages[currentEditingEnvId]; } const hidden = isHidden(formValueForEvaluatingHiddenObj, props.config.hidden); const configErrors: EvaluationError[] = useSelector( diff --git a/app/client/src/pages/Editor/GeneratePage/components/GeneratePageForm/hooks.ts b/app/client/src/pages/Editor/GeneratePage/components/GeneratePageForm/hooks.ts index df33947864..2a76a2bc53 100644 --- a/app/client/src/pages/Editor/GeneratePage/components/GeneratePageForm/hooks.ts +++ b/app/client/src/pages/Editor/GeneratePage/components/GeneratePageForm/hooks.ts @@ -6,9 +6,9 @@ import { CONNECT_NEW_DATASOURCE_OPTION_ID } from "../DataSourceOption"; import type { executeDatasourceQuerySuccessPayload } from "actions/datasourceActions"; import { executeDatasourceQuery } from "actions/datasourceActions"; import type { DropdownOption } from "design-system-old"; -import { useDispatch } from "react-redux"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; +import { useDispatch, useSelector } from "react-redux"; import { PluginPackageName } from "entities/Action"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; export const FAKE_DATASOURCE_OPTION = { CONNECT_NEW_DATASOURCE_OPTION: { @@ -35,7 +35,7 @@ export const useDatasourceOptions = ({ const [dataSourceOptions, setDataSourceOptions] = useState( [], ); - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment = useSelector(getCurrentEnvironmentId); useEffect(() => { // On mount of component and on change of datasources, Update the list. diff --git a/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx b/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx index c6b7fa3798..c20918b041 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx @@ -48,11 +48,11 @@ import { MenuWrapper, StyledMenu } from "components/utils/formComponents"; import { DatasourceEditEntryPoints } from "constants/Datasource"; import { isEnvironmentConfigured, - getCurrentEnvironment, doesAnyDsConfigExist, DB_NOT_SUPPORTED, } from "@appsmith/utils/Environments"; import { getCurrentApplication } from "@appsmith/selectors/applicationSelectors"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const Wrapper = styled.div` padding: 15px; @@ -202,7 +202,7 @@ function DatasourceCard(props: DatasourceCardProps) { datasourceFormConfigs[datasource?.pluginId ?? ""]; const QUERY = queriesWithThisDatasource > 1 ? "queries" : "query"; - const currentEnv = getCurrentEnvironment(); + const currentEnv = useSelector(getCurrentEnvironmentId); const editDatasource = useCallback(() => { AnalyticsUtil.logEvent("DATASOURCE_CARD_EDIT_ACTION"); @@ -264,6 +264,7 @@ function DatasourceCard(props: DatasourceCardProps) { const isDSAuthorizedForQueryCreation = isDatasourceAuthorizedForQueryCreation( datasource, plugin, + currentEnv, ); const showReconnectButton = !( @@ -272,7 +273,7 @@ function DatasourceCard(props: DatasourceCardProps) { ); const showCreateNewActionButton = envSupportedDs - ? doesAnyDsConfigExist(datasource, currentEnv) + ? doesAnyDsConfigExist(datasource) : true; return ( diff --git a/app/client/src/pages/Editor/QueryEditor/index.tsx b/app/client/src/pages/Editor/QueryEditor/index.tsx index 8776f9ea27..473e42fbce 100644 --- a/app/client/src/pages/Editor/QueryEditor/index.tsx +++ b/app/client/src/pages/Editor/QueryEditor/index.tsx @@ -50,10 +50,7 @@ import { getConfigInitialValues } from "components/formControls/utils"; import { merge } from "lodash"; import { getPathAndValueFromActionDiffObject } from "../../../utils/getPathAndValueFromActionDiffObject"; import { DatasourceCreateEntryPoints } from "constants/Datasource"; -import { - getCurrentEnvName, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors"; const EmptyStateContainer = styled.div` display: flex; @@ -106,6 +103,8 @@ type ReduxStateProps = { actionObjectDiff?: any; isSaas: boolean; datasourceId?: string; + currentEnvironmentId: string; + currentEnvironmentName: string; }; type StateAndRouteProps = RouteComponentProps; @@ -167,8 +166,8 @@ class QueryEditor extends React.Component { AnalyticsUtil.logEvent("RUN_QUERY_CLICK", { actionId: this.props.actionId, dataSourceSize: dataSources.length, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: this.props.currentEnvironmentId, + environmentName: this.props.currentEnvironmentName, pluginName: pluginName, datasourceId: datasource?.id, isMock: !!datasource?.isMock, @@ -330,8 +329,12 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => { let uiComponent = UIComponentTypes.DbEditorForm; if (!!pluginId) uiComponent = getUIComponent(pluginId, allPlugins); + const currentEnvDetails = getCurrentEnvironmentDetails(state); + return { actionId, + currentEnvironmentId: currentEnvDetails?.id || "", + currentEnvironmentName: currentEnvDetails?.name || "", pluginId, plugins: allPlugins, runErrorMessage, diff --git a/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx b/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx index 3a3baaf64a..e792d8f274 100644 --- a/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx +++ b/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx @@ -79,7 +79,6 @@ import Debugger, { } from "../DataSourceEditor/Debugger"; import { showDebuggerFlag } from "selectors/debuggerSelectors"; import { Form, ViewModeWrapper } from "../DataSourceEditor/DBForm"; -import { getCurrentEditingEnvID } from "@appsmith/utils/Environments"; import DSDataFilter from "@appsmith/components/DSDataFilter"; import { DSEditorWrapper } from "../DataSourceEditor"; import type { DatasourceFilterState } from "../DataSourceEditor"; @@ -88,6 +87,7 @@ import GoogleSheetSchema from "./GoogleSheetSchema"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors"; import AnalyticsUtil from "utils/AnalyticsUtil"; +import { getDefaultEnvironmentId } from "@appsmith/selectors/environmentSelectors"; const ViewModeContainer = styled.div` display: flex; @@ -172,6 +172,7 @@ type State = { type SaasEditorWrappperProps = RouteProps & { hiddenHeader?: boolean; // for reconnect modal isInsideReconnectModal?: boolean; // for reconnect modal + currentEnvironment: string; }; type RouteProps = { datasourceId: string; @@ -182,7 +183,6 @@ type RouteProps = { type SaasEditorWrappperState = { requiredFields: Record; configDetails: Record; - currentEditingEnvironment: string; }; class SaasEditorWrapper extends React.Component< SaasEditorWrappperProps, @@ -193,7 +193,6 @@ class SaasEditorWrapper extends React.Component< this.state = { requiredFields: {}, configDetails: {}, - currentEditingEnvironment: getCurrentEditingEnvID(), }; } @@ -225,7 +224,6 @@ class SaasEditorWrapper extends React.Component< @@ -506,7 +504,11 @@ class DatasourceSaaSEditor extends JSONtoForm { if we want to extend this functionality for other plugins, we should be able to extend this function for other plugins */ - const authErrorMessage = getDatasourceErrorMessage(formData, plugin); + const authErrorMessage = getDatasourceErrorMessage( + formData, + plugin, + this.state.filterParams.id, + ); const googleSheetsInfoMessage = createMessage( GOOGLE_SHEETS_INFO_BANNER_MESSAGE, @@ -625,7 +627,7 @@ class DatasourceSaaSEditor extends JSONtoForm { {/* Render datasource form call-to-actions */} {datasource && ( { viewMode = viewModeFromURLParams === "true"; } + const { currentEnvironment } = props; + // Returning false to isPluginAuthorized if there exists no plugin or formdata. const isPluginAuthorized = !!plugin && !!formData ? isDatasourceAuthorizedForQueryCreation( formData, plugin, - getCurrentEditingEnvID(), + currentEnvironment, ) : false; @@ -757,7 +761,7 @@ const mapStateToProps = (state: AppState, props: any) => { ? isDatasourceAuthorizedForQueryCreation( formData, plugin, - getCurrentEditingEnvID(), + currentEnvironment, [ AuthenticationStatus.FAILURE, AuthenticationStatus.FAILURE_ACCESS_DENIED, @@ -845,4 +849,6 @@ const SaaSEditor = connect( })(DatasourceSaaSEditor), ); -export default SaasEditorWrapper; +export default connect((state) => ({ + currentEnvironment: getDefaultEnvironmentId(state), +}))(SaasEditorWrapper); diff --git a/app/client/src/pages/Editor/SaaSEditor/errorUtils.ts b/app/client/src/pages/Editor/SaaSEditor/errorUtils.ts index a7dca37bb7..b6701e3efe 100644 --- a/app/client/src/pages/Editor/SaaSEditor/errorUtils.ts +++ b/app/client/src/pages/Editor/SaaSEditor/errorUtils.ts @@ -10,7 +10,6 @@ import { import { getDatasourcePropertyValue } from "utils/editorContextUtils"; import { GOOGLE_SHEET_SPECIFIC_SHEETS_SCOPE } from "constants/Datasource"; import { PluginPackageName } from "entities/Action"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; import { get } from "lodash"; /** @@ -23,8 +22,8 @@ import { get } from "lodash"; export function isAuthorisedFilesEmptyGsheet( datasource: Datasource, propertyKey: string, + currentEnvironment: string, ): boolean { - const currentEnvironment = getCurrentEnvironment(); const value = get( datasource, `datasourceStorages.${currentEnvironment}.datasourceConfiguration.authentication.scopeString`, @@ -64,6 +63,7 @@ export function isAuthorisedFilesEmptyGsheet( export function getDatasourceErrorMessage( datasource: Datasource, plugin: Plugin | undefined, + currentEnvironment: string, ): string { if (!datasource) return ""; @@ -74,6 +74,7 @@ export function getDatasourceErrorMessage( const authorisedFilesEmptyGsheet = isAuthorisedFilesEmptyGsheet( datasource, createMessage(GSHEET_AUTHORISED_FILE_IDS_KEY), + currentEnvironment, ); authErrorMessage = authorisedFilesEmptyGsheet diff --git a/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx b/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx index 00b456303a..0e25819ed1 100644 --- a/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx +++ b/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx @@ -63,18 +63,17 @@ import { Button, Text, } from "design-system"; -import { - isEnvironmentConfigured, - getCurrentEnvironment, - getCurrentEnvName, -} from "@appsmith/utils/Environments"; +import { isEnvironmentConfigured } from "@appsmith/utils/Environments"; import { keyBy } from "lodash"; import type { Plugin } from "api/PluginApi"; import { isDatasourceAuthorizedForQueryCreation, isGoogleSheetPluginDS, } from "utils/editorContextUtils"; -import { areEnvironmentsFetched } from "@appsmith/selectors/environmentSelectors"; +import { + areEnvironmentsFetched, + getCurrentEnvironmentDetails, +} from "@appsmith/selectors/environmentSelectors"; import type { AppState } from "@appsmith/reducers"; const Section = styled.div` @@ -271,6 +270,7 @@ function ReconnectDatasourceModal() { ); // getting query from redirection url const userWorkspaces = useSelector(getUserApplicationsWorkspacesList); + const currentEnvDetails = useSelector(getCurrentEnvironmentDetails); const queryParams = useQuery(); const queryAppId = queryParams.get("appId") || (pendingApp ? pendingApp.appId : null); @@ -299,9 +299,13 @@ function ReconnectDatasourceModal() { if (!ds || pluginsArray.length === 0) return false; const plugin = plugins[ds.pluginId]; const output = isGoogleSheetPluginDS(plugin?.packageName) - ? isDatasourceAuthorizedForQueryCreation(ds, plugin as Plugin) + ? isDatasourceAuthorizedForQueryCreation( + ds, + plugin as Plugin, + currentEnvDetails.id, + ) : ds.datasourceStorages - ? isEnvironmentConfigured(ds, getCurrentEnvironment()) + ? isEnvironmentConfigured(ds, currentEnvDetails.id) : false; return output; }; @@ -320,8 +324,8 @@ function ReconnectDatasourceModal() { AnalyticsUtil.logEvent("DATASOURCE_AUTH_COMPLETE", { applicationId: queryAppId, datasourceId: queryDatasourceId, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, pageId: queryPageId, oAuthPassOrFailVerdict: status, workspaceId: orgId, @@ -524,6 +528,7 @@ function ReconnectDatasourceModal() { const mappedDataSources = datasources.map((ds: Datasource) => { return ( { diff --git a/app/client/src/pages/Editor/gitSync/components/DatasourceListItem.tsx b/app/client/src/pages/Editor/gitSync/components/DatasourceListItem.tsx index cc758b716d..558b7de21b 100644 --- a/app/client/src/pages/Editor/gitSync/components/DatasourceListItem.tsx +++ b/app/client/src/pages/Editor/gitSync/components/DatasourceListItem.tsx @@ -5,10 +5,7 @@ import type { Datasource } from "entities/Datasource"; import styled from "styled-components"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { PluginImage } from "pages/Editor/DataSourceEditor/DSFormHeader"; -import { - getCurrentEnvironment, - isEnvironmentConfigured, -} from "@appsmith/utils/Environments"; +import { isEnvironmentConfigured } from "@appsmith/utils/Environments"; import type { Plugin } from "api/PluginApi"; import { isDatasourceAuthorizedForQueryCreation, @@ -58,15 +55,20 @@ const DsTitle = styled.div` } `; function ListItemWrapper(props: { + currentEnvironment: string; ds: Datasource; selected?: boolean; plugin: Plugin; onClick: (ds: Datasource) => void; }) { - const { ds, onClick, plugin, selected } = props; + const { currentEnvironment, ds, onClick, plugin, selected } = props; const isPluginAuthorized = isGoogleSheetPluginDS(plugin?.packageName) - ? isDatasourceAuthorizedForQueryCreation(ds, plugin ?? {}) - : isEnvironmentConfigured(ds, getCurrentEnvironment()); + ? isDatasourceAuthorizedForQueryCreation( + ds, + plugin ?? {}, + currentEnvironment, + ) + : isEnvironmentConfigured(ds, currentEnvironment); return ( ( yield select(getAction, actionId), `action not found for id - ${actionId}`, @@ -897,7 +905,7 @@ function* runActionSaga( id: actionId, iconId: actionObject.pluginId, logType: LOG_TYPE.ACTION_EXECUTION_ERROR, - environmentName: getCurrentEnvName() || "", + environmentName: currentEnvDetails.name, text: `Execution failed${ payload.statusCode ? ` with status ${payload.statusCode}` : "" }`, @@ -933,8 +941,8 @@ function* runActionSaga( AnalyticsUtil.logEvent(failureEventName, { actionId, actionName: actionObject.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, pageName: pageName, apiType: "INTERNAL", datasourceId: datasource?.id, @@ -956,8 +964,8 @@ function* runActionSaga( AnalyticsUtil.logEvent(eventName, { actionId, actionName: actionObject.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, pageName: pageName, responseTime: payload.duration, apiType: "INTERNAL", @@ -1061,6 +1069,9 @@ function* executeOnPageLoadJSAction(pageAction: PageAction) { } function* executePageLoadAction(pageAction: PageAction) { + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); if (pageAction.hasOwnProperty("collectionId")) { yield call(executeOnPageLoadJSAction, pageAction); } else { @@ -1086,8 +1097,8 @@ function* executePageLoadAction(pageAction: PageAction) { appId: currentApp.id, onPageLoad: true, appName: currentApp.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, isExampleApp: currentApp.appIsExample, pluginName: plugin?.name, datasourceId: datasourceId, @@ -1130,7 +1141,7 @@ function* executePageLoadAction(pageAction: PageAction) { id: pageAction.id, iconId: action.pluginId, logType: LOG_TYPE.ACTION_EXECUTION_ERROR, - environmentName: getCurrentEnvName() || "", + environmentName: currentEnvDetails.name, text: `Execution failed with status ${payload.statusCode}`, source: { type: ENTITY_TYPE.ACTION, @@ -1175,8 +1186,8 @@ function* executePageLoadAction(pageAction: PageAction) { appId: currentApp.id, onPageLoad: true, appName: currentApp.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, isExampleApp: currentApp.appIsExample, pluginName: plugin?.name, datasourceId: datasourceId, @@ -1194,8 +1205,8 @@ function* executePageLoadAction(pageAction: PageAction) { appId: currentApp.id, onPageLoad: true, appName: currentApp.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, isExampleApp: currentApp.appIsExample, pluginName: plugin?.name, datasourceId: datasourceId, @@ -1527,7 +1538,8 @@ function* softRefreshActionsSaga() { if (isQueryPane) { yield put(changeQuery(isQueryPane.params.queryId)); } - toast.show(createMessage(SWITCH_ENVIRONMENT_SUCCESS, getCurrentEnvName()), { + const currentEnvName: string = yield select(getCurrentEnvironmentName); + toast.show(createMessage(SWITCH_ENVIRONMENT_SUCCESS, currentEnvName), { kind: "success", }); } diff --git a/app/client/src/sagas/DatasourcesSagas.ts b/app/client/src/sagas/DatasourcesSagas.ts index 209defa27b..e7e3f3e1e7 100644 --- a/app/client/src/sagas/DatasourcesSagas.ts +++ b/app/client/src/sagas/DatasourcesSagas.ts @@ -146,11 +146,6 @@ import { toast } from "design-system"; import { fetchPluginFormConfig } from "actions/pluginActions"; import { addClassToDocumentRoot } from "pages/utils"; import { AuthorizationStatus } from "pages/common/datasourceAuth"; -import { - getCurrentEditingEnvID, - getCurrentEnvName, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; import { getFormDiffPaths, getFormName, @@ -160,6 +155,10 @@ import { getDefaultEnvId } from "@appsmith/api/ApiUtils"; import type { DatasourceStructureContext } from "pages/Editor/Explorer/Datasources/DatasourceStructureContainer"; import { MAX_DATASOURCE_SUGGESTIONS } from "pages/Editor/Explorer/hooks"; import { klona } from "klona/lite"; +import { + getCurrentEditingEnvironmentId, + getCurrentEnvironmentDetails, +} from "@appsmith/selectors/environmentSelectors"; function* fetchDatasourcesSaga( action: ReduxAction<{ workspaceId?: string } | undefined>, @@ -434,9 +433,12 @@ function* updateDatasourceSaga( >, ) { try { + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); const queryParams = getQueryParams(); const currentEnvironment = - actionPayload.payload?.currEditingEnvId || getCurrentEnvironment(); + actionPayload.payload?.currEditingEnvId || currentEnvDetails.id; const datasourcePayload = omit(actionPayload.payload, "name"); const datasourceStoragePayload = datasourcePayload.datasourceStorages[currentEnvironment]; @@ -510,7 +512,7 @@ function* updateDatasourceSaga( datasourceId: responseData?.id, datasourceName: responseData.name, environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentName: currentEnvDetails.name, pluginName: plugin?.name || "", pluginPackageName: plugin?.packageName || "", isFormValid: isFormValid, @@ -596,7 +598,10 @@ function* redirectAuthorizationCodeSaga( const isImport: string = yield select(getWorkspaceIdForImport); if (pluginType === PluginType.API) { - window.location.href = `/api/v1/datasources/${datasourceId}/pages/${pageId}/code?environmentId=${getCurrentEditingEnvID()}`; + const currentEnvironment: string = yield select( + getCurrentEditingEnvironmentId, + ); + window.location.href = `/api/v1/datasources/${datasourceId}/pages/${pageId}/code?environmentId=${currentEnvironment}`; } else { try { // Get an "appsmith token" from the server @@ -666,11 +671,14 @@ function* getOAuthAccessTokenSaga( }, }); } else { + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); AnalyticsUtil.logEvent("DATASOURCE_AUTH_COMPLETE", { applicationId: applicationId, datasourceId: datasourceId, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, pageId: pageId, oAuthPassOrFailVerdict: "success", workspaceId: response.data.datasource?.workspaceId, @@ -743,7 +751,9 @@ function* testDatasourceSaga(actionPayload: ReduxAction) { yield select(getDatasource, actionPayload.payload.id), `Datasource not found for id - ${actionPayload.payload.id}`, ); - const currentEnvironment = getCurrentEditingEnvID(); + const currentEnvironment: string = yield select( + getCurrentEditingEnvironmentId, + ); const payload = { ...actionPayload.payload, id: actionPayload.payload.id as any, @@ -767,6 +777,9 @@ function* testDatasourceSaga(actionPayload: ReduxAction) { }; } + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); try { const response: ApiResponse = yield DatasourcesApi.testDatasource( @@ -790,7 +803,7 @@ function* testDatasourceSaga(actionPayload: ReduxAction) { AnalyticsUtil.logEvent("TEST_DATA_SOURCE_FAILED", { datasoureId: datasource?.id, environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentName: currentEnvDetails.name, pluginName: plugin?.name, errorMessages: responseData.invalids, messages: responseData.messages, @@ -828,7 +841,7 @@ function* testDatasourceSaga(actionPayload: ReduxAction) { datasourceName: payload.name, datasoureId: datasource?.id, environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentName: currentEnvDetails.name, pluginName: plugin?.name, }); toast.show(createMessage(DATASOURCE_VALID, payload.name), { @@ -861,7 +874,7 @@ function* testDatasourceSaga(actionPayload: ReduxAction) { AnalyticsUtil.logEvent("TEST_DATA_SOURCE_FAILED", { datasoureId: datasource?.id, environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentName: currentEnvDetails.name, pluginName: plugin?.name, errorMessages: (error as any)?.message, }); @@ -962,7 +975,9 @@ function* createDatasourceFromFormSaga( getPluginForm, actionPayload.payload.pluginId, ); - const currentEnvironment = getCurrentEditingEnvID(); + const currentEnvironment: string = yield select( + getCurrentEditingEnvironmentId, + ); const initialValues: unknown = yield call( getConfigInitialValues, @@ -1000,6 +1015,9 @@ function* createDatasourceFromFormSaga( workspaceId, }); const isValidResponse: boolean = yield validateResponse(response); + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); if (isValidResponse) { const plugin: Plugin = yield select(getPlugin, response?.data?.pluginId); const formName: string = getFormName(plugin); @@ -1014,7 +1032,7 @@ function* createDatasourceFromFormSaga( datasourceId: response?.data?.id, datasourceName: response?.data?.name, environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentName: currentEnvDetails.name, pluginName: plugin?.name || "", pluginPackageName: plugin?.packageName || "", isFormValid: isFormValid, @@ -1171,7 +1189,11 @@ function* storeAsDatasourceSaga() { let datasource = get(values, "datasource"); datasource = omit(datasource, ["name"]); const originalHeaders = get(values, "actionConfiguration.headers", []); - const currentEnvironment = getCurrentEnvironment(); + + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); + const currentEnvironment = currentEnvDetails.id; const [datasourceHeaders, actionHeaders] = partition( originalHeaders, ({ key, value }: { key: string; value: string }) => { @@ -1348,11 +1370,14 @@ function* fetchDatasourceStructureSaga( }, }); } + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); AnalyticsUtil.logEvent("DATASOURCE_SCHEMA_FETCH", { datasourceId: datasource?.id, pluginName: plugin?.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, errorMessage: errorMessage, isSuccess: isSuccess, source: action.payload.schemaFetchContext, @@ -1462,12 +1487,15 @@ function* refreshDatasourceStructure( }, }); } + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); AnalyticsUtil.logEvent("DATASOURCE_SCHEMA_FETCH", { datasourceId: datasource?.id, pluginName: plugin?.name, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, errorMessage: errorMessage, isSuccess: isSuccess, source: action.payload.schemaRefreshContext, @@ -1580,7 +1608,9 @@ function* filePickerActionCallbackSaga( const plugin: Plugin = yield select(getPlugin, datasource?.pluginId); const applicationId: string = yield select(getCurrentApplicationId); const pageId: string = yield select(getCurrentPageId); - const currentEnvironment = getCurrentEnvironment(); + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); // update authentication status based on whether files were picked or not const authStatus = @@ -1591,7 +1621,7 @@ function* filePickerActionCallbackSaga( // Once files are selected in case of import, set this flag set( datasource, - `datasourceStorages.${currentEnvironment}.datasourceConfiguration.authentication.authenticationStatus`, + `datasourceStorages.${currentEnvDetails.id}.datasourceConfiguration.authentication.authenticationStatus`, true, ); @@ -1600,8 +1630,8 @@ function* filePickerActionCallbackSaga( applicationId: applicationId, pageId: pageId, datasourceId: datasource?.id, - environmentId: currentEnvironment, - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, oAuthPassOrFailVerdict: authStatus === AuthenticationStatus.FAILURE_FILE_NOT_SELECTED ? createMessage(FILES_NOT_SELECTED_EVENT) @@ -1617,7 +1647,7 @@ function* filePickerActionCallbackSaga( // using the second index specifically for file ids. set( datasource, - `datasourceStorages.${currentEnvironment}.datasourceConfiguration.properties[1]`, + `datasourceStorages.${currentEnvDetails.id}.datasourceConfiguration.properties[1]`, { key: createMessage(GSHEET_AUTHORISED_FILE_IDS_KEY), value: fileIds, @@ -1854,7 +1884,9 @@ function* updateDatasourceAuthStateSaga( ) { try { const { authStatus, datasource } = actionPayload.payload; - const currentEnvironment = getCurrentEditingEnvID(); + const currentEnvironment: string = yield select( + getCurrentEditingEnvironmentId, + ); set( datasource, `datasourceStorages.${currentEnvironment}.datasourceConfiguration.authentication.authenticationStatus`, @@ -2019,5 +2051,13 @@ export function* watchDatasourcesSagas() { ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE, setDatasourceViewModeSaga, ), + takeEvery( + ReduxActionTypes.SOFT_REFRESH_DATASOURCE_STRUCTURE, + handleFetchDatasourceStructureOnLoad, + ), + takeEvery( + ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE, + setDatasourceViewModeSaga, + ), ]); } diff --git a/app/client/src/sagas/DebuggerSagas.ts b/app/client/src/sagas/DebuggerSagas.ts index e58d30f38c..5dc5086101 100644 --- a/app/client/src/sagas/DebuggerSagas.ts +++ b/app/client/src/sagas/DebuggerSagas.ts @@ -63,10 +63,7 @@ import { isAction, isWidget, } from "@appsmith/workers/Evaluation/evaluationUtils"; -import { - getCurrentEnvName, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentDetails } from "@appsmith/selectors/environmentSelectors"; // Saga to format action request values to be shown in the debugger function* formatActionRequestSaga( @@ -488,14 +485,17 @@ function* addDebuggerErrorLogsSaga(action: ReduxAction) { // Log analytics for new error messages //errorID has timestamp for 1:1 mapping with new and resolved errors if (errorMessages.length && errorLog) { + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); yield all( errorMessages.map((errorMessage) => put({ type: ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS, payload: { ...analyticsPayload, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, eventName: "DEBUGGER_NEW_ERROR_MESSAGE", errorId: errorLog.id + "_" + errorLog.timestamp, errorMessage: errorMessage.message, @@ -510,6 +510,9 @@ function* addDebuggerErrorLogsSaga(action: ReduxAction) { } else { const updatedErrorMessages = messages ?? []; const existingErrorMessages = currentDebuggerErrors[id].messages ?? []; + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); // Log new error messages yield all( updatedErrorMessages.map((updatedErrorMessage) => { @@ -526,8 +529,8 @@ function* addDebuggerErrorLogsSaga(action: ReduxAction) { type: ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS, payload: { ...analyticsPayload, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, eventName: "DEBUGGER_NEW_ERROR_MESSAGE", errorId: errorLog.id + "_" + errorLog.timestamp, errorMessage: updatedErrorMessage.message, @@ -555,8 +558,8 @@ function* addDebuggerErrorLogsSaga(action: ReduxAction) { type: ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS, payload: { ...analyticsPayload, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, eventName: "DEBUGGER_RESOLVED_ERROR_MESSAGE", errorId: currentDebuggerErrors[id].id + @@ -618,6 +621,9 @@ function* deleteDebuggerErrorLogsSaga( }); if (errorMessages) { + const currentEnvDetails: { id: string; name: string } = yield select( + getCurrentEnvironmentDetails, + ); //errorID has timestamp for 1:1 mapping with new and resolved errors yield all( errorMessages.map((errorMessage) => { @@ -625,8 +631,8 @@ function* deleteDebuggerErrorLogsSaga( type: ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS, payload: { ...analyticsPayload, - environmentId: getCurrentEnvironment(), - environmentName: getCurrentEnvName(), + environmentId: currentEnvDetails.id, + environmentName: currentEnvDetails.name, eventName: "DEBUGGER_RESOLVED_ERROR_MESSAGE", errorId: error.id + "_" + error.timestamp, errorMessage: errorMessage.message, diff --git a/app/client/src/sagas/QueryPaneSagas.ts b/app/client/src/sagas/QueryPaneSagas.ts index 4145e8648e..d9d47cde87 100644 --- a/app/client/src/sagas/QueryPaneSagas.ts +++ b/app/client/src/sagas/QueryPaneSagas.ts @@ -81,10 +81,8 @@ import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil"; import { toast } from "design-system"; import type { CreateDatasourceSuccessAction } from "actions/datasourceActions"; import { createDefaultActionPayload } from "./ActionSagas"; -import { - DB_NOT_SUPPORTED, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; +import { DB_NOT_SUPPORTED } from "@appsmith/utils/Environments"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; // Called whenever the query being edited is changed via the URL or query pane function* changeQuerySaga(actionPayload: ReduxAction<{ id: string }>) { @@ -266,7 +264,7 @@ function* formValueChangeSaga( // Editing form fields triggers evaluations. // We pass the action to run form evaluations when the dataTree evaluation is complete - let currentEnvironment = getCurrentEnvironment(); + let currentEnvironment: string = yield select(getCurrentEnvironmentId); const pluginType = plugin?.type; if ( (!!pluginType && DB_NOT_SUPPORTED.includes(pluginType)) || diff --git a/app/client/src/sagas/ReplaySaga.ts b/app/client/src/sagas/ReplaySaga.ts index bdad4bbe48..058304f9e9 100644 --- a/app/client/src/sagas/ReplaySaga.ts +++ b/app/client/src/sagas/ReplaySaga.ts @@ -76,10 +76,10 @@ import { AppThemingMode } from "selectors/appThemingSelectors"; import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { startFormEvaluations } from "actions/evaluationActions"; -import { getCurrentEnvironment } from "@appsmith/utils/Environments"; import { getUIComponent } from "pages/Editor/QueryEditor/helpers"; import type { Plugin } from "api/PluginApi"; import { UIComponentTypes } from "api/PluginApi"; +import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; export type UndoRedoPayload = { operation: ReplayReduxActionTypes; @@ -317,7 +317,7 @@ function* replayActionSaga( * Update all the diffs in the action object. * We need this for debugger logs, dynamicBindingPathList and to call relevant APIs */ - const currentEnvironment = getCurrentEnvironment(); + const currentEnvironment: string = yield select(getCurrentEnvironmentId); const plugins: Plugin[] = yield select(getPlugins); const uiComponent = getUIComponent(replayEntity.pluginId, plugins); const datasource: Datasource | undefined = yield select( diff --git a/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts b/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts index 08a5853bc4..8b910c7f29 100644 --- a/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts +++ b/app/client/src/transformers/RestAPIDatasourceFormTransformer.ts @@ -1,7 +1,4 @@ -import { - getCurrentEditingEnvID, - isEnvironmentValid, -} from "@appsmith/utils/Environments"; +import { isEnvironmentValid } from "@appsmith/utils/Environments"; import type { Property } from "entities/Action"; import type { Datasource, DatasourceStorage } from "entities/Datasource"; import type { @@ -20,8 +17,8 @@ import { get, set } from "lodash"; export const datasourceToFormValues = ( datasource: Datasource, + currentEnvironment: string, ): ApiDatasourceForm => { - const currentEnvironment = getCurrentEditingEnvID(); const authType = get( datasource, `datasourceStorages.${currentEnvironment}.datasourceConfiguration.authentication.authenticationType`, @@ -46,7 +43,11 @@ export const datasourceToFormValues = ( connection.ssl.authType === SSLType.SELF_SIGNED_CERTIFICATE, ); } - const authentication = datasourceToFormAuthentication(authType, datasource); + const authentication = datasourceToFormAuthentication( + authType, + datasource, + currentEnvironment, + ); const isSendSessionEnabled = get( datasource, @@ -86,8 +87,8 @@ export const datasourceToFormValues = ( export const formValuesToDatasource = ( datasource: Datasource, form: ApiDatasourceForm, + currentEnvironment: string, ): Datasource => { - const currentEnvironment = getCurrentEditingEnvID(); const authentication = formToDatasourceAuthentication( form.authType, form.authentication, @@ -223,8 +224,8 @@ const formToDatasourceAuthentication = ( const datasourceToFormAuthentication = ( authType: AuthType, datasource: Datasource, + currentEnvironment: string, ): Authentication | undefined => { - const currentEnvironment = getCurrentEditingEnvID(); if ( !datasource || !datasource.datasourceStorages[currentEnvironment] diff --git a/app/client/src/utils/editorContextUtils.ts b/app/client/src/utils/editorContextUtils.ts index d2ac009fd1..061ba3b694 100644 --- a/app/client/src/utils/editorContextUtils.ts +++ b/app/client/src/utils/editorContextUtils.ts @@ -4,10 +4,7 @@ import { DATASOURCE_REST_API_FORM, DATASOURCE_SAAS_FORM, } from "@appsmith/constants/forms"; -import { - DB_NOT_SUPPORTED, - getCurrentEnvironment, -} from "@appsmith/utils/Environments"; +import { DB_NOT_SUPPORTED } from "@appsmith/utils/Environments"; import { diff } from "deep-diff"; import { PluginName, PluginPackageName, PluginType } from "entities/Action"; import type { @@ -104,7 +101,7 @@ export function getPropertyControlFocusElement( export function isDatasourceAuthorizedForQueryCreation( datasource: Datasource, plugin: Plugin, - currentEnvironment = getCurrentEnvironment(), + currentEnvironment: string, validStatusArr: Array = [AuthenticationStatus.SUCCESS], ): boolean { if (!datasource || !datasource.hasOwnProperty("datasourceStorages")) diff --git a/app/client/src/utils/storage.ts b/app/client/src/utils/storage.ts index 5a42ed71a9..08ba9dac7c 100644 --- a/app/client/src/utils/storage.ts +++ b/app/client/src/utils/storage.ts @@ -33,6 +33,7 @@ export const STORAGE_KEYS: { USER_SIGN_UP: "USER_SIGN_UP", VERSION_UPDATE_STATE: "VERSION_UPDATE_STATE", AI_RECENT_QUERIES: "AI_RECENT_QUERIES", + CURRENT_ENV: "CURRENT_ENV", AI_KNOWLEDGE_BASE: "AI_KNOWLEDGE_BASE", }; @@ -113,6 +114,42 @@ export const getCopiedWidgets = async () => { return []; }; +// Function to save the current environment and the appId in indexedDB +export const saveCurrentEnvironment = async (envId: string, appId: string) => { + try { + await store.setItem(STORAGE_KEYS.CURRENT_ENV, { envId, appId }); + return true; + } catch (error) { + log.error("An error occurred when storing current env: ", error); + return false; + } +}; + +// Function to fetch the current environment and related appId from indexedDB +export const getSavedCurrentEnvironmentDetails = async () => { + try { + return ( + (await store.getItem(STORAGE_KEYS.CURRENT_ENV)) || { + envId: "", + appId: "", + } + ); + } catch (error) { + log.error("An error occurred when fetching current env: ", error); + } +}; + +// Function to reset the current environment and related appId from indexedDB +export const resetCurrentEnvironment = async () => { + try { + await store.removeItem(STORAGE_KEYS.CURRENT_ENV); + return true; + } catch (error) { + log.error("An error occurred when resetting current env: ", error); + return false; + } +}; + export const setPostWelcomeTourState = async (flag: boolean) => { try { await store.setItem(STORAGE_KEYS.POST_WELCOME_TOUR, flag);