diff --git a/app/client/cypress/e2e/Regression/ClientSide/BugTests/DatasourceSchema_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/BugTests/DatasourceSchema_spec.ts index 9608ee564cbd..0ed9a482eb3a 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/BugTests/DatasourceSchema_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/BugTests/DatasourceSchema_spec.ts @@ -79,7 +79,7 @@ describe( "public.users", ); dataSources.SelectTableFromPreviewSchemaList("public.users"); - dataSources.VerifyColumnSchemaOnQueryEditor("id", 1); + dataSources.VerifyColumnSchemaOnQueryEditor("id", 0); }, ); diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index 059bf5413b88..003193e2e9a8 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -265,7 +265,7 @@ export class DataSources { "')]/ancestor::div[@class='form-config-top']/following-sibling::div//div[contains(@class, 'rc-select-multiple')]"; private _datasourceSchemaRefreshBtn = ".datasourceStructure-refresh"; private _datasourceStructureHeader = ".datasourceStructure-header"; - _datasourceSchemaColumn = ".t--datasource-column"; + _datasourceSchemaColumn = ".t--datasource-column .t--field-name"; _datasourceStructureSearchInput = ".datasourceStructure-search input"; _jsModeSortingControl = ".t--actionConfiguration\\.formData\\.sortBy\\.data"; public _queryEditorCollapsibleIcon = ".collapsible-icon"; @@ -296,7 +296,7 @@ export class DataSources { _imgFireStoreLogo = "//img[contains(@src, 'firestore.svg')]"; _dsVirtuosoElement = `div .t--schema-virtuoso-container`; private _dsVirtuosoList = `[data-test-id="virtuoso-item-list"]`; - private _dsSchemaContainer = `[data-testid="datasource-schema-container"]`; + private _dsSchemaContainer = `[data-testid="t--datasource-schema-container"]`; private _dsVirtuosoElementTable = (targetTableName: string) => `${this._dsSchemaEntityItem}[data-testid='t--entity-item-${targetTableName}']`; private _dsPageTabListItem = (buttonText: string) => diff --git a/app/client/src/IDE/Components/BottomView.tsx b/app/client/src/IDE/Components/BottomView.tsx index 1c8b8f870190..7ed23f18beee 100644 --- a/app/client/src/IDE/Components/BottomView.tsx +++ b/app/client/src/IDE/Components/BottomView.tsx @@ -38,6 +38,7 @@ const ViewWrapper = styled.div` & { .ads-v2-tabs__list { padding: var(--ads-v2-spaces-1) var(--ads-v2-spaces-7); + padding-left: var(--ads-v2-spaces-3); } } diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema.tsx deleted file mode 100644 index 7305c7a13927..000000000000 --- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema.tsx +++ /dev/null @@ -1,210 +0,0 @@ -import { Button, Flex, Link } from "@appsmith/ads"; -import React, { useCallback, useEffect, useState } from "react"; -import { - DatasourceStructureContext, - type DatasourceColumns, - type DatasourceKeys, -} from "entities/Datasource"; -import { DatasourceStructureContainer as DatasourceStructureList } from "pages/Editor/DatasourceInfo/DatasourceStructureContainer"; -import { useDispatch, useSelector } from "react-redux"; -import { - getDatasourceStructureById, - getIsFetchingDatasourceStructure, - getPluginImages, - getPluginIdFromDatasourceId, - getPluginDatasourceComponentFromId, -} from "ee/selectors/entitiesSelector"; -import DatasourceField from "pages/Editor/DatasourceInfo/DatasourceField"; -import { find } from "lodash"; -import type { AppState } from "ee/reducers"; -import RenderInterimDataState from "pages/Editor/DatasourceInfo/RenderInterimDataState"; -import { getPluginActionDebuggerState } from "../../../store"; -import { - fetchDatasourceStructure, - refreshDatasourceStructure, -} from "actions/datasourceActions"; -import history from "utils/history"; -import { datasourcesEditorIdURL } from "ee/RouteBuilder"; -import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons"; -import { getAssetUrl } from "ee/utils/airgapHelpers"; -import { DatasourceComponentTypes } from "api/PluginApi"; - -interface Props { - datasourceId: string; - datasourceName: string; - currentActionId: string; -} - -const Schema = (props: Props) => { - const dispatch = useDispatch(); - - const datasourceStructure = useSelector((state) => - getDatasourceStructureById(state, props.datasourceId), - ); - const { responseTabHeight } = useSelector(getPluginActionDebuggerState); - - const pluginId = useSelector((state) => - getPluginIdFromDatasourceId(state, props.datasourceId), - ); - const pluginImages = useSelector((state) => getPluginImages(state)); - const datasourceIcon = pluginId ? pluginImages[pluginId] : undefined; - - const [selectedTable, setSelectedTable] = useState(); - - const selectedTableItems = find(datasourceStructure?.tables, [ - "name", - selectedTable, - ]); - - const columnsAndKeys: Array = []; - - if (selectedTableItems) { - columnsAndKeys.push(...selectedTableItems.keys); - columnsAndKeys.push(...selectedTableItems.columns); - } - - const columns = - find(datasourceStructure?.tables, ["name", selectedTable])?.columns || []; - - const isLoading = useSelector((state: AppState) => - getIsFetchingDatasourceStructure(state, props.datasourceId), - ); - - const pluginDatasourceForm = useSelector((state) => - getPluginDatasourceComponentFromId(state, pluginId || ""), - ); - - useEffect(() => { - setSelectedTable(undefined); - }, [props.datasourceId]); - - useEffect(() => { - if ( - props.datasourceId && - datasourceStructure === undefined && - pluginDatasourceForm !== DatasourceComponentTypes.RestAPIDatasourceForm - ) { - dispatch( - fetchDatasourceStructure( - props.datasourceId, - true, - DatasourceStructureContext.QUERY_EDITOR, - ), - ); - } - }, [props.datasourceId, datasourceStructure, dispatch, pluginDatasourceForm]); - - useEffect(() => { - if (!selectedTable && datasourceStructure?.tables?.length && !isLoading) { - setSelectedTable(datasourceStructure.tables[0].name); - } - }, [selectedTable, props.datasourceId, isLoading, datasourceStructure]); - - const refreshStructure = useCallback(() => { - dispatch( - refreshDatasourceStructure( - props.datasourceId, - DatasourceStructureContext.QUERY_EDITOR, - ), - ); - }, [dispatch, props.datasourceId]); - - const goToDatasource = useCallback(() => { - history.push(datasourcesEditorIdURL({ datasourceId: props.datasourceId })); - }, [props.datasourceId]); - - if (!datasourceStructure) { - return ( - - {isLoading ? ( - - ) : ( - - )} - - ); - } - - return ( - - - - - - - entityIcon - - {props.datasourceName} - - - + )} + + + ); +}; + +export { StatusDisplay, SchemaDisplayStatus }; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/TableColumns.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/TableColumns.tsx new file mode 100644 index 000000000000..9acc816d3173 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/TableColumns.tsx @@ -0,0 +1,143 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import { Flex, type FlexProps, SearchInput, Text } from "@appsmith/ads"; +import { find } from "lodash"; + +import type { DatasourceStructure } from "entities/Datasource"; +import { StatusDisplay, SchemaDisplayStatus } from "./StatusDisplay"; +import DatasourceField from "pages/Editor/DatasourceInfo/DatasourceField"; +import { + COLUMNS_SEARCH_PLACEHOLDER, + COLUMNS_TITLE, + createMessage, +} from "ee/constants/messages"; +import Fuse from "fuse.js"; +import { TableColumn } from "./styles"; + +interface Props { + isLoading: boolean; + datasourceStructure: DatasourceStructure; + selectedTable: string | undefined; +} + +const Wrapper: React.FC = (props) => { + return ( + + {props.children} + + ); +}; + +const TableColumns: React.FC = ({ + datasourceStructure, + isLoading, + selectedTable, +}) => { + // Find selected table items + const selectedTableItems = useMemo( + () => + find(datasourceStructure?.tables, { name: selectedTable }) ?? { + columns: [], + keys: [], + }, + [datasourceStructure, selectedTable], + ); + + // Combine columns and keys + const columns = useMemo(() => { + return selectedTableItems.columns.map((column) => ({ + name: column.name, + type: column.type, + keys: selectedTableItems.keys + .filter( + (key) => + key.columnNames?.includes(column.name) || + key.fromColumns?.includes(column.name), + ) + .map((key) => key.type), + })); + }, [selectedTableItems]); + + // search + const columnsFuzy = useMemo( + () => + new Fuse(columns, { + keys: ["name"], + shouldSort: true, + threshold: 0.5, + location: 0, + }), + [columns], + ); + + const [term, setTerm] = useState(""); + const filteredColumns = useMemo( + () => (term ? columnsFuzy.search(term) : columns), + [term, columns, columnsFuzy], + ); + + const handleSearch = useCallback((value: string) => setTerm(value), []); + + // Reset term whenever selectedTable changes + useEffect( + function clearTerm() { + setTerm(""); + }, + [selectedTable], + ); + + // loading status + if (isLoading) { + return ( + + + + ); + } + + // no columns status + if (columns.length === 0) { + return ( + + + + ); + } + + return ( + + + {createMessage(COLUMNS_TITLE)} + + + + + + {filteredColumns.map((field, index) => ( + + ))} + + + ); +}; + +export { TableColumns }; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/constants.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/constants.tsx new file mode 100644 index 000000000000..15cad6174cd6 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/constants.tsx @@ -0,0 +1,2 @@ +// This is bottom bar height + paddings +export const BOTTOMBAR_HEIGHT = 42; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/index.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/index.tsx new file mode 100644 index 000000000000..5501a546df7f --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/index.tsx @@ -0,0 +1 @@ +export * from "./Schema"; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/styles.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/styles.ts new file mode 100644 index 000000000000..991b30c25e8d --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/styles.ts @@ -0,0 +1,23 @@ +import styled from "styled-components"; +import { Flex } from "@appsmith/ads"; + +export const TableColumn = styled(Flex)` + & .t--datasource-column { + padding: 0; + + & > div { + margin: 0; + } + } +`; + +export const SchemaTableContainer = styled(Flex)` + & .t--entity-item { + height: 28px; + grid-template-columns: 0 auto 1fr auto auto auto auto auto; + + .entity-icon > .ads-v2-icon { + display: none; + } + } +`; diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/hooks/useGoToDatasource.ts b/app/client/src/PluginActionEditor/components/PluginActionResponse/hooks/useGoToDatasource.ts new file mode 100644 index 000000000000..f28ef61c23e0 --- /dev/null +++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/hooks/useGoToDatasource.ts @@ -0,0 +1,15 @@ +import { useCallback } from "react"; +import { datasourcesEditorIdURL } from "ee/RouteBuilder"; +import history from "utils/history"; + +function useGoToDatasource() { + const goToDatasource = useCallback((datasourceId: string) => { + history.push( + datasourcesEditorIdURL({ datasourceId, generateEditorPath: true }), + ); + }, []); + + return { goToDatasource }; +} + +export { useGoToDatasource }; diff --git a/app/client/src/ce/PluginActionEditor/components/PluginActionResponse/hooks/usePluginActionResponseTabs.tsx b/app/client/src/ce/PluginActionEditor/components/PluginActionResponse/hooks/usePluginActionResponseTabs.tsx index 0b44436bf908..35a87e5341a1 100644 --- a/app/client/src/ce/PluginActionEditor/components/PluginActionResponse/hooks/usePluginActionResponseTabs.tsx +++ b/app/client/src/ce/PluginActionEditor/components/PluginActionResponse/hooks/usePluginActionResponseTabs.tsx @@ -25,7 +25,7 @@ import { } from "PluginActionEditor/store"; import { doesPluginRequireDatasource } from "ee/entities/Engine/actionHelpers"; import useShowSchema from "PluginActionEditor/components/PluginActionResponse/hooks/useShowSchema"; -import Schema from "PluginActionEditor/components/PluginActionResponse/components/Schema"; +import { Schema } from "PluginActionEditor/components/PluginActionResponse/components/Schema"; import QueryResponseTab from "PluginActionEditor/components/PluginActionResponse/components/QueryResponseTab"; import type { SourceEntity } from "entities/AppsmithConsole"; import { ENTITY_TYPE as SOURCE_ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils"; diff --git a/app/client/src/ce/PluginActionEditor/hooks/useCreateDatasource.ts b/app/client/src/ce/PluginActionEditor/hooks/useCreateDatasource.ts new file mode 100644 index 000000000000..7ee726376222 --- /dev/null +++ b/app/client/src/ce/PluginActionEditor/hooks/useCreateDatasource.ts @@ -0,0 +1,27 @@ +import { useCallback } from "react"; +import { integrationEditorURL } from "ee/RouteBuilder"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { DatasourceCreateEntryPoints } from "constants/Datasource"; +import history from "utils/history"; + +function useCreateDatasource() { + const onCreateDatasourceClick = useCallback( + (selectedTab, pageId?: string) => { + history.push( + integrationEditorURL({ + basePageId: pageId, + selectedTab, + }), + ); + + AnalyticsUtil.logEvent("NAVIGATE_TO_CREATE_NEW_DATASOURCE_PAGE", { + entryPoint: DatasourceCreateEntryPoints.QUERY_EDITOR, + }); + }, + [], + ); + + return { onCreateDatasourceClick }; +} + +export { useCreateDatasource }; diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index f525c40f0d38..d3dc228d3f1a 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -365,7 +365,7 @@ export const DATASOURCE_UPDATE = (dsName: string) => `${dsName} datasource updated successfully`; export const DATASOURCE_VALID = (dsName: string) => `${dsName} datasource is valid`; -export const EDIT_DATASOURCE = () => "Edit"; +export const EDIT_DATASOURCE = () => "Edit configuration"; export const SAVE_DATASOURCE = () => "Save URL"; export const EDIT_DATASOURCE_TOOLTIP = () => "Edit datasource"; export const SAVE_DATASOURCE_TOOLTIP = () => "Save URL as a datasource"; @@ -804,7 +804,7 @@ export const SCHEMA_NOT_AVAILABLE = () => "We can't show schema for this datasource"; export const TABLE_NOT_FOUND = () => "Table not found."; export const DATASOURCE_STRUCTURE_INPUT_PLACEHOLDER_TEXT = (name: string) => - `Tables in ${name}`; + `Search tables in ${name}`; export const SCHEMA_LABEL = () => "Schema"; export const STRUCTURE_NOT_FETCHED = () => "We could not fetch the schema of the database."; @@ -2270,14 +2270,24 @@ export const COMMUNITY_TEMPLATES = { // Interim data state info export const EMPTY_TABLE_TITLE_TEXT = () => "Empty table"; +export const EMPTY_SCHEMA_TITLE_TEXT = () => "Empty schema"; export const EMPTY_TABLE_MESSAGE_TEXT = () => "There are no data records to show"; +export const EMPTY_SCHEMA_MESSAGE_TEXT = () => + "There are no schema records to show"; export const NO_COLUMNS_MESSAGE_TEXT = () => "There are no columns to show"; export const LOADING_RECORDS_TITLE_TEXT = () => "Loading records"; +export const LOADING_SCHEMA_TITLE_TEXT = () => "Loading schema"; export const LOADING_RECORDS_MESSAGE_TEXT = () => "This may take a few seconds"; export const FAILED_RECORDS_TITLE_TEXT = () => "Failed to load"; export const FAILED_RECORDS_MESSAGE_TEXT = () => - "There was an error connecting to the datasource. Please check the datasource configuration and retry. If the issue persists, review the datasource settings."; + "There was an error connecting to the datasource. Please check the datasource configuration and retry."; +export const DATASOURCE_SWITCHER_MENU_GROUP_NAME = () => "Select a datasource"; +export const CANT_SHOW_SCHEMA = () => + "We can’t show the schema for this datasource"; +export const COLUMNS_TITLE = () => "Columns"; +export const COLUMNS_SEARCH_PLACEHOLDER = (tableName: string) => + `Search columns in ${tableName}`; export const DATA_PANE_TITLE = () => "Datasources in your workspace"; export const DATASOURCE_LIST_BLANK_DESCRIPTION = () => diff --git a/app/client/src/components/editorComponents/form/fields/MenuField.tsx b/app/client/src/components/editorComponents/form/fields/MenuField.tsx new file mode 100644 index 000000000000..96ad94156bdb --- /dev/null +++ b/app/client/src/components/editorComponents/form/fields/MenuField.tsx @@ -0,0 +1,87 @@ +import { + Button, + Menu, + MenuContent, + MenuGroupName, + MenuTrigger, + Text, + MenuGroup, + MenuItem, + Flex, + Icon, +} from "@appsmith/ads"; +import { getAssetUrl } from "ee/utils/airgapHelpers"; +import React from "react"; +import { type WrappedFieldProps, type BaseFieldProps, Field } from "redux-form"; + +interface iOption { + value: string; + label: string; + icon?: string; + image?: string; + onSelect?: (value: string) => void; +} + +interface iMenuFieldProps { + options: iOption[]; + children: React.ReactNode; + className?: string; + groupName?: string; +} + +const MenuFieldRender = (props: iMenuFieldProps & WrappedFieldProps) => { + const { children, groupName, input, options } = props; + + const handleMenuSelect = (option: iOption) => { + if (option.onSelect) { + option.onSelect(option.value); // Trigger custom onSelect + } else { + input.onChange(option.value); // Default behavior + } + }; + + return ( + + + + + + {groupName && ( + + {groupName} + + )} + + {options.map((option) => ( + handleMenuSelect(option)} + > + + {option.image && ( + Datasource + )} + {option.icon && } + {option.label} + + + ))} + + + + ); +}; + +const MenuField = ( + props: BaseFieldProps & iMenuFieldProps & { formName: string }, +) => ( + +); + +export default MenuField; diff --git a/app/client/src/ee/PluginActionEditor/hooks/useCreateDatasource.ts b/app/client/src/ee/PluginActionEditor/hooks/useCreateDatasource.ts new file mode 100644 index 000000000000..8f932b705461 --- /dev/null +++ b/app/client/src/ee/PluginActionEditor/hooks/useCreateDatasource.ts @@ -0,0 +1 @@ +export * from "ce/PluginActionEditor/hooks/useCreateDatasource"; diff --git a/app/client/src/entities/Datasource/index.ts b/app/client/src/entities/Datasource/index.ts index 9a0c30c352a4..2bb69a96b9d5 100644 --- a/app/client/src/entities/Datasource/index.ts +++ b/app/client/src/entities/Datasource/index.ts @@ -66,6 +66,7 @@ export interface DatasourceKeys { name: string; type: string; columnNames: string[]; + fromColumns: string[]; } export interface DatasourceStructure { diff --git a/app/client/src/pages/Editor/DatasourceInfo/DatasourceField.tsx b/app/client/src/pages/Editor/DatasourceInfo/DatasourceField.tsx index ec9fd5e23d0e..98355cf2bfb7 100644 --- a/app/client/src/pages/Editor/DatasourceInfo/DatasourceField.tsx +++ b/app/client/src/pages/Editor/DatasourceInfo/DatasourceField.tsx @@ -1,11 +1,7 @@ import React, { useRef } from "react"; -import { - DATASOURCE_FIELD_ICONS_MAP, - datasourceColumnIcon, -} from "../Explorer/ExplorerIcons"; +import { DATASOURCE_FIELD_ICONS_MAP } from "../Explorer/ExplorerIcons"; import styled from "styled-components"; -import type { DatasourceColumns, DatasourceKeys } from "entities/Datasource"; -import { Tooltip } from "@appsmith/ads"; +import { Tooltip, Tag, Flex } from "@appsmith/ads"; import { isEllipsisActive } from "utils/helpers"; const Wrapper = styled.div<{ step: number }>` @@ -21,33 +17,41 @@ const Wrapper = styled.div<{ step: number }>` const FieldName = styled.div` color: var(--ads-v2-color-fg); - flex: 1; - font-size: 12px; + font-size: 14px; white-space: nowrap; overflow: hidden; - line-height: 13px; text-overflow: ellipsis; - padding-right: 30px; `; const FieldValue = styled.div` + color: var(--ads-v2-color-fg-subtle); text-align: right; - font-size: 10px; - line-height: 12px; + font-size: 14px; font-weight: 300; `; const Content = styled.div` margin: 0px 4px; - flex: 1; flex-direction: row; min-width: 0; display: flex; - justify-content: space-between; + gap: var(--ads-v2-spaces-2); `; +const FieldKeyLabel = styled.span` + &:first-letter { + text-transform: capitalize; + } +`; + +interface FieldProps { + name: string; + type: string; + keys?: string[]; +} + interface DatabaseFieldProps { - field: DatasourceColumns | DatasourceKeys; + field: FieldProps; step: number; } @@ -55,12 +59,15 @@ export function DatabaseColumns(props: DatabaseFieldProps) { const field = props.field; const fieldName = field.name; const fieldType = field.type; - const icon = DATASOURCE_FIELD_ICONS_MAP[fieldType] || datasourceColumnIcon; + const fieldKeys = field.keys; + const icon = + fieldKeys && fieldKeys.length > 0 + ? DATASOURCE_FIELD_ICONS_MAP[fieldKeys[0]] + : null; const nameRef = useRef(null); return ( - {icon} - {fieldName} + + {fieldName} + {fieldType} + {icon && fieldKeys && ( + + + {icon} + {fieldKeys[0]} + + + )} ); diff --git a/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureNotFound.tsx b/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureNotFound.tsx index 35512803cf19..e7225a364e22 100644 --- a/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureNotFound.tsx +++ b/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureNotFound.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback } from "react"; import { useSelector } from "react-redux"; import styled from "styled-components"; import { Text, Button } from "@appsmith/ads"; @@ -42,7 +42,7 @@ const DatasourceStructureNotFound = (props: Props) => { const basePageId = useSelector(getCurrentBasePageId); - const editDatasource = () => { + const editDatasource = useCallback(() => { let entryPoint = DatasourceEditEntryPoints.QUERY_EDITOR_DATASOURCE_SCHEMA; if (props.context === DatasourceStructureContext.DATASOURCE_VIEW_MODE) { @@ -69,7 +69,7 @@ const DatasourceStructureNotFound = (props: Props) => { }); history.push(url); - }; + }, [basePageId, datasourceId, pluginName, props]); return ( diff --git a/app/client/src/pages/Editor/DatasourceInfo/DatasourceViewModeSchema.tsx b/app/client/src/pages/Editor/DatasourceInfo/DatasourceViewModeSchema.tsx index 6464e0a52675..33ccf5c49c2f 100644 --- a/app/client/src/pages/Editor/DatasourceInfo/DatasourceViewModeSchema.tsx +++ b/app/client/src/pages/Editor/DatasourceInfo/DatasourceViewModeSchema.tsx @@ -246,7 +246,7 @@ const DatasourceViewModeSchema = (props: Props) => { return ( - + {props.datasource && ( - + {datasource && (