diff --git a/app/client/cypress/e2e/Regression/ClientSide/BugTests/DS_Bug25148_Spec.ts b/app/client/cypress/e2e/Regression/ClientSide/BugTests/DS_Bug25148_Spec.ts
index a2c5228fa9dc..83fc9d8a7955 100644
--- a/app/client/cypress/e2e/Regression/ClientSide/BugTests/DS_Bug25148_Spec.ts
+++ b/app/client/cypress/e2e/Regression/ClientSide/BugTests/DS_Bug25148_Spec.ts
@@ -17,10 +17,10 @@ describe(
dataSources.FillAuthAPIUrl();
dataSources.SaveDatasource();
apiPage.CreateApi("API" + uid, "GET", true);
+ agHelper.AssertElementAbsence(apiPage._saveAsDS);
apiPage.SelectPaneTab("Authentication");
- agHelper.AssertElementEnabledDisabled(apiPage._saveAsDS, 0, false);
// Last one if present on the authentication tab.
- agHelper.AssertElementEnabledDisabled(apiPage._saveAsDS, 1, false);
+ agHelper.AssertElementEnabledDisabled(apiPage._saveAsDS, 0, false);
});
});
},
diff --git a/app/client/cypress/e2e/Sanity/Datasources/GraphQL_spec.ts b/app/client/cypress/e2e/Sanity/Datasources/GraphQL_spec.ts
index 33dd9ba475ab..b20e8f054b70 100644
--- a/app/client/cypress/e2e/Sanity/Datasources/GraphQL_spec.ts
+++ b/app/client/cypress/e2e/Sanity/Datasources/GraphQL_spec.ts
@@ -305,6 +305,7 @@ describe(
variable: GRAPHQL_VARIABLES,
});
apiPage.RunAPI();
+ apiPage.SelectPaneTab("Authentication");
agHelper.GetNClick(locators._saveDatasource);
dataSources.AssertDataSourceInfo([
dataManager.dsValues[
diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts
index 58a3099f2b49..85ad360fb8fa 100644
--- a/app/client/cypress/support/Pages/DataSources.ts
+++ b/app/client/cypress/support/Pages/DataSources.ts
@@ -206,7 +206,7 @@ export class DataSources {
".t--datasource-name:contains('" + dsName + "')";
_mandatoryMark = "//span[text()='*']";
_deleteDSHostPort = ".t--delete-field";
- _dsTabSchema = "[data-testid='t--tab-SCHEMA_TAB']";
+ _dsTabSchema = "[data-testid='t--tab-DATASOURCE_TAB']";
private _pageSelectionMenu = "[data-testid='t--page-selection']";
private _pageSelectMenuItem = ".ads-v2-menu__menu-item";
@@ -1891,7 +1891,9 @@ export class DataSources {
cy.intercept("GET", "/api/v1/datasources/*/structure?ignoreCache=*").as(
`getDatasourceStructureUpdated_${ds_entity_name}`,
);
- cy.get("[data-testid=t--tab-SCHEMA_TAB]").first().click({ force: true });
+ cy.get("[data-testid=t--tab-DATASOURCE_TAB]")
+ .first()
+ .click({ force: true });
this.RefreshDatasourceSchema();
this.assertHelper
.WaitForNetworkCall(`@getDatasourceStructureUpdated_${ds_entity_name}`)
diff --git a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx
index 5a5ff05eb1e0..bf7406c6ee75 100644
--- a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx
+++ b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx
@@ -1033,6 +1033,10 @@ const DashboardLineIcon = importSvg(
async () => import("../__assets__/icons/ads/dashboard-line.svg"),
);
+const DatasourceConfigIcon = importSvg(
+ async () => import("../__assets__/icons/ads/datasource-config.svg"),
+);
+
// v3 icons
const JsSquareV3Icon = importSvg(
async () => import("../__assets__/icons/ads/js-square-v3-icon.svg"),
@@ -1173,6 +1177,7 @@ const ICON_LOOKUP = {
"cut-control": CutIcon,
"dashboard-line": DashboardLineIcon,
"database-2-line": Database2Line,
+ "datasource-config": DatasourceConfigIcon,
"datasource-v3": DatasourceV3Icon,
"datasources-2": Datasources2,
"decrease-control": DecreaseIcon,
diff --git a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx
index 96b9bee34147..2b0358ffeee2 100644
--- a/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx
+++ b/app/client/packages/design-system/ads/src/Switch/Switch.styles.tsx
@@ -31,6 +31,7 @@ export const StyledSwitchLabel = styled(Text)<{
justify-content: space-between;
min-width: 9rem;
cursor: pointer;
+ word-break: break-all;
${({ isDisabled }) =>
isDisabled &&
diff --git a/app/client/packages/design-system/ads/src/__assets__/icons/ads/datasource-config.svg b/app/client/packages/design-system/ads/src/__assets__/icons/ads/datasource-config.svg
new file mode 100644
index 000000000000..dbc7387c46f7
--- /dev/null
+++ b/app/client/packages/design-system/ads/src/__assets__/icons/ads/datasource-config.svg
@@ -0,0 +1,10 @@
+
diff --git a/app/client/src/PluginActionEditor/components/PluginActionForm/components/CommonEditorForm/components/EmbeddedDatasourcePathField.tsx b/app/client/src/PluginActionEditor/components/PluginActionForm/components/CommonEditorForm/components/EmbeddedDatasourcePathField.tsx
index 87615cbf7f2f..55511f3b9710 100644
--- a/app/client/src/PluginActionEditor/components/PluginActionForm/components/CommonEditorForm/components/EmbeddedDatasourcePathField.tsx
+++ b/app/client/src/PluginActionEditor/components/PluginActionForm/components/CommonEditorForm/components/EmbeddedDatasourcePathField.tsx
@@ -593,7 +593,7 @@ class EmbeddedDatasourcePathComponent extends React.Component<
)}
- {displayValue && (
+ {displayValue && shouldSave && (
{
+const Datasource = (props: Props) => {
const dispatch = useDispatch();
const datasourceStructure = useSelector((state) =>
@@ -44,7 +45,8 @@ const Schema = (props: Props) => {
getPluginIdFromDatasourceId(state, props.datasourceId),
);
- const currentPageId = useSelector(getCurrentPageId);
+ const editorType = useEditorType(location.pathname);
+ const { parentEntityId } = useParentEntityInfo(editorType);
const [selectedTable, setSelectedTable] = useState();
@@ -107,7 +109,7 @@ const Schema = (props: Props) => {
});
const url = datasourcesEditorIdURL({
- basePageId: currentPageId,
+ baseParentEntityId: parentEntityId,
datasourceId: props.datasourceId,
params: { ...omit(getQueryParams(), "viewMode"), viewMode: false },
generateEditorPath: true,
@@ -137,13 +139,12 @@ const Schema = (props: Props) => {
}
return (
- <>
-
-
-
+
+
{
}
state={statusState}
/>
- >
+
);
};
@@ -164,7 +165,7 @@ const Schema = (props: Props) => {
return (
- {
);
};
-export { Schema };
+export { Datasource };
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceInfo.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceInfo.tsx
new file mode 100644
index 000000000000..e671e70d4afc
--- /dev/null
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceInfo.tsx
@@ -0,0 +1,69 @@
+import React from "react";
+import { Button, Flex, Tooltip } from "@appsmith/ads";
+import DatasourceSelector from "./DatasourceSelector";
+import { createMessage, EDIT_DS_CONFIG } from "ee/constants/messages";
+import { DatasourceEditEntryPoints } from "constants/Datasource";
+import AnalyticsUtil from "ee/utils/AnalyticsUtil";
+import { datasourcesEditorIdURL } from "ee/RouteBuilder";
+import { omit } from "lodash";
+import { getQueryParams } from "utils/URLUtils";
+import history from "utils/history";
+import { useEditorType } from "ee/hooks";
+import { useParentEntityInfo } from "ee/hooks/datasourceEditorHooks";
+
+interface Props {
+ datasourceId: string;
+ datasourceName: string;
+ showEditButton: boolean;
+}
+
+const DatasourceInfo = ({
+ datasourceId,
+ datasourceName,
+ showEditButton,
+}: Props) => {
+ const editorType = useEditorType(location.pathname);
+ const { parentEntityId } = useParentEntityInfo(editorType);
+
+ // eslint-disable-next-line react-perf/jsx-no-new-function-as-prop
+ const editDatasource = () => {
+ const entryPoint = DatasourceEditEntryPoints.QUERY_EDITOR_DATASOURCE_SCHEMA;
+
+ AnalyticsUtil.logEvent("EDIT_DATASOURCE_CLICK", {
+ datasourceId: datasourceId,
+ pluginName: "",
+ entryPoint: entryPoint,
+ });
+
+ const url = datasourcesEditorIdURL({
+ baseParentEntityId: parentEntityId,
+ datasourceId: datasourceId,
+ params: { ...omit(getQueryParams(), "viewMode"), viewMode: false },
+ generateEditorPath: true,
+ });
+
+ history.push(url);
+ };
+
+ return (
+
+
+ {showEditButton && (
+
+
+
+ )}
+
+ );
+};
+
+export default DatasourceInfo;
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/ApiDatasourceSelector.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/ApiDatasourceSelector.tsx
new file mode 100644
index 000000000000..35f70ffffae1
--- /dev/null
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/ApiDatasourceSelector.tsx
@@ -0,0 +1,13 @@
+import { API_EDITOR_FORM_NAME } from "ee/constants/forms";
+import { type Action } from "entities/Action";
+import { reduxForm } from "redux-form";
+import {
+ PluginDatasourceSelector,
+ type CustomProps,
+} from "./PluginDatasourceSelector";
+
+export default reduxForm({
+ form: API_EDITOR_FORM_NAME,
+ destroyOnUnmount: false,
+ enableReinitialize: true,
+})(PluginDatasourceSelector);
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/DatasourceSelector.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/PluginDatasourceSelector.tsx
similarity index 86%
rename from app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/DatasourceSelector.tsx
rename to app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/PluginDatasourceSelector.tsx
index 75e2c0cd81bf..b29c750f07db 100644
--- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/DatasourceSelector.tsx
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/PluginDatasourceSelector.tsx
@@ -20,18 +20,17 @@ import type { AppState } from "ee/reducers";
import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors";
import { useActiveActionBaseId } from "ee/pages/Editor/Explorer/hooks";
import { INTEGRATION_TABS } from "constants/routes";
-import { QUERY_EDITOR_FORM_NAME } from "ee/constants/forms";
import MenuField from "components/editorComponents/form/fields/MenuField";
import type { InjectedFormProps } from "redux-form";
-import { reduxForm } from "redux-form";
-import type { Action } from "entities/Action";
-import { CurrentDataSourceLink } from "./CurrentDataSourceLink";
-import { CurrentDataSource } from "./CurrentDataSource";
+import { type Action } from "entities/Action";
+import { CurrentDataSourceLink } from "../CurrentDataSourceLink";
+import { CurrentDataSource } from "../CurrentDataSource";
import { useCreateDatasource } from "ee/PluginActionEditor/hooks/useCreateDatasource";
-interface CustomProps {
+export interface CustomProps {
datasourceId: string;
datasourceName: string;
+ formName: string;
}
type Props = InjectedFormProps & CustomProps;
@@ -44,7 +43,11 @@ interface DATASOURCES_OPTIONS_TYPE {
onSelect?: (value: string) => void;
}
-const DatasourceSelector = ({ datasourceId, datasourceName }: Props) => {
+export const PluginDatasourceSelector = ({
+ datasourceId,
+ datasourceName,
+ formName,
+}: Props) => {
const activeActionBaseId = useActiveActionBaseId();
const currentActionConfig = useSelector((state) =>
activeActionBaseId
@@ -118,7 +121,7 @@ const DatasourceSelector = ({ datasourceId, datasourceName }: Props) => {
@@ -130,9 +133,3 @@ const DatasourceSelector = ({ datasourceId, datasourceName }: Props) => {
);
};
-
-export default reduxForm({
- form: QUERY_EDITOR_FORM_NAME,
- destroyOnUnmount: false,
- enableReinitialize: true,
-})(DatasourceSelector);
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/QueryDatasourceSelector.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/QueryDatasourceSelector.tsx
new file mode 100644
index 000000000000..ab41909283c0
--- /dev/null
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/QueryDatasourceSelector.tsx
@@ -0,0 +1,13 @@
+import { QUERY_EDITOR_FORM_NAME } from "ee/constants/forms";
+import { type Action } from "entities/Action";
+import { reduxForm } from "redux-form";
+import {
+ PluginDatasourceSelector,
+ type CustomProps,
+} from "./PluginDatasourceSelector";
+
+export default reduxForm({
+ form: QUERY_EDITOR_FORM_NAME,
+ destroyOnUnmount: false,
+ enableReinitialize: true,
+})(PluginDatasourceSelector);
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/index.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/index.tsx
new file mode 100644
index 000000000000..6f3ef2f510f1
--- /dev/null
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceSelector/index.tsx
@@ -0,0 +1,31 @@
+import React from "react";
+import { UIComponentTypes } from "api/PluginApi";
+import { usePluginActionContext } from "PluginActionEditor/PluginActionContext";
+import ApiDatasourceSelector from "./ApiDatasourceSelector";
+import QueryDatasourceSelector from "./QueryDatasourceSelector";
+import {
+ API_EDITOR_FORM_NAME,
+ QUERY_EDITOR_FORM_NAME,
+} from "ee/constants/forms";
+
+const API_FORM_COMPONENTS = [
+ UIComponentTypes.ApiEditorForm,
+ UIComponentTypes.GraphQLEditorForm,
+];
+
+export interface DatasourceProps {
+ datasourceId: string;
+ datasourceName: string;
+}
+
+const DatasourceSelector = (props: DatasourceProps) => {
+ const { plugin } = usePluginActionContext();
+
+ return API_FORM_COMPONENTS.includes(plugin.uiComponent) ? (
+
+ ) : (
+
+ );
+};
+
+export default DatasourceSelector;
diff --git a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/SchemaTables.tsx b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceTables.tsx
similarity index 93%
rename from app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/SchemaTables.tsx
rename to app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceTables.tsx
index 1ee99e4c959c..1664ff7667aa 100644
--- a/app/client/src/PluginActionEditor/components/PluginActionResponse/components/Schema/SchemaTables.tsx
+++ b/app/client/src/PluginActionEditor/components/PluginActionResponse/components/DatasourceTab/DatasourceTables.tsx
@@ -5,10 +5,10 @@ import {
} from "entities/Datasource";
import { DatasourceStructureContainer as DatasourceStructureList } from "pages/Editor/DatasourceInfo/DatasourceStructureContainer";
import React, { useCallback } from "react";
-import DatasourceSelector from "./DatasourceSelector";
import { refreshDatasourceStructure } from "actions/datasourceActions";
import { useDispatch } from "react-redux";
import { SchemaTableContainer } from "./styles";
+import DatasourceInfo from "./DatasourceInfo";
interface Props {
datasourceId: string;
@@ -19,7 +19,7 @@ interface Props {
selectedTable: string | undefined;
}
-const SchemaTables = ({
+const DatasourceTables = ({
currentActionId,
datasourceId,
datasourceName,
@@ -53,9 +53,10 @@ const SchemaTables = ({
gap="spaces-2"
justifyContent={"space-between"}
>
-