From b7db5d8fca8bf0312dd1efe096471693cfec4233 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Wed, 14 Feb 2024 14:22:04 +0530 Subject: [PATCH 1/7] fix: Datasource null check in QueryDebugger (#31115) Adds null check for datasources as sometimes they may not be available ## Summary by CodeRabbit - **Bug Fixes** - Improved reliability in accessing datasource properties within the Query Debugger, ensuring safer operations and correcting the datasource structure fetching process. --- .../pages/Editor/QueryEditor/QueryDebuggerTabs.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx index 532c6cf8d0..ea82cda35a 100644 --- a/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx +++ b/app/client/src/pages/Editor/QueryEditor/QueryDebuggerTabs.tsx @@ -98,18 +98,21 @@ function QueryDebuggerTabs({ ); const datasourceStructure = useSelector((state) => - getDatasourceStructureById(state, currentActionConfig?.datasource.id || ""), + getDatasourceStructureById( + state, + currentActionConfig?.datasource?.id ?? "", + ), ); useEffect(() => { if ( - currentActionConfig?.datasource.id && + currentActionConfig?.datasource?.id && datasourceStructure === undefined && pluginDatasourceForm !== DatasourceComponentTypes.RestAPIDatasourceForm ) { dispatch( fetchDatasourceStructure( - currentActionConfig?.datasource.id, + currentActionConfig.datasource.id, true, DatasourceStructureContext.QUERY_EDITOR, ), @@ -180,7 +183,7 @@ function QueryDebuggerTabs({ }); } - if (showSchema && currentActionConfig) { + if (showSchema && currentActionConfig && currentActionConfig.datasource) { responseTabs.unshift({ key: "schema", title: "Schema", From 7ccc6874a32ad64ea2ebdfb92cde2ed7b3b419fc Mon Sep 17 00:00:00 2001 From: balajisoundar Date: Fri, 15 Mar 2024 13:17:11 +0530 Subject: [PATCH 2/7] =?UTF-8?q?fix:=20[map=20chart=20widget]=20create=20un?= =?UTF-8?q?ique=20instance=20of=20map=20loader=20per=20widget=20to=20avoi?= =?UTF-8?q?=E2=80=A6=20(#31822)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …d cross cancelling loader calls ## Description Create an instance of map loader per widget to avoid one widget cancelling calls of another widget. Fixes https://github.com/appsmithorg/appsmith/issues/31819 ## Automation /ok-to-test tags="@tag.Maps" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `cd13c989d8b911a064629bf1d8c683e09927d3b2` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **New Features** - Enhanced the Map Widget to load maps more efficiently with the introduction of `loadMapGenerator`. - **Tests** - Added Cypress tests to ensure the Map Widget loads correctly on the canvas. - **Refactor** - Updated the Map Widget loading process for better performance and flexibility. --- .../Widgets/Others/MapWidget_loading_Spec.ts | 23 +++++++++++++++++++ .../MapChartWidget/component/index.tsx | 4 +++- .../MapChartWidget/component/utilities.ts | 4 ++-- 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 app/client/cypress/e2e/Regression/ClientSide/Widgets/Others/MapWidget_loading_Spec.ts diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Others/MapWidget_loading_Spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Others/MapWidget_loading_Spec.ts new file mode 100644 index 0000000000..e3e56ddefc --- /dev/null +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Others/MapWidget_loading_Spec.ts @@ -0,0 +1,23 @@ +/// +import { + agHelper, + entityExplorer, + draggableWidgets, +} from "../../../../../support/Objects/ObjectsCore"; + +describe( + "Map chart Widget", + { tags: ["@tag.Widget", "@tag.Maps"] }, + function () { + it("1.Drag two Map Widget and Verify the Map Widget is loading", () => { + //Add map and verify + entityExplorer.DragDropWidgetNVerify(draggableWidgets.MAPCHART, 200, 200); + entityExplorer.DragDropWidgetNVerify(draggableWidgets.MAPCHART, 600, 200); + agHelper.RefreshPage(); + agHelper.AssertElementLength( + ".t--draggable-mapchartwidget svg text:contains('Global Population')", + 2, + ); + }); + }, +); diff --git a/app/client/src/widgets/MapChartWidget/component/index.tsx b/app/client/src/widgets/MapChartWidget/component/index.tsx index c5dcdee8a3..3ba358eee4 100644 --- a/app/client/src/widgets/MapChartWidget/component/index.tsx +++ b/app/client/src/widgets/MapChartWidget/component/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; import styled from "styled-components"; import type { MapColorObject, MapTypes } from "../constants"; import type { MapData } from "./types"; -import { getChartOption, loadMap } from "./utilities"; +import { getChartOption, loadMapGenerator } from "./utilities"; import * as echarts from "echarts"; import countryDetails from "./countryDetails"; import clsx from "clsx"; @@ -27,6 +27,8 @@ const MapChartContainer = styled.div<{ export default function EchartComponent(props: MapChartComponentProps) { const [isLoading, setIsLoading] = useState(false); + const loadMap = useMemo(loadMapGenerator, []); + const [key, setKey] = useState(0); const { caption, colorRange, data, onDataPointClick, showLabels, type } = diff --git a/app/client/src/widgets/MapChartWidget/component/utilities.ts b/app/client/src/widgets/MapChartWidget/component/utilities.ts index c00fe46af8..41f0d8231a 100644 --- a/app/client/src/widgets/MapChartWidget/component/utilities.ts +++ b/app/client/src/widgets/MapChartWidget/component/utilities.ts @@ -43,7 +43,7 @@ export function getSpecialAreas(map: MapTypes): GeoSpecialAreas { /* * Function to load the map geojson file and register it with echarts */ -export const loadMap = (() => { +export const loadMapGenerator = () => { let abortController: AbortController | null = null; return async (type: MapTypes) => { @@ -85,7 +85,7 @@ export const loadMap = (() => { return Promise.resolve(); } }; -})(); +}; function getProjection(type: string) { switch (type) { From 782c7b0f98d223938a7208024060a046940eac77 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Fri, 15 Mar 2024 15:24:26 +0530 Subject: [PATCH 3/7] fix: remove counter of cmd + click navigation usage (#31830) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixes the blocker issue for canvas resize by removing the counter of cmd + click as that goes to local storage and that is somehow causing this issue Fixes #31820 ## Automation /ok-to-test tags="@tag.Widget" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `00eee43d89c9df1071a3a1daca449629e48386ca` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **Refactor** - Improved the widget selection process by streamlining the tracking and storage method within the application. --- app/client/src/sagas/WidgetSelectionSagas.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/app/client/src/sagas/WidgetSelectionSagas.ts b/app/client/src/sagas/WidgetSelectionSagas.ts index 1fe5dbba35..a7982f8ce4 100644 --- a/app/client/src/sagas/WidgetSelectionSagas.ts +++ b/app/client/src/sagas/WidgetSelectionSagas.ts @@ -61,10 +61,6 @@ import type { FeatureFlags } from "@appsmith/entities/FeatureFlag"; import { getWidgetSelectorByWidgetId } from "selectors/layoutSystemSelectors"; import { getAppViewerPageIdFromPath } from "@appsmith/pages/Editor/Explorer/helpers"; import AnalyticsUtil from "../utils/AnalyticsUtil"; -import { - retrieveCodeWidgetNavigationUsed, - storeCodeWidgetNavigationUsed, -} from "../utils/storage"; // The following is computed to be used in the entity explorer // Every time a widget is selected, we need to expand widget entities @@ -220,9 +216,6 @@ function* appendSelectedWidgetToUrlSaga( const isWidgetSelectionBlocked: boolean = yield select( getWidgetSelectionBlock, ); - const timesUsedCodeModeWidgetSelection: number = yield call( - retrieveCodeWidgetNavigationUsed, - ); const appMode: APP_MODE = yield select(getAppMode); const viewMode = appMode === APP_MODE.PUBLISHED; if (isSnipingMode || viewMode) return; @@ -243,12 +236,6 @@ function* appendSelectedWidgetToUrlSaga( }); if (invokedBy === NavigationMethod.CanvasClick && isWidgetSelectionBlocked) { AnalyticsUtil.logEvent("CODE_MODE_WIDGET_SELECTION"); - if (timesUsedCodeModeWidgetSelection < 2) { - yield call( - storeCodeWidgetNavigationUsed, - timesUsedCodeModeWidgetSelection + 1, - ); - } } if (currentURL !== newUrl) { history.push(newUrl, { invokedBy }); From 77bb2a4fdd3c5188fb77b6f7165ce69cc490b87b Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Fri, 15 Mar 2024 16:47:48 +0530 Subject: [PATCH 4/7] chore: Have a failsafe for split screen if we turn off the feature flag (#31832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Adds a failsafe for Split screen feature when flag is turned off ## Automation /ok-to-test tags="@tag.IDE" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `434c36e595e46c378b58fa14bd1c9d04a3bfd119` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **New Features** - Introduced an `Editor View Mode` option to enhance user interface customization based on feature availability. --- app/client/src/selectors/ideSelectors.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/client/src/selectors/ideSelectors.tsx b/app/client/src/selectors/ideSelectors.tsx index 1bd5451b66..a9df3685fe 100644 --- a/app/client/src/selectors/ideSelectors.tsx +++ b/app/client/src/selectors/ideSelectors.tsx @@ -2,7 +2,10 @@ import { createSelector } from "reselect"; import { selectFeatureFlags } from "@appsmith/selectors/featureFlagsSelectors"; import type { AppState } from "@appsmith/reducers"; import { getPageActions } from "@appsmith/selectors/entitiesSelector"; -import { EditorEntityTab } from "@appsmith/entities/IDE/constants"; +import { + EditorEntityTab, + EditorViewMode, +} from "@appsmith/entities/IDE/constants"; export const getIsSideBySideEnabled = createSelector( selectFeatureFlags, @@ -11,7 +14,16 @@ export const getIsSideBySideEnabled = createSelector( flags.rollout_side_by_side_enabled, ); -export const getIDEViewMode = (state: AppState) => state.ui.ide.view; +export const getIDEViewMode = createSelector( + getIsSideBySideEnabled, + (state) => state.ui.ide.view, + (featureFlag, ideViewMode) => { + if (featureFlag) { + return ideViewMode; + } + return EditorViewMode.FullScreen; + }, +); export const getPagesActiveStatus = (state: AppState) => state.ui.ide.pagesActive; From 635af92e2e408da0bb37e0bb314199b0e8bb9498 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 15 Mar 2024 17:40:30 +0530 Subject: [PATCH 5/7] fix: fixing redirect from ds modal after import (#31834) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Redirection issue on DS Reconfigure modal after user imports the application ## Automation /ok-to-test tags="@tag.Fork,@tag.ImportExport" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `16953d533498713ec3e3eefb943614b20bdd5b95` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **Refactor** - Improved the redirection logic in the `ReconnectDatasourceModal` to ensure users are navigated correctly based on their current application context. --- .../pages/Editor/gitSync/ReconnectDatasourceModal.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx b/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx index 25fd58eb90..6a732e4095 100644 --- a/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx +++ b/app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx @@ -75,7 +75,6 @@ import { getFetchedWorkspaces } from "@appsmith/selectors/workspaceSelectors"; import { getApplicationsOfWorkspace } from "@appsmith/selectors/selectedWorkspaceSelectors"; import useReconnectModalData from "@appsmith/pages/Editor/gitSync/useReconnectModalData"; import { resetImportData } from "@appsmith/actions/workspaceActions"; -import history from "utils/history"; const Section = styled.div` display: flex; @@ -439,6 +438,11 @@ function ReconnectDatasourceModal() { // If either the close button or the overlay was clicked close the modal if (shouldClose) { onClose(); + const isInsideApplication = + window.location.pathname.split("/")[1] === "app"; + if (isInsideApplication && editorURL) { + window.location.href = editorURL; + } } } }; @@ -563,7 +567,10 @@ function ReconnectDatasourceModal() { const onSkipBtnClick = () => { AnalyticsUtil.logEvent("RECONNECTING_SKIP_TO_APPLICATION_BUTTON_CLICK"); localStorage.setItem("importedAppPendingInfo", "null"); - editorURL && history.push(editorURL); + if (editorURL) { + // window location because history push changes routes shallowly and some side effects needed for page loading might not run + window.location.href = editorURL; + } onClose(); }; From 3d0eec020bd8ef4bf3217441d2c49346a9bbc198 Mon Sep 17 00:00:00 2001 From: Trisha Anand Date: Tue, 2 Apr 2024 20:20:51 +0530 Subject: [PATCH 6/7] fix: Scheduling synchronized block on bounded elastic threadpool instead of main event threadpool (#32343) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … ## Description > [!TIP] > _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content team)._ > > _Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR._ Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Sanity" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `03dc817039ee24159438e613320550620353a2b7` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **Refactor** - Improved backend scheduling for datasource operations to enhance performance without blocking the main thread. --- .../ce/DatasourceContextServiceCEImpl.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java index 3fa73f2f2a..1004185572 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java @@ -24,6 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import java.time.Instant; import java.util.Map; @@ -103,7 +104,8 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC // Basically remove entry from both cache maps pluginExecutor.datasourceDestroy(connection); } catch (Exception e) { - log.info("Error destroying stale datasource connection", e); + log.info( + Thread.currentThread().getName() + ": Error destroying stale datasource connection", e); } } datasourceContextMonoMap.remove(datasourceContextIdentifier); @@ -117,7 +119,8 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC */ if (datasourceContextIdentifier.getDatasourceId() != null && datasourceContextMonoMap.get(datasourceContextIdentifier) != null) { - log.debug("Cached resource context mono exists. Returning the same."); + log.debug(Thread.currentThread().getName() + + ": Cached resource context mono exists. Returning the same."); return datasourceContextMonoMap.get(datasourceContextIdentifier); } @@ -182,11 +185,11 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC protected Mono> createNewDatasourceContext( DatasourceStorage datasourceStorage, DatasourceContextIdentifier datasourceContextIdentifier) { - log.debug("Datasource context doesn't exist. Creating connection."); + log.debug(Thread.currentThread().getName() + ": Datasource context doesn't exist. Creating connection."); Mono pluginMono = pluginService.findById(datasourceStorage.getPluginId()).cache(); - return pluginMono + return (Mono>) pluginMono .zipWith(pluginExecutorHelper.getPluginExecutor(pluginMono)) .flatMap(tuple2 -> { Plugin plugin = tuple2.getT1(); @@ -214,7 +217,9 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC return getCachedDatasourceContextMono( datasourceStorage, plugin, pluginExecutor, monitor, datasourceContextIdentifier); - }); + }) + // Scheduling on bounded elastic to avoid blocking the main thread + .subscribeOn(Schedulers.boundedElastic()); } public boolean getIsStale( From a34e0e9867c73bacd36d109b83d8c5ace5c7e71f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 3 Apr 2024 15:50:58 +0530 Subject: [PATCH 7/7] revert: multi env switcher view mode changes (#32360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts changes for multienv switcher on view mode ## Automation /ok-to-test tags="@tag.MultiEnv" ### :mag: Cypress test results > [!IMPORTANT] > Workflow run: > Commit: `973e392a00cc68e0dbf1e99e06ca2b8b1ebc0474` > Cypress dashboard url: Click here! > All cypress tests have passed 🎉🎉🎉 ## Summary by CodeRabbit - **Refactor** - Simplified the handling of view modes and conditional rendering in the `BottomBar` component. - Removed and streamlined the `showBottomBar` logic and UI adjustments in `AppViewer`. - Introduced `isCombinedPreviewMode` for enhanced preview functionality in the Editor's `IDE` component. - Simplified the structure of `EditorWrapperContainer` by removing unnecessary props and logic. --- .../src/ce/hooks/useShowEnvSwitcher.test.tsx | 316 ------------------ app/client/src/ce/hooks/useShowEnvSwitcher.ts | 50 --- app/client/src/components/BottomBar/index.tsx | 20 +- app/client/src/ee/hooks/useShowEnvSwitcher.ts | 3 - app/client/src/pages/AppViewer/index.tsx | 18 +- app/client/src/pages/Editor/IDE/index.tsx | 9 +- .../Editor/commons/EditorWrapperContainer.tsx | 17 +- 7 files changed, 15 insertions(+), 418 deletions(-) delete mode 100644 app/client/src/ce/hooks/useShowEnvSwitcher.test.tsx delete mode 100644 app/client/src/ce/hooks/useShowEnvSwitcher.ts delete mode 100644 app/client/src/ee/hooks/useShowEnvSwitcher.ts diff --git a/app/client/src/ce/hooks/useShowEnvSwitcher.test.tsx b/app/client/src/ce/hooks/useShowEnvSwitcher.test.tsx deleted file mode 100644 index 56283adcd2..0000000000 --- a/app/client/src/ce/hooks/useShowEnvSwitcher.test.tsx +++ /dev/null @@ -1,316 +0,0 @@ -import React from "react"; -import { render } from "@testing-library/react"; -import { Provider } from "react-redux"; -import configureMockStore from "redux-mock-store"; -import useShowEnvSwitcher from "./useShowEnvSwitcher"; - -const spier = { - useShowEnvSwitcher: useShowEnvSwitcher, -}; - -const useShowEnvSwitcherSpy = jest.spyOn(spier, "useShowEnvSwitcher"); - -const MockEl = ({ viewMode = false }: { viewMode?: boolean } = {}) => { - spier.useShowEnvSwitcher({ viewMode }); - return
; -}; - -const renderMockElement = ({ - store, - viewMode, -}: { - store: any; - viewMode: boolean; -}) => { - return render( - - - , - ); -}; - -const environments = { data: [] }; - -describe("BottomBar environment switcher", () => { - it("should render when admin in edit mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: true, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(true); - }); - it("should render when dev in edit mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(true); - }); - it("should render when viewer in edit mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: [], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - - it("should render when admin in preview mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: true, - }, - }, - editor: { - isPreviewMode: true, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - it("should render when dev in preview mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: true, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - it("should render when viewer in preview mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: [], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: true, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: false }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - - it("should render when admin in view mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: true, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: true }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - it("should render when dev in view mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: ["manage:applications"], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: true }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); - it("should render when viewer in view mode", () => { - const mockStore = configureMockStore(); - const store = mockStore({ - ui: { - selectedWorkspace: { - workspace: {}, - }, - applications: { - currentApplication: { - userPermissions: [], - }, - }, - users: { - featureFlag: { - data: { - release_datasource_environments_enabled: false, - }, - }, - currentUser: { - isSuperUser: false, - }, - }, - editor: { - isPreviewMode: false, - }, - }, - environments, - }); - renderMockElement({ store, viewMode: true }); - expect(useShowEnvSwitcherSpy).lastReturnedWith(false); - }); -}); diff --git a/app/client/src/ce/hooks/useShowEnvSwitcher.ts b/app/client/src/ce/hooks/useShowEnvSwitcher.ts deleted file mode 100644 index cc3fa5669f..0000000000 --- a/app/client/src/ce/hooks/useShowEnvSwitcher.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; -import { - areEnvironmentsFetched, - getEnvironmentsWithPermission, -} from "@appsmith/selectors/environmentSelectors"; -import { showProductRamps } from "@appsmith/selectors/rampSelectors"; -import { useSelector } from "react-redux"; -import { RAMP_NAME } from "utils/ProductRamps/RampsControlList"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -import { previewModeSelector } from "selectors/editorSelectors"; -import { getCurrentAppWorkspace } from "@appsmith/selectors/selectedWorkspaceSelectors"; - -const useShowEnvSwitcher = ({ viewMode }: { viewMode: boolean }) => { - const isFeatureEnabled = useFeatureFlag( - FEATURE_FLAG.release_datasource_environments_enabled, - ); - const previewMode = useSelector(previewModeSelector); - const isMultiEnvNotPresent = useSelector((state) => { - const workspace = getCurrentAppWorkspace(state); - const isLoaded = areEnvironmentsFetched(state, workspace?.id); - const list = getEnvironmentsWithPermission(state); - const isDefault = list?.[0]?.isDefault; - if (!isFeatureEnabled) { - return true; - } else { - return ( - isLoaded && (list.length === 0 || (list.length === 1 && isDefault)) - ); - } - }); - - const isRampAllowed = useSelector((state) => - showProductRamps(RAMP_NAME.MULTIPLE_ENV, true)(state), - ); - if (!isFeatureEnabled && !isRampAllowed) { - return false; - } - - if (viewMode && isMultiEnvNotPresent) { - return false; - } - - if (previewMode && isMultiEnvNotPresent) { - return false; - } - - return true; -}; - -export default useShowEnvSwitcher; diff --git a/app/client/src/components/BottomBar/index.tsx b/app/client/src/components/BottomBar/index.tsx index b80fe7dfa1..2e90f0abfa 100644 --- a/app/client/src/components/BottomBar/index.tsx +++ b/app/client/src/components/BottomBar/index.tsx @@ -7,22 +7,12 @@ import { Button } from "design-system"; import SwitchEnvironment from "@appsmith/components/SwitchEnvironment"; import { Container, Wrapper } from "./components"; import { useSelector } from "react-redux"; -import { - getCurrentApplicationId, - previewModeSelector, -} from "selectors/editorSelectors"; +import { getCurrentApplicationId } from "selectors/editorSelectors"; import { useDispatch } from "react-redux"; import { softRefreshActions } from "actions/pluginActionActions"; import { START_SWITCH_ENVIRONMENT } from "@appsmith/constants/messages"; -import useShowEnvSwitcher from "@appsmith/hooks/useShowEnvSwitcher"; -interface BottomBarProps { - viewMode?: boolean; -} - -export default function BottomBar({ viewMode = false }: BottomBarProps) { - const isPreviewMode = useSelector(previewModeSelector); - const showEnvSwitcher = useShowEnvSwitcher({ viewMode }); +export default function BottomBar({ viewMode }: { viewMode: boolean }) { const appId = useSelector(getCurrentApplicationId) || ""; const dispatch = useDispatch(); @@ -33,7 +23,7 @@ export default function BottomBar({ viewMode = false }: BottomBarProps) { return ( - {showEnvSwitcher && ( + {!viewMode && ( )} - {!viewMode && !isPreviewMode && } + {!viewMode && } - {!viewMode && !isPreviewMode && ( + {!viewMode && (