From 89bf555727b504ae88b2905df392bc69d2f66805 Mon Sep 17 00:00:00 2001 From: akash-codemonk <67054171+akash-codemonk@users.noreply.github.com> Date: Fri, 2 Dec 2022 08:36:22 +0530 Subject: [PATCH] feat: [ Context Switching ] Maintain datasource edit mode (#17521) --- .../IDE/MaintainContext&Focus_spec.js | 11 ++++ .../cypress/support/Pages/DataSources.ts | 13 +++++ app/client/src/actions/datasourceActions.ts | 5 +- .../editorComponents/StoreAsDatasource.tsx | 12 ++--- .../fields/EmbeddedDatasourcePathField.tsx | 4 -- app/client/src/navigation/FocusElements.ts | 12 ++++- app/client/src/navigation/FocusEntity.ts | 12 +++++ .../pages/Editor/DataSourceEditor/DBForm.tsx | 9 +--- .../Editor/DataSourceEditor/JSONtoForm.tsx | 2 +- .../pages/Editor/DataSourceEditor/index.tsx | 53 ++++++++++++++++--- .../Explorer/Datasources/DatasourceEntity.tsx | 12 ++--- .../IntegrationEditor/DatasourceCard.tsx | 4 +- .../Editor/SaaSEditor/DatasourceForm.tsx | 19 +++---- .../src/pages/common/datasourceAuth/index.tsx | 3 ++ .../uiReducers/datasourcePaneReducer.ts | 11 ++-- app/client/src/sagas/DatasourcesSagas.ts | 28 ++-------- app/client/src/selectors/ui.tsx | 3 ++ 17 files changed, 129 insertions(+), 84 deletions(-) diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/IDE/MaintainContext&Focus_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/IDE/MaintainContext&Focus_spec.js index 8d4ad3230e..83a2cc37c0 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/IDE/MaintainContext&Focus_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/IDE/MaintainContext&Focus_spec.js @@ -4,6 +4,7 @@ import { ObjectsRegistry } from "../../../../support/Objects/Registry"; const homePage = ObjectsRegistry.HomePage; const agHelper = ObjectsRegistry.AggregateHelper; +const dataSources = ObjectsRegistry.DataSources; const ee = ObjectsRegistry.EntityExplorer; const apiPage = ObjectsRegistry.ApiPage; @@ -145,4 +146,14 @@ describe("MaintainContext&Focus", function() { ee.SelectEntityByName("Rest_Api_1"); apiPage.AssertRightPaneSelectedTab("connections"); }); + + it("8. Datasource edit mode has to be maintained", () => { + ee.SelectEntityByName("Appsmith"); + dataSources.EditDatasource(); + dataSources.SaveDSFromDialog(false); + ee.SelectEntityByName("Github"); + dataSources.AssertViewMode(); + ee.SelectEntityByName("Appsmith"); + dataSources.AssertEditMode(); + }); }); diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index a7830290e7..80cadb2b95 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -30,6 +30,7 @@ export class DataSources { private _saveDs = ".t--save-datasource"; private _saveAndAuthorizeDS = ".t--save-and-authorize-datasource"; private _datasourceCard = ".t--datasource"; + private _editButton = ".t--edit-datasource"; _dsEntityItem = "[data-guided-tour-id='explorer-entity-Datasources']"; _activeDS = "[data-testid='active-datasource-name']"; _templateMenu = ".t--template-menu"; @@ -111,6 +112,14 @@ export class DataSources { "//input[@name='actionConfiguration.timeoutInMillisecond']"; _getStructureReq = "/api/v1/datasources/*/structure?ignoreCache=true"; + public AssertViewMode() { + this.agHelper.AssertElementExist(this._editButton); + } + + public AssertEditMode() { + this.agHelper.AssertElementAbsence(this._editButton); + } + public StartDataSourceRoutes() { cy.intercept("POST", "/api/v1/datasources").as("saveDatasource"); cy.intercept("POST", "/api/v1/datasources/test").as("testDatasource"); @@ -212,6 +221,10 @@ export class DataSources { // else this.agHelper.AssertContains("datasource created"); } + public EditDatasource() { + this.agHelper.GetNClick(this._editButton); + } + public NavigateToDSCreateNew() { this.agHelper.GetNClick(this._addNewDataSource); // cy.get(this._dsCreateNewTab) diff --git a/app/client/src/actions/datasourceActions.ts b/app/client/src/actions/datasourceActions.ts index 84c2571fde..139382b2d7 100644 --- a/app/client/src/actions/datasourceActions.ts +++ b/app/client/src/actions/datasourceActions.ts @@ -177,10 +177,7 @@ export const deleteDatasource = ( }; }; -export const setDatsourceEditorMode = (payload: { - id: string; - viewMode: boolean; -}) => { +export const setDatasourceViewMode = (payload: boolean) => { return { type: ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE, payload, diff --git a/app/client/src/components/editorComponents/StoreAsDatasource.tsx b/app/client/src/components/editorComponents/StoreAsDatasource.tsx index 6fff522d2a..293570b417 100644 --- a/app/client/src/components/editorComponents/StoreAsDatasource.tsx +++ b/app/client/src/components/editorComponents/StoreAsDatasource.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled, { css } from "styled-components"; import { - setDatsourceEditorMode, + setDatasourceViewMode, storeAsDatasource, } from "actions/datasourceActions"; import { connect, useDispatch, useSelector } from "react-redux"; @@ -47,11 +47,11 @@ type storeDataSourceProps = { datasourceId?: string; enable: boolean; shouldSave: boolean; - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; + setDatasourceViewMode: (viewMode: boolean) => void; }; interface ReduxDispatchProps { - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; + setDatasourceViewMode: (viewMode: boolean) => void; } function StoreAsDatasource(props: storeDataSourceProps) { @@ -63,7 +63,7 @@ function StoreAsDatasource(props: storeDataSourceProps) { dispatch(storeAsDatasource()); } else { if (props.datasourceId) { - props.setDatasourceEditorMode(props.datasourceId, false); + props.setDatasourceViewMode(false); history.push( datasourcesEditorIdURL({ pageId, @@ -96,8 +96,8 @@ function StoreAsDatasource(props: storeDataSourceProps) { } const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({ - setDatasourceEditorMode: (id: string, viewMode: boolean) => - dispatch(setDatsourceEditorMode({ id, viewMode })), + setDatasourceViewMode: (viewMode: boolean) => + dispatch(setDatasourceViewMode(viewMode)), }); export default connect(null, mapDispatchToProps)(StoreAsDatasource); diff --git a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx index 409f9605cf..556ce9d150 100644 --- a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx +++ b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @@ -37,7 +37,6 @@ import { Text, FontWeight, TextType } from "design-system"; import { getDatasourceInfo } from "pages/Editor/APIEditor/ApiRightPane"; import * as FontFamilies from "constants/Fonts"; import { AuthType } from "entities/Datasource/RestAPIForm"; -import { setDatsourceEditorMode } from "actions/datasourceActions"; import { getCurrentApplicationId } from "selectors/editorSelectors"; import { Colors } from "constants/Colors"; @@ -66,7 +65,6 @@ type ReduxStateProps = { type ReduxDispatchProps = { updateDatasource: (datasource: Datasource | EmbeddedRestDatasource) => void; - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; }; type Props = EditorProps & @@ -555,8 +553,6 @@ const mapDispatchToProps = ( ): ReduxDispatchProps => ({ updateDatasource: (datasource) => dispatch(change(ownProps.formName, "datasource", datasource)), - setDatasourceEditorMode: (id: string, viewMode: boolean) => - dispatch(setDatsourceEditorMode({ id, viewMode })), }); const EmbeddedDatasourcePathConnectedComponent = connect( diff --git a/app/client/src/navigation/FocusElements.ts b/app/client/src/navigation/FocusElements.ts index 763e65daef..f1989b4f5a 100644 --- a/app/client/src/navigation/FocusElements.ts +++ b/app/client/src/navigation/FocusElements.ts @@ -19,7 +19,7 @@ import { getSelectedPropertyTabIndex, } from "selectors/editorContextSelectors"; import { setFocusableCodeEditorField } from "actions/editorContextActions"; -import { getSelectedWidgets } from "selectors/ui"; +import { getSelectedWidgets, isDatasourceInViewMode } from "selectors/ui"; import { selectMultipleWidgetsInitAction } from "actions/widgetSelectionActions"; import { FocusEntity } from "navigation/FocusEntity"; @@ -50,6 +50,7 @@ import { setSelectedPropertyTabIndex, } from "actions/propertyPaneActions"; import { setCanvasDebuggerSelectedTab } from "actions/debuggerActions"; +import { setDatasourceViewMode } from "actions/datasourceActions"; import { PluginPackageName } from "entities/Action"; import { getFocusablePropertyPaneField } from "selectors/propertyPaneSelectors"; @@ -57,6 +58,7 @@ export enum FocusElement { ApiPaneConfigTabs = "ApiPaneConfigTabs", ApiPaneResponseTabs = "ApiPaneResponseTabs", ApiPaneResponseHeight = "ApiPaneResponseHeight", + DatasourceViewMode = "DatasourceViewMode", ApiRightPaneTabs = "ApiRightPaneTabs", QueryPaneConfigTabs = "QueryPaneConfigTabs", QueryPaneResponseTabs = "QueryPaneResponseTabs", @@ -102,6 +104,14 @@ export const FocusElementsConfig: Record = { defaultValue: 0, }, ], + [FocusEntity.DATASOURCE]: [ + { + name: FocusElement.DatasourceViewMode, + selector: isDatasourceInViewMode, + setter: setDatasourceViewMode, + defaultValue: true, + }, + ], [FocusEntity.JS_OBJECT]: [ { name: FocusElement.CodeEditor, diff --git a/app/client/src/navigation/FocusEntity.ts b/app/client/src/navigation/FocusEntity.ts index 9dcba896e5..5eb9955a4a 100644 --- a/app/client/src/navigation/FocusEntity.ts +++ b/app/client/src/navigation/FocusEntity.ts @@ -4,14 +4,17 @@ import { BUILDER_CUSTOM_PATH, BUILDER_PATH, BUILDER_PATH_DEPRECATED, + DATA_SOURCES_EDITOR_ID_PATH, JS_COLLECTION_ID_PATH, QUERIES_EDITOR_ID_PATH, } from "constants/routes"; +import { SAAS_EDITOR_DATASOURCE_ID_PATH } from "pages/Editor/SaaSEditor/constants"; import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants"; export enum FocusEntity { API = "API", CANVAS = "CANVAS", + DATASOURCE = "DATASOURCE", QUERY = "QUERY", JS_OBJECT = "JS_OBJECT", PROPERTY_PANE = "PROPERTY_PANE", @@ -33,6 +36,7 @@ export function identifyEntityFromPath( } const match = matchPath<{ apiId?: string; + datasourceId?: string; pluginPackageName?: string; queryId?: string; appId?: string; @@ -46,6 +50,11 @@ export function identifyEntityFromPath( BUILDER_PATH_DEPRECATED + QUERIES_EDITOR_ID_PATH, BUILDER_PATH + QUERIES_EDITOR_ID_PATH, BUILDER_CUSTOM_PATH + QUERIES_EDITOR_ID_PATH, + BUILDER_PATH_DEPRECATED + DATA_SOURCES_EDITOR_ID_PATH, + BUILDER_PATH + DATA_SOURCES_EDITOR_ID_PATH, + BUILDER_CUSTOM_PATH + DATA_SOURCES_EDITOR_ID_PATH, + BUILDER_PATH + SAAS_EDITOR_DATASOURCE_ID_PATH, + BUILDER_CUSTOM_PATH + SAAS_EDITOR_DATASOURCE_ID_PATH, BUILDER_PATH_DEPRECATED + SAAS_EDITOR_API_ID_PATH, BUILDER_PATH + SAAS_EDITOR_API_ID_PATH, BUILDER_CUSTOM_PATH + SAAS_EDITOR_API_ID_PATH, @@ -66,6 +75,9 @@ export function identifyEntityFromPath( } return { entity: FocusEntity.API, id: match.params.apiId }; } + if (match.params.datasourceId) { + return { entity: FocusEntity.DATASOURCE, id: match.params.datasourceId }; + } if (match.params.queryId) { return { entity: FocusEntity.QUERY, id: match.params.queryId }; } diff --git a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx index 6106d2d08d..294dd5ade2 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/DBForm.tsx @@ -32,7 +32,7 @@ import { TEMP_DATASOURCE_ID } from "constants/Datasource"; const { cloudHosting } = getAppsmithConfigs(); interface DatasourceDBEditorProps extends JSONtoFormProps { - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; + setDatasourceViewMode: (viewMode: boolean) => void; openOmnibarReadMore: (text: string) => void; datasourceId: string; applicationId: string; @@ -80,8 +80,6 @@ class DatasourceDBEditor extends JSONtoForm { componentDidUpdate(prevProps: Props) { if (prevProps.datasourceId !== this.props.datasourceId) { super.componentDidUpdate(prevProps); - if (!this.props.hiddenHeader) - this.props.setDatasourceEditorMode(this.props.datasourceId, true); } } // returns normalized and trimmed datasource form data @@ -145,10 +143,7 @@ class DatasourceDBEditor extends JSONtoForm { category={Category.tertiary} className="t--edit-datasource" onClick={() => { - this.props.setDatasourceEditorMode( - this.props.datasourceId, - false, - ); + this.props.setDatasourceViewMode(false); }} text="EDIT" /> diff --git a/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx b/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx index f7b95acd00..46e730f138 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/JSONtoForm.tsx @@ -221,7 +221,7 @@ export class JSONtoForm< if (isArrayorObject(valueType)) { this.getTrimmedData(formData[key]); } else if (valueType === Types.STRING) { - formData[key] = formData[key].trim(); + _.set(formData, key, formData[key].trim()); } }); } diff --git a/app/client/src/pages/Editor/DataSourceEditor/index.tsx b/app/client/src/pages/Editor/DataSourceEditor/index.tsx index 9a1be182e3..1849ba4ac6 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/index.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/index.tsx @@ -10,7 +10,7 @@ import { } from "selectors/entitiesSelector"; import { switchDatasource, - setDatsourceEditorMode, + setDatasourceViewMode, removeTempDatasource, deleteTempDSFromDraft, toggleSaveActionFlag, @@ -43,6 +43,8 @@ import { REST_API_AUTHORIZATION_SUCCESSFUL, } from "@appsmith/constants/messages"; import { Toaster, Variant } from "design-system"; +import { isDatasourceInViewMode } from "selectors/ui"; +import { getQueryParams } from "utils/URLUtils"; import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import SaveOrDiscardDatasourceModal from "./SaveOrDiscardDatasourceModal"; @@ -93,6 +95,8 @@ type Props = ReduxStateProps & type State = { showDialog: boolean; routesBlocked: boolean; + readUrlParams: boolean; + unblock(): void; navigation(): void; }; @@ -109,6 +113,7 @@ class DataSourceEditor extends React.Component { this.props.switchDatasource(this.props.datasourceId); } } + componentDidMount() { //Fix to prevent restapi datasource from being set in DatasourceDBForm in datasource view mode //TODO: Needs cleanup @@ -161,7 +166,7 @@ class DataSourceEditor extends React.Component { pluginId, pluginImages, pluginType, - setDatasourceEditorMode, + setDatasourceViewMode, viewMode, } = this.props; @@ -183,7 +188,7 @@ class DataSourceEditor extends React.Component { pageId={pageId} pluginImage={pluginImages[pluginId]} pluginType={pluginType} - setDatasourceEditorMode={setDatasourceEditorMode} + setDatasourceViewMode={setDatasourceViewMode} viewMode={viewMode && !fromImporting} /> ); @@ -194,6 +199,7 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => { const datasourceId = props.datasourceId ?? props.match?.params?.datasourceId; const { datasourcePane } = state.ui; const { datasources, plugins } = state.entities; + const viewMode = isDatasourceInViewMode(state); const datasource = getDatasource(state, datasourceId); const { formConfigs } = plugins; const formData = getFormValues(DATASOURCE_DB_FORM)(state) as Datasource; @@ -217,8 +223,7 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => { formConfig: formConfigs[pluginId] || [], isNewDatasource: datasourcePane.newDatasource === TEMP_DATASOURCE_ID, pageId: props.pageId ?? props.match?.params?.pageId, - viewMode: - datasourcePane.viewMode[datasource?.id ?? ""] ?? !props.fromImporting, + viewMode: viewMode ?? !props.fromImporting, pluginType: plugin?.type ?? "", pluginDatasourceForm: plugin?.datasourceComponent ?? DatasourceComponentTypes.AutoForm, @@ -241,8 +246,8 @@ const mapDispatchToProps = ( // on reconnect data modal, it shouldn't be redirected to datasource edit page dispatch(switchDatasource(id, ownProps.fromImporting)); }, - setDatasourceEditorMode: (id: string, viewMode: boolean) => - dispatch(setDatsourceEditorMode({ id, viewMode })), + setDatasourceViewMode: (viewMode: boolean) => + dispatch(setDatasourceViewMode(viewMode)), openOmnibarReadMore: (text: string) => { dispatch(setGlobalSearchQuery(text)); dispatch(toggleShowGlobalSearchModal()); @@ -258,7 +263,7 @@ const mapDispatchToProps = ( export interface DatasourcePaneFunctions { switchDatasource: (id: string) => void; - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; + setDatasourceViewMode: (viewMode: boolean) => void; openOmnibarReadMore: (text: string) => void; discardTempDatasource: () => void; deleteTempDSFromDraft: () => void; @@ -273,6 +278,7 @@ class DatasourceEditorRouter extends React.Component { this.state = { showDialog: false, routesBlocked: false, + readUrlParams: false, unblock: () => { return undefined; }, @@ -296,6 +302,7 @@ class DatasourceEditorRouter extends React.Component { if (this.props.isDatasourceBeingSaved) { this.closeDialogAndUnblockRoutes(); } + this.setViewModeFromQueryParams(); } componentDidMount() { @@ -314,6 +321,36 @@ class DatasourceEditorRouter extends React.Component { if (!this.props.viewMode) { this.blockRoutes(); } + + if ( + this.props.pluginDatasourceForm === + DatasourceComponentTypes.RestAPIDatasourceForm + ) { + this.setViewModeFromQueryParams(); + } + } + + // To move to edit state for new datasources and when we want to move to edit state + // from outside the datasource route + setViewModeFromQueryParams() { + const params = getQueryParams(); + if (this.props.viewMode) { + if ( + (params.viewMode === "false" && !this.state.readUrlParams) || + this.props.isNewDatasource + ) { + // We just want to read the query params once. Cannot remove query params + // here as this triggers history.block + this.setState( + { + readUrlParams: true, + }, + () => { + this.props.setDatasourceViewMode(false); + }, + ); + } + } } componentWillUnmount() { diff --git a/app/client/src/pages/Editor/Explorer/Datasources/DatasourceEntity.tsx b/app/client/src/pages/Editor/Explorer/Datasources/DatasourceEntity.tsx index 0abfa0b42d..ff0f48e72b 100644 --- a/app/client/src/pages/Editor/Explorer/Datasources/DatasourceEntity.tsx +++ b/app/client/src/pages/Editor/Explorer/Datasources/DatasourceEntity.tsx @@ -9,14 +9,12 @@ import history from "utils/history"; import { fetchDatasourceStructure, expandDatasourceEntity, - setDatsourceEditorMode, updateDatasourceName, } from "actions/datasourceActions"; import { useDispatch, useSelector } from "react-redux"; import { AppState } from "@appsmith/reducers"; import { DatasourceStructureContainer } from "./DatasourceStructureContainer"; import { isStoredDatasource, PluginType } from "entities/Action"; -import { getQueryParams } from "utils/URLUtils"; import { getAction } from "selectors/entitiesSelector"; import { datasourcesEditorIdURL, @@ -26,6 +24,8 @@ import { inGuidedTour } from "selectors/onboardingSelectors"; import { getCurrentPageId } from "selectors/editorSelectors"; import AnalyticsUtil from "utils/AnalyticsUtil"; import { useLocation } from "react-router"; +import omit from "lodash/omit"; +import { getQueryParams } from "utils/URLUtils"; type ExplorerDatasourceEntityProps = { plugin: Plugin; @@ -51,18 +51,12 @@ const ExplorerDatasourceEntity = React.memo( pageId, pluginPackageName: props.plugin.packageName, datasourceId: props.datasource.id, - params: { - viewMode: true, - }, }); } else { - dispatch( - setDatsourceEditorMode({ id: props.datasource.id, viewMode: true }), - ); url = datasourcesEditorIdURL({ pageId, datasourceId: props.datasource.id, - params: getQueryParams(), + params: omit(getQueryParams(), "viewMode"), }); } diff --git a/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx b/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx index cb32929ef6..2b2249a61b 100644 --- a/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx +++ b/app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx @@ -15,7 +15,6 @@ import history from "utils/history"; import { Position } from "@blueprintjs/core/lib/esm/common/position"; import { renderDatasourceSection } from "pages/Editor/DataSourceEditor/DatasourceSection"; -import { setDatsourceEditorMode } from "actions/datasourceActions"; import { getQueryParams } from "utils/URLUtils"; import { Button, @@ -234,18 +233,19 @@ function DatasourceCard(props: DatasourceCardProps) { datasourceId: datasource.id, params: { from: "datasources", + viewMode: "false", ...getQueryParams(), }, }), ); } else { - dispatch(setDatsourceEditorMode({ id: datasource.id, viewMode: false })); history.push( datasourcesEditorIdURL({ pageId, datasourceId: datasource.id, params: { from: "datasources", + viewMode: "false", ...getQueryParams(), }, }), diff --git a/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx b/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx index cb16b47354..b28102da84 100644 --- a/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx +++ b/app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx @@ -35,13 +35,14 @@ import { getCurrentApplicationId } from "selectors/editorSelectors"; import DatasourceAuth from "../../common/datasourceAuth"; import EntityNotFoundPane from "../EntityNotFoundPane"; import { saasEditorDatasourceIdURL } from "RouteBuilder"; +import { isDatasourceInViewMode } from "selectors/ui"; import { hasManageDatasourcePermission } from "@appsmith/utils/permissionHelpers"; import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import { createTempDatasourceFromForm, deleteTempDSFromDraft, removeTempDatasource, - setDatsourceEditorMode, + setDatasourceViewMode, toggleSaveActionFlag, toggleSaveActionFromPopupFlag, } from "actions/datasourceActions"; @@ -73,8 +74,8 @@ interface DatasourceFormFunctions { deleteTempDSFromDraft: () => void; toggleSaveActionFlag: (flag: boolean) => void; toggleSaveActionFromPopupFlag: (flag: boolean) => void; - setDatasourceEditorMode: (id: string, viewMode: boolean) => void; createTempDatasource: (data: any) => void; + setDatasourceViewMode: (viewMode: boolean) => void; } type DatasourceSaaSEditorProps = StateProps & @@ -250,7 +251,6 @@ class DatasourceSaaSEditor extends JSONtoForm { pageId, pluginPackageName, } = this.props; - const params: string = location.search; const viewMode = !hiddenHeader && new URLSearchParams(params).get("viewMode"); @@ -276,6 +276,7 @@ class DatasourceSaaSEditor extends JSONtoForm { category={Category.tertiary} className="t--edit-datasource" onClick={() => { + this.props.setDatasourceViewMode(false); this.props.history.replace( saasEditorDatasourceIdURL({ pageId: pageId || "", @@ -286,10 +287,6 @@ class DatasourceSaaSEditor extends JSONtoForm { }, }), ); - this.props.setDatasourceEditorMode( - this.props.datasourceId, - false, - ); }} text="EDIT" /> @@ -335,6 +332,7 @@ const mapStateToProps = (state: AppState, props: any) => { const datasourceId = props.datasourceId || props.match?.params?.datasourceId; const { datasourcePane } = state.ui; const { datasources, plugins } = state.entities; + const viewMode = isDatasourceInViewMode(state); const datasource = getDatasource(state, datasourceId); const { formConfigs } = plugins; const formData = getFormValues(DATASOURCE_SAAS_FORM)(state) as Datasource; @@ -369,6 +367,7 @@ const mapStateToProps = (state: AppState, props: any) => { isDeleting: !!datasource?.isDeleting, formData: formData, formConfig, + viewMode: viewMode ?? !props.fromImporting, isNewDatasource: datasourcePane.newDatasource === TEMP_DATASOURCE_ID, pageId: props.pageId || props.match?.params?.pageId, pluginImage: getPluginImages(state)[pluginId], @@ -381,8 +380,6 @@ const mapStateToProps = (state: AppState, props: any) => { applicationId: getCurrentApplicationId(state), canManageDatasource: canManageDatasource, datasourceName: datasource?.name ?? "", - viewMode: - datasourcePane.viewMode[datasource?.id ?? ""] ?? !props.fromImporting, isDatasourceBeingSaved: datasources.isDatasourceBeingSaved, isDatasourceBeingSavedFromPopup: state.entities.datasources.isDatasourceBeingSavedFromPopup, @@ -396,8 +393,8 @@ const mapDispatchToProps = (dispatch: any): DatasourceFormFunctions => ({ toggleSaveActionFlag: (flag) => dispatch(toggleSaveActionFlag(flag)), toggleSaveActionFromPopupFlag: (flag) => dispatch(toggleSaveActionFromPopupFlag(flag)), - setDatasourceEditorMode: (id: string, viewMode: boolean) => - dispatch(setDatsourceEditorMode({ id, viewMode })), + setDatasourceViewMode: (viewMode: boolean) => + dispatch(setDatasourceViewMode(viewMode)), createTempDatasource: (data: any) => dispatch(createTempDatasourceFromForm(data)), }); diff --git a/app/client/src/pages/common/datasourceAuth/index.tsx b/app/client/src/pages/common/datasourceAuth/index.tsx index 923aa59291..7a75676845 100644 --- a/app/client/src/pages/common/datasourceAuth/index.tsx +++ b/app/client/src/pages/common/datasourceAuth/index.tsx @@ -15,6 +15,7 @@ import { updateDatasource, redirectAuthorizationCode, getOAuthAccessToken, + setDatasourceViewMode, createDatasourceFromForm, toggleSaveActionFlag, } from "actions/datasourceActions"; @@ -232,6 +233,7 @@ function DatasourceAuth({ if (datasource.id === TEMP_DATASOURCE_ID) { dispatch(createDatasourceFromForm(getSanitizedFormData())); } else { + dispatch(setDatasourceViewMode(true)); // we dont need to redirect it to active ds list instead ds would be shown in view only mode dispatch(updateDatasource(getSanitizedFormData())); } @@ -250,6 +252,7 @@ function DatasourceAuth({ ), ); } else { + dispatch(setDatasourceViewMode(true)); dispatch( updateDatasource( getSanitizedFormData(), diff --git a/app/client/src/reducers/uiReducers/datasourcePaneReducer.ts b/app/client/src/reducers/uiReducers/datasourcePaneReducer.ts index 36a0adf8cf..9499b7e00b 100644 --- a/app/client/src/reducers/uiReducers/datasourcePaneReducer.ts +++ b/app/client/src/reducers/uiReducers/datasourcePaneReducer.ts @@ -11,7 +11,7 @@ const initialState: DatasourcePaneReduxState = { actionRouteInfo: {}, expandDatasourceId: "", newDatasource: "", - viewMode: {}, + viewMode: true, }; export interface DatasourcePaneReduxState { @@ -24,7 +24,7 @@ export interface DatasourcePaneReduxState { applicationId: string; }>; newDatasource: string; - viewMode: Record; + viewMode: boolean; } const datasourcePaneReducer = createReducer(initialState, { @@ -98,14 +98,11 @@ const datasourcePaneReducer = createReducer(initialState, { }, [ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE]: ( state: DatasourcePaneReduxState, - action: ReduxAction<{ id: string; viewMode: boolean }>, + action: ReduxAction, ) => { return { ...state, - viewMode: { - ...state.viewMode, - [action.payload.id]: action.payload.viewMode, - }, + viewMode: action.payload, }; }, [ReduxActionTypes.EXPAND_DATASOURCE_ENTITY]: ( diff --git a/app/client/src/sagas/DatasourcesSagas.ts b/app/client/src/sagas/DatasourcesSagas.ts index 7265964d0b..a2bb2bde99 100644 --- a/app/client/src/sagas/DatasourcesSagas.ts +++ b/app/client/src/sagas/DatasourcesSagas.ts @@ -34,7 +34,7 @@ import { import { changeDatasource, fetchDatasourceStructure, - setDatsourceEditorMode, + setDatasourceViewMode, updateDatasourceSuccess, UpdateDatasourceSuccessAction, executeDatasourceQueryReduxAction, @@ -353,9 +353,6 @@ function* updateDatasourceSaga( queryParams, ), ); - yield put( - setDatsourceEditorMode({ id: datasourcePayload.id, viewMode: true }), - ); yield put({ type: ReduxActionTypes.DELETE_DATASOURCE_DRAFT, payload: { @@ -365,10 +362,10 @@ function* updateDatasourceSaga( if (actionPayload.onSuccess) { yield put(actionPayload.onSuccess); } - //Refresh datasource structure on save if (expandDatasourceId === response.data.id) { yield put(fetchDatasourceStructure(response.data.id, true)); } + yield put(setDatasourceViewMode(true)); AppsmithConsole.info({ text: "Datasource configuration saved", @@ -668,12 +665,7 @@ function* createTempDatasourceFromFormSaga( payload, }); - yield put( - setDatsourceEditorMode({ - id: payload.id, - viewMode: false, - }), - ); + yield put(setDatasourceViewMode(false)); } function* createDatasourceFromFormSaga( @@ -724,16 +716,6 @@ function* createDatasourceFromFormSaga( yield put( createDatasourceSuccess(response.data, true, !!actionRouteInfo.apiId), ); - // Todo: Refactor later. - // If we move this `put` over to QueryPaneSaga->handleDatasourceCreatedSaga, onboarding tests start failing. - if (response.data.id !== TEMP_DATASOURCE_ID) { - yield put( - setDatsourceEditorMode({ - id: response.data.id, - viewMode: true, - }), - ); - } Toaster.show({ text: createMessage(DATASOURCE_CREATE, response.data.name), @@ -904,9 +886,7 @@ function* storeAsDatasourceSaga() { const createdDatasource = createDatasourceSuccessAction.payload; // Set datasource page to edit mode - yield put( - setDatsourceEditorMode({ id: createdDatasource.id, viewMode: false }), - ); + yield put(setDatasourceViewMode(false)); yield put({ type: ReduxActionTypes.STORE_AS_DATASOURCE_UPDATE, diff --git a/app/client/src/selectors/ui.tsx b/app/client/src/selectors/ui.tsx index 03b525ee21..75e274e1e1 100644 --- a/app/client/src/selectors/ui.tsx +++ b/app/client/src/selectors/ui.tsx @@ -32,3 +32,6 @@ export const getErrorForJSObjectName = (state: AppState, id: string) => export const getFocusedWidget = (state: AppState) => state.ui.widgetDragResize.focusedWidget; + +export const isDatasourceInViewMode = (state: AppState) => + state.ui.datasourcePane.viewMode;