chore: Updating styles and adding docs link for REST API plugin for better UI/UX (#37941)
## Description - Adding docs link for REST API plugin - Updating styles for JS function popover when the name is too long - Updating styles for response pane - Removing edit configuration button next to URL for an API, and adding the datasource tab for API editor as well for a saved API. Also, adding a new icon button in schema tab (now datasource tab) for editing DS configuration. Fixes [#37925](https://github.com/appsmithorg/appsmith/issues/37925) Fixes [#37928](https://github.com/appsmithorg/appsmith/issues/37928) Fixes [#37926](https://github.com/appsmithorg/appsmith/issues/37926) Fixes [#37927](https://github.com/appsmithorg/appsmith/issues/37927) ## Automation /ok-to-test tags="@tag.Datasource, @tag.IDE" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/12234851157> > Commit: 925369c4282e6c2c408283be416ffc0f50608e4c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12234851157&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Datasource, @tag.IDE` > Spec: > <hr>Mon, 09 Dec 2024 12:28:22 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced a new `Datasource` component, enhancing the management of datasource configurations. - Added a new icon, `DatasourceConfigIcon`, to improve visual representation. - Implemented a new `DatasourceInfo` component for displaying datasource details and editing options. - Added a new `DatasourceSelector` component to streamline datasource selection based on plugin context. - **Improvements** - Updated default tab selection logic to prioritize the `Datasource` tab. - Enhanced styling for the `StatusBar` and `StyledSwitchLabel` components for better UI consistency. - Added new access-related messages to the `StatusDisplay` component. - Refined rendering logic for the `StoreAsDatasource` component to improve user interaction. - **Bug Fixes** - Fixed rendering logic for the debugger tabs to ensure accurate display based on user interactions. - Streamlined test logic for the "Edit Datasource" button functionality. - **Documentation** - Updated constant messages for improved clarity and user guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Trisha Anand <trisha@appsmith.com> Co-authored-by: Hetu Nandu <hetu@appsmith.com>
This commit is contained in:
parent
cbfe89ef83
commit
26b05343b4
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ describe(
|
|||
variable: GRAPHQL_VARIABLES,
|
||||
});
|
||||
apiPage.RunAPI();
|
||||
apiPage.SelectPaneTab("Authentication");
|
||||
agHelper.GetNClick(locators._saveDatasource);
|
||||
dataSources.AssertDataSourceInfo([
|
||||
dataManager.dsValues[
|
||||
|
|
|
|||
|
|
@ -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}`)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const StyledSwitchLabel = styled(Text)<{
|
|||
justify-content: space-between;
|
||||
min-width: 9rem;
|
||||
cursor: pointer;
|
||||
word-break: break-all;
|
||||
|
||||
${({ isDisabled }) =>
|
||||
isDisabled &&
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5273 4.91831C12.5456 4.36996 12.8 3.81352 12.8 3.5C12.8 3.18648 12.5456 2.63004 11.5273 2.08169C10.5578 1.55967 9.13609 1.2 7.5 1.2C5.86391 1.2 4.4422 1.55967 3.47273 2.08169C2.45437 2.63004 2.2 3.18648 2.2 3.5C2.2 3.81352 2.45437 4.36996 3.47273 4.91831C4.4422 5.44033 5.86391 5.8 7.5 5.8C9.13609 5.8 10.5578 5.44033 11.5273 4.91831ZM7.5 7C11.0899 7 14 5.433 14 3.5C14 1.567 11.0899 0 7.5 0C3.91015 0 1 1.567 1 3.5C1 5.433 3.91015 7 7.5 7Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.2 3.5V7.5C2.2 7.51705 2.20921 7.59285 2.31238 7.73222C2.41306 7.86821 2.57568 8.0264 2.80319 8.19397C3.25752 8.5286 3.89813 8.84764 4.5904 9.07469C4.90527 9.17796 5.0768 9.51692 4.97353 9.83179C4.87027 10.1467 4.5313 10.3182 4.21643 10.2149C3.43047 9.95715 2.66937 9.58576 2.09155 9.16018C1.80298 8.94764 1.54192 8.70827 1.34793 8.44624C1.15644 8.18759 1 7.86492 1 7.5V3.5H2.2Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.2 7.5V11.5C2.2 11.8823 2.41755 12.2833 2.98457 12.6612C3.55483 13.0412 4.41304 13.3459 5.4954 13.5122C5.82293 13.5626 6.04764 13.8689 5.9973 14.1964C5.94697 14.5239 5.64066 14.7487 5.31313 14.6983C4.12801 14.5162 3.08409 14.1696 2.31909 13.6597C1.55084 13.1478 1 12.4204 1 11.5V7.5H2.2Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5273 4.91831C12.5456 4.36996 12.8 3.81352 12.8 3.5C12.8 3.18648 12.5456 2.63004 11.5273 2.08169C10.5578 1.55967 9.13609 1.2 7.5 1.2C5.86391 1.2 4.4422 1.55967 3.47273 2.08169C2.45437 2.63004 2.2 3.18648 2.2 3.5C2.2 3.81352 2.45437 4.36996 3.47273 4.91831C4.4422 5.44033 5.86391 5.8 7.5 5.8C9.13609 5.8 10.5578 5.44033 11.5273 4.91831ZM7.5 7C11.0899 7 14 5.433 14 3.5C14 1.567 11.0899 0 7.5 0C3.91015 0 1 1.567 1 3.5C1 5.433 3.91015 7 7.5 7Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7998 6.4V3.5H13.9998V6.4C13.9998 6.73137 13.7312 7 13.3998 7C13.0684 7 12.7998 6.73137 12.7998 6.4Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.2 3.5V7.5C2.2 7.51705 2.20921 7.59285 2.31238 7.73222C2.41306 7.86821 2.57568 8.0264 2.80319 8.19397C3.25752 8.5286 3.89813 8.84764 4.5904 9.07469C4.90527 9.17796 5.0768 9.51692 4.97353 9.83179C4.87027 10.1467 4.5313 10.3182 4.21643 10.2149C3.43047 9.95715 2.66937 9.58576 2.09155 9.16018C1.80298 8.94764 1.54192 8.70827 1.34793 8.44624C1.15644 8.18759 1 7.86492 1 7.5V3.5H2.2Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.2 7.5V11.5C2.2 11.8823 2.41755 12.2833 2.98457 12.6612C3.55483 13.0412 4.41304 13.3459 5.4954 13.5122C5.82293 13.5626 6.04764 13.8689 5.9973 14.1964C5.94697 14.5239 5.64066 14.7487 5.31313 14.6983C4.12801 14.5162 3.08409 14.1696 2.31909 13.6597C1.55084 13.1478 1 12.4204 1 11.5V7.5H2.2Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.0179 8.5C11.0179 8.22386 11.2417 8 11.5179 8H11.7179C11.994 8 12.2179 8.22386 12.2179 8.5V8.77256C12.2179 9.00885 12.3852 9.20851 12.6072 9.28943C12.9252 9.40537 13.2172 9.57554 13.4718 9.78876C13.6526 9.9401 13.9086 9.98468 14.1128 9.86681L14.3489 9.73047C14.588 9.5924 14.8938 9.67433 15.0319 9.91348L15.1319 10.0867C15.27 10.3258 15.188 10.6316 14.9489 10.7697L14.7166 10.9038C14.5119 11.022 14.4226 11.267 14.4638 11.4999C14.4929 11.6644 14.508 11.8336 14.508 12.0064C14.508 12.1759 14.4934 12.3419 14.4655 12.5034C14.4252 12.7356 14.5146 12.9796 14.7187 13.0974L14.9489 13.2303C15.188 13.3684 15.27 13.6742 15.1319 13.9133L15.0319 14.0865C14.8938 14.3257 14.588 14.4076 14.3489 14.2695L14.1217 14.1384C13.9169 14.0201 13.6601 14.0654 13.4793 14.2178C13.2229 14.4339 12.9283 14.6063 12.6072 14.7234C12.3852 14.8043 12.2179 15.004 12.2179 15.2402V15.5C12.2179 15.7761 11.994 16 11.7179 16H11.5179C11.2417 16 11.0179 15.7761 11.0179 15.5V15.2409C11.0179 15.0044 10.8503 14.8047 10.6282 14.7239C10.3068 14.6069 10.012 14.4345 9.75538 14.2183C9.57457 14.066 9.3178 14.0208 9.11305 14.139L8.88672 14.2697C8.64758 14.4078 8.34178 14.3258 8.20371 14.0867L8.10371 13.9135C7.96564 13.6743 8.04758 13.3685 8.28672 13.2305L8.51547 13.0984C8.71966 12.9805 8.80901 12.7365 8.7687 12.5042C8.74063 12.3425 8.72601 12.1761 8.72601 12.0064C8.72601 11.8333 8.74122 11.6638 8.77037 11.4991C8.8116 11.2662 8.72239 11.0211 8.51756 10.9028L8.2867 10.7695C8.04756 10.6315 7.96562 10.3257 8.10369 10.0865L8.20369 9.91331C8.34176 9.67417 8.64756 9.59223 8.8867 9.7303L9.12203 9.86616C9.32614 9.98401 9.58207 9.93949 9.76283 9.78823C10.0177 9.57495 10.3099 9.40478 10.6282 9.28893C10.8503 9.20808 11.0179 9.00836 11.0179 8.77196V8.5ZM11.617 13.7769C12.5996 13.7769 13.3961 12.9804 13.3961 11.9978C13.3961 11.0153 12.5996 10.2188 11.617 10.2188C10.6345 10.2188 9.83796 11.0153 9.83796 11.9978C9.83796 12.9804 10.6345 13.7769 11.617 13.7769Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -593,7 +593,7 @@ class EmbeddedDatasourcePathComponent extends React.Component<
|
|||
</Text>
|
||||
</StyledTooltip>
|
||||
)}
|
||||
{displayValue && (
|
||||
{displayValue && shouldSave && (
|
||||
<StoreAsDatasource
|
||||
datasourceId={
|
||||
datasourceObject && "id" in datasourceObject
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function PluginActionResponse() {
|
|||
dispatch(
|
||||
setPluginActionEditorDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.SCHEMA_TAB,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,15 +15,16 @@ import { datasourcesEditorIdURL } from "ee/RouteBuilder";
|
|||
import { DatasourceComponentTypes } from "api/PluginApi";
|
||||
import { getPluginActionDebuggerState } from "PluginActionEditor/store";
|
||||
import { SchemaDisplayStatus, StatusDisplay } from "./StatusDisplay";
|
||||
import DatasourceSelector from "./DatasourceSelector";
|
||||
import { SchemaTables } from "./SchemaTables";
|
||||
import { DatasourceTables } from "./DatasourceTables";
|
||||
import { DatasourceEditEntryPoints } from "constants/Datasource";
|
||||
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
||||
import { isEmpty, omit } from "lodash";
|
||||
import { getQueryParams } from "utils/URLUtils";
|
||||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import { TableColumns } from "./TableColumns";
|
||||
import { BOTTOMBAR_HEIGHT } from "./constants";
|
||||
import { useEditorType } from "ee/hooks";
|
||||
import { useParentEntityInfo } from "ee/hooks/datasourceEditorHooks";
|
||||
import DatasourceInfo from "./DatasourceInfo";
|
||||
|
||||
interface Props {
|
||||
datasourceId: string;
|
||||
|
|
@ -31,7 +32,7 @@ interface Props {
|
|||
currentActionId: string;
|
||||
}
|
||||
|
||||
const Schema = (props: Props) => {
|
||||
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<string>();
|
||||
|
||||
|
|
@ -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 (
|
||||
<>
|
||||
<Flex padding="spaces-3">
|
||||
<DatasourceSelector
|
||||
datasourceId={props.datasourceId}
|
||||
datasourceName={props.datasourceName}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex flexDirection="column" padding="spaces-3">
|
||||
<DatasourceInfo
|
||||
datasourceId={props.datasourceId}
|
||||
datasourceName={props.datasourceName}
|
||||
showEditButton={!isLoading}
|
||||
/>
|
||||
<StatusDisplay
|
||||
editDatasource={editDatasource}
|
||||
errorMessage={
|
||||
|
|
@ -153,7 +154,7 @@ const Schema = (props: Props) => {
|
|||
}
|
||||
state={statusState}
|
||||
/>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ const Schema = (props: Props) => {
|
|||
|
||||
return (
|
||||
<Flex h="100%">
|
||||
<SchemaTables
|
||||
<DatasourceTables
|
||||
currentActionId={props.currentActionId}
|
||||
datasourceId={props.datasourceId}
|
||||
datasourceName={props.datasourceName}
|
||||
|
|
@ -194,4 +195,4 @@ const Schema = (props: Props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export { Schema };
|
||||
export { Datasource };
|
||||
|
|
@ -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 (
|
||||
<Flex alignItems={"center"} gap="spaces-2">
|
||||
<DatasourceSelector
|
||||
datasourceId={datasourceId}
|
||||
datasourceName={datasourceName}
|
||||
/>
|
||||
{showEditButton && (
|
||||
<Tooltip content={createMessage(EDIT_DS_CONFIG)} placement="top">
|
||||
<Button
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={editDatasource}
|
||||
size="sm"
|
||||
startIcon="datasource-config"
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatasourceInfo;
|
||||
|
|
@ -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<Action, CustomProps>({
|
||||
form: API_EDITOR_FORM_NAME,
|
||||
destroyOnUnmount: false,
|
||||
enableReinitialize: true,
|
||||
})(PluginDatasourceSelector);
|
||||
|
|
@ -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<Action, CustomProps> & 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) => {
|
|||
<Flex>
|
||||
<MenuField
|
||||
className={"t--switch-datasource"}
|
||||
formName={QUERY_EDITOR_FORM_NAME}
|
||||
formName={formName}
|
||||
name="datasource.id"
|
||||
options={DATASOURCES_OPTIONS}
|
||||
>
|
||||
|
|
@ -130,9 +133,3 @@ const DatasourceSelector = ({ datasourceId, datasourceName }: Props) => {
|
|||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default reduxForm<Action, CustomProps>({
|
||||
form: QUERY_EDITOR_FORM_NAME,
|
||||
destroyOnUnmount: false,
|
||||
enableReinitialize: true,
|
||||
})(DatasourceSelector);
|
||||
|
|
@ -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<Action, CustomProps>({
|
||||
form: QUERY_EDITOR_FORM_NAME,
|
||||
destroyOnUnmount: false,
|
||||
enableReinitialize: true,
|
||||
})(PluginDatasourceSelector);
|
||||
|
|
@ -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) ? (
|
||||
<ApiDatasourceSelector {...props} formName={API_EDITOR_FORM_NAME} />
|
||||
) : (
|
||||
<QueryDatasourceSelector {...props} formName={QUERY_EDITOR_FORM_NAME} />
|
||||
);
|
||||
};
|
||||
|
||||
export default DatasourceSelector;
|
||||
|
|
@ -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"}
|
||||
>
|
||||
<DatasourceSelector
|
||||
<DatasourceInfo
|
||||
datasourceId={datasourceId}
|
||||
datasourceName={datasourceName}
|
||||
showEditButton
|
||||
/>
|
||||
<Button
|
||||
className="datasourceStructure-refresh"
|
||||
|
|
@ -80,4 +81,4 @@ const SchemaTables = ({
|
|||
);
|
||||
};
|
||||
|
||||
export { SchemaTables };
|
||||
export { DatasourceTables };
|
||||
|
|
@ -16,6 +16,8 @@ import {
|
|||
EDIT_DATASOURCE,
|
||||
LOADING_RECORDS_TITLE_TEXT,
|
||||
CANT_SHOW_SCHEMA,
|
||||
NO_ACCESS_TITLE_TEXT,
|
||||
NO_ACCESS_MESSAGE_TEXT,
|
||||
} from "ee/constants/messages";
|
||||
import { getAssetUrl } from "ee/utils/airgapHelpers";
|
||||
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
|
||||
|
|
@ -28,6 +30,7 @@ enum SchemaDisplayStatus {
|
|||
FAILED = "FAILED",
|
||||
NOCOLUMNS = "NOCOLUMNS",
|
||||
CANTSHOW = "CANTSHOW",
|
||||
NOACCESS = "NOACCESS",
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
|
@ -74,6 +77,11 @@ const StateData: Record<
|
|||
message: createMessage(CANT_SHOW_SCHEMA),
|
||||
image: getAssetUrl(`${ASSETS_CDN_URL}/empty-state.svg`),
|
||||
},
|
||||
NOACCESS: {
|
||||
title: createMessage(NO_ACCESS_TITLE_TEXT),
|
||||
message: createMessage(NO_ACCESS_MESSAGE_TEXT),
|
||||
image: getAssetUrl(`${ASSETS_CDN_URL}/locked-state.svg`),
|
||||
},
|
||||
};
|
||||
|
||||
const StatusDisplay = ({ editDatasource, errorMessage, state }: Props) => {
|
||||
|
|
@ -0,0 +1 @@
|
|||
export * from "./Datasource";
|
||||
|
|
@ -19,5 +19,9 @@ export const SchemaTableContainer = styled(Flex)`
|
|||
.entity-icon > .ads-v2-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.t--entity-name {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
@ -30,9 +30,10 @@ export const StatusBar = styled.div`
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: ${TAB_BAR_HEIGHT}px;
|
||||
padding: 8px;
|
||||
padding: 8px 8px 8px 12px;
|
||||
border-bottom: 1px solid var(--ads-v2-color-border);
|
||||
z-index: var(--ads-v2-z-index-1);
|
||||
background: var(--ads-v2-color-bg);
|
||||
`;
|
||||
|
||||
export const StatusBarInfo = styled.div`
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
export * from "./Schema";
|
||||
|
|
@ -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 { Datasource } from "PluginActionEditor/components/PluginActionResponse/components/DatasourceTab";
|
||||
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";
|
||||
|
|
@ -62,6 +62,20 @@ function usePluginActionResponseTabs() {
|
|||
};
|
||||
|
||||
if (plugin.type === PluginType.API) {
|
||||
if (datasource && "id" in datasource) {
|
||||
tabs.push({
|
||||
key: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
|
||||
title: "Datasource",
|
||||
panelComponent: (
|
||||
<Datasource
|
||||
currentActionId={action.id}
|
||||
datasourceId={datasource?.id || ""}
|
||||
datasourceName={datasource?.name || ""}
|
||||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
tabs.push(
|
||||
{
|
||||
key: DEBUGGER_TAB_KEYS.RESPONSE_TAB,
|
||||
|
|
@ -111,10 +125,10 @@ function usePluginActionResponseTabs() {
|
|||
|
||||
if (showSchema) {
|
||||
tabs.push({
|
||||
key: DEBUGGER_TAB_KEYS.SCHEMA_TAB,
|
||||
title: "Schema",
|
||||
key: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
|
||||
title: "Datasource",
|
||||
panelComponent: (
|
||||
<Schema
|
||||
<Datasource
|
||||
currentActionId={action.id}
|
||||
datasourceId={datasource?.id || ""}
|
||||
datasourceName={datasource?.name || ""}
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@ export const CREATE_NEW_DATASOURCE_DATABASE_HEADER = () => "Databases";
|
|||
export const CREATE_NEW_DATASOURCE_MOST_POPULAR_HEADER = () => "Most popular";
|
||||
export const CREATE_NEW_DATASOURCE_REST_API = () => "REST API";
|
||||
export const SAMPLE_DATASOURCES = () => "Sample datasources";
|
||||
export const EDIT_DS_CONFIG = () => "Edit datasource configuration";
|
||||
|
||||
export const ERROR_EVAL_ERROR_GENERIC = () =>
|
||||
`Unexpected error occurred while evaluating the application`;
|
||||
|
|
@ -2277,18 +2278,22 @@ export const EMPTY_TABLE_MESSAGE_TEXT = () =>
|
|||
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_RECORDS_TITLE_TEXT = () => "Loading columns";
|
||||
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_TITLE_TEXT = () => "Failed to load datasource";
|
||||
export const FAILED_RECORDS_MESSAGE_TEXT = () =>
|
||||
"There was an error connecting to the datasource. Please check the datasource configuration and retry.";
|
||||
"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 NO_ACCESS_TITLE_TEXT = () =>
|
||||
"You do not have access to this datasource";
|
||||
export const NO_ACCESS_MESSAGE_TEXT = () =>
|
||||
"Please contact your workspace administrator to gain access";
|
||||
|
||||
export const DATA_PANE_TITLE = () => "Datasources in your workspace";
|
||||
export const DATASOURCE_LIST_BLANK_DESCRIPTION = () =>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ function DebuggerTabs() {
|
|||
const shouldRender = !(
|
||||
selectedTab === DEBUGGER_TAB_KEYS.RESPONSE_TAB ||
|
||||
selectedTab === DEBUGGER_TAB_KEYS.HEADER_TAB ||
|
||||
selectedTab === DEBUGGER_TAB_KEYS.SCHEMA_TAB
|
||||
selectedTab === DEBUGGER_TAB_KEYS.DATASOURCE_TAB
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export enum DEBUGGER_TAB_KEYS {
|
||||
SCHEMA_TAB = "SCHEMA_TAB",
|
||||
DATASOURCE_TAB = "DATASOURCE_TAB",
|
||||
RESPONSE_TAB = "RESPONSE_TAB",
|
||||
HEADER_TAB = "HEADERS_TAB",
|
||||
ERROR_TAB = "ERROR_TAB",
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export default function Debugger() {
|
|||
const shouldRender = !(
|
||||
selectedResponseTab === DEBUGGER_TAB_KEYS.RESPONSE_TAB ||
|
||||
selectedResponseTab === DEBUGGER_TAB_KEYS.HEADER_TAB ||
|
||||
selectedResponseTab === DEBUGGER_TAB_KEYS.SCHEMA_TAB
|
||||
selectedResponseTab === DEBUGGER_TAB_KEYS.DATASOURCE_TAB
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import { getIDETestState } from "test/factories/AppIDEFactoryUtils";
|
|||
import { PageFactory } from "test/factories/PageFactory";
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import { GoogleSheetFactory } from "test/factories/Actions/GoogleSheetFactory";
|
||||
import { PluginActionContextProvider } from "PluginActionEditor";
|
||||
import { PluginPackageName, PluginType } from "entities/Action";
|
||||
import { DatasourceComponentTypes, UIComponentTypes } from "api/PluginApi";
|
||||
|
||||
const FeatureFlags = {
|
||||
rollout_side_by_side_enabled: true,
|
||||
|
|
@ -326,6 +329,17 @@ describe("IDE URL rendering of Queries", () => {
|
|||
});
|
||||
|
||||
describe("Postgres Routes", () => {
|
||||
const mockPlugin = {
|
||||
id: "plugin_id",
|
||||
name: "Postgres",
|
||||
packageName: PluginPackageName.POSTGRES,
|
||||
type: PluginType.DB,
|
||||
uiComponent: UIComponentTypes.UQIDbEditorForm,
|
||||
datasourceComponent: DatasourceComponentTypes.AutoForm,
|
||||
templates: {},
|
||||
requiresDatasource: true,
|
||||
};
|
||||
|
||||
it("Renders Postgres routes in Full Screen", async () => {
|
||||
const page = PageFactory.build();
|
||||
const anQuery = PostgresFactory.build({
|
||||
|
|
@ -344,7 +358,9 @@ describe("IDE URL rendering of Queries", () => {
|
|||
|
||||
const { getAllByText, getByRole, getByTestId } = render(
|
||||
<Route path={BUILDER_PATH}>
|
||||
<IDE />
|
||||
<PluginActionContextProvider action={anQuery} plugin={mockPlugin}>
|
||||
<IDE />
|
||||
</PluginActionContextProvider>
|
||||
</Route>,
|
||||
{
|
||||
url: `/app/applicationSlug/pageSlug-${page.basePageId}/edit/queries/${anQuery.baseId}`,
|
||||
|
|
@ -402,7 +418,9 @@ describe("IDE URL rendering of Queries", () => {
|
|||
|
||||
const { getAllByText, getByRole, getByTestId } = render(
|
||||
<Route path={BUILDER_PATH}>
|
||||
<IDE />
|
||||
<PluginActionContextProvider action={anQuery} plugin={mockPlugin}>
|
||||
<IDE />
|
||||
</PluginActionContextProvider>
|
||||
</Route>,
|
||||
{
|
||||
url: `/app/applicationSlug/pageSlug-${page.basePageId}/edit/queries/${anQuery.baseId}`,
|
||||
|
|
@ -533,6 +551,17 @@ describe("IDE URL rendering of Queries", () => {
|
|||
});
|
||||
|
||||
describe("Google Sheets Routes", () => {
|
||||
const mockPlugin = {
|
||||
id: "plugin_id",
|
||||
name: "Google Sheets",
|
||||
packageName: PluginPackageName.GOOGLE_SHEETS,
|
||||
type: PluginType.DB,
|
||||
uiComponent: UIComponentTypes.GraphQLEditorForm,
|
||||
datasourceComponent: DatasourceComponentTypes.RestAPIDatasourceForm,
|
||||
templates: {},
|
||||
requiresDatasource: false,
|
||||
};
|
||||
|
||||
it("Renders Google Sheets routes in Full Screen", async () => {
|
||||
const page = PageFactory.build();
|
||||
const anQuery = GoogleSheetFactory.build({
|
||||
|
|
@ -552,7 +581,9 @@ describe("IDE URL rendering of Queries", () => {
|
|||
|
||||
const { getAllByText, getByRole, getByTestId } = render(
|
||||
<Route path={BUILDER_PATH}>
|
||||
<IDE />
|
||||
<PluginActionContextProvider action={anQuery} plugin={mockPlugin}>
|
||||
<IDE />
|
||||
</PluginActionContextProvider>
|
||||
</Route>,
|
||||
{
|
||||
url: `/app/applicationSlug/pageSlug-${page.basePageId}/edit/saas/google-sheets-plugin/api/${anQuery.baseId}`,
|
||||
|
|
@ -603,7 +634,9 @@ describe("IDE URL rendering of Queries", () => {
|
|||
|
||||
const { container, getAllByText, getByRole, getByTestId } = render(
|
||||
<Route path={BUILDER_PATH}>
|
||||
<IDE />
|
||||
<PluginActionContextProvider action={anQuery} plugin={mockPlugin}>
|
||||
<IDE />
|
||||
</PluginActionContextProvider>
|
||||
</Route>,
|
||||
{
|
||||
url: `/app/applicationSlug/pageSlug-${page.basePageId}/edit/saas/google-sheets-plugin/api/${anQuery.baseId}`,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from "ee/constants/messages";
|
||||
import DebuggerLogs from "components/editorComponents/Debugger/DebuggerLogs";
|
||||
import ErrorLogs from "components/editorComponents/Debugger/Errors";
|
||||
import { Schema } from "PluginActionEditor/components/PluginActionResponse/components/Schema";
|
||||
import { Datasource } from "PluginActionEditor/components/PluginActionResponse/components/DatasourceTab";
|
||||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import type { SourceEntity } from "entities/AppsmithConsole";
|
||||
import type { Action } from "entities/Action";
|
||||
|
|
@ -141,7 +141,7 @@ function QueryDebuggerTabs({
|
|||
dispatch(
|
||||
setPluginActionEditorDebuggerState({
|
||||
open: true,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.SCHEMA_TAB,
|
||||
selectedTab: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -217,10 +217,10 @@ function QueryDebuggerTabs({
|
|||
|
||||
if (showSchema && currentActionConfig && currentActionConfig.datasource) {
|
||||
responseTabs.unshift({
|
||||
key: DEBUGGER_TAB_KEYS.SCHEMA_TAB,
|
||||
title: "Schema",
|
||||
key: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
|
||||
title: "Datasource",
|
||||
panelComponent: (
|
||||
<Schema
|
||||
<Datasource
|
||||
currentActionId={currentActionConfig.id}
|
||||
datasourceId={currentActionConfig.datasource.id || ""}
|
||||
datasourceName={datasource?.name || ""}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package com.appsmith.server.migrations.db.ce;
|
||||
|
||||
import com.appsmith.server.domains.Plugin;
|
||||
import io.mongock.api.annotations.ChangeUnit;
|
||||
import io.mongock.api.annotations.Execution;
|
||||
import io.mongock.api.annotations.RollbackExecution;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
@Slf4j
|
||||
@ChangeUnit(order = "064", id = "add_plugin_doc_url_to_rest_api_plugin")
|
||||
public class Migration064AddPluginDocUrlToRestApiPlugin {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
public Migration064AddPluginDocUrlToRestApiPlugin(MongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
@RollbackExecution
|
||||
public void rollbackExecution() {}
|
||||
|
||||
@Execution
|
||||
public void execute() {
|
||||
Query query = new Query().addCriteria(Criteria.where("packageName").is("restapi-plugin"));
|
||||
Update update =
|
||||
new Update().set("documentationLink", "https://docs.appsmith.com/connect-data/reference/rest-api");
|
||||
mongoTemplate.updateMulti(query, update, Plugin.class);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user