diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 37ca1f3379..00485dcf0c 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1903,6 +1903,11 @@ export const ERR_FETCHING_DATASOURCE_PREVIEW_DATA = () => export const FETCHING_DATASOURCE_PREVIEW_DATA = () => "Loading data"; export const SCHEMA_PREVIEW_NO_DATA = () => "No data records to show or the table header begins with an index other than 1"; +export const GSHEET_SPREADSHEET_LABEL = () => "Spreadsheets"; +export const GSHEET_SPREADSHEET_LOADING = () => "Loading Spreadsheets"; +export const GSHEET_SHEET_LOADING = () => "Loading Sheets"; +export const GSHEET_DATA_LOADING = () => "Loading attributes"; +export const GSHEET_SEARCH_PLACEHOLDER = () => "Search for spreadsheet"; //Layout Conversion flow export const CONVERT = () => "Convert layout"; @@ -2161,6 +2166,8 @@ export const COMMUNITY_TEMPLATES = { export const EMPTY_TABLE_TITLE_TEXT = () => "Empty table"; export const EMPTY_TABLE_MESSAGE_TEXT = () => "There are no data records to show"; +export const LOADING_RECORDS_TITLE_TEXT = () => "Loading records"; +export const LOADING_RECORDS_MESSAGE_TEXT = () => "This may take a few seconds"; export const EMPTY_TABLE_SVG_ALT_TEXT = () => "Empty table image"; export const DATA_PANE_TITLE = () => "Datasources in your Workspace"; diff --git a/app/client/src/ce/utils/analyticsUtilTypes.ts b/app/client/src/ce/utils/analyticsUtilTypes.ts index 4e6b552437..d78da69057 100644 --- a/app/client/src/ce/utils/analyticsUtilTypes.ts +++ b/app/client/src/ce/utils/analyticsUtilTypes.ts @@ -350,7 +350,8 @@ export type DATASOURCE_SCHEMA_EVENTS = | "GSHEET_PREVIEW_DATA_SHOWN" | "DATASOURCE_GENERATE_PAGE_BUTTON_CLICKED" | "DATASOURCE_PREVIEW_TABLE_CHANGE" - | "DATASOURCE_PREVIEW_DATA_SHOWN"; + | "DATASOURCE_PREVIEW_DATA_SHOWN" + | "GSHEET_SPREADSHEET_SEARCH"; type WALKTHROUGH_EVENTS = "WALKTHROUGH_DISMISSED" | "WALKTHROUGH_SHOWN"; diff --git a/app/client/src/components/editorComponents/ActionRightPane/index.tsx b/app/client/src/components/editorComponents/ActionRightPane/index.tsx index 5fa318850f..042c625145 100644 --- a/app/client/src/components/editorComponents/ActionRightPane/index.tsx +++ b/app/client/src/components/editorComponents/ActionRightPane/index.tsx @@ -51,6 +51,7 @@ import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { getHasManagePagePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers"; +import type { Datasource } from "entities/Datasource"; import { DatasourceStructureContext } from "entities/Datasource"; const SCHEMA_GUIDE_GIF = `${ASSETS_CDN_URL}/schema.gif`; @@ -152,7 +153,7 @@ const Placeholder = styled.div` `; const DataStructureListWrapper = styled.div` - overflow-y: auto; + overflow-y: hidden; height: 100%; display: flex; flex-direction: column; @@ -176,7 +177,7 @@ interface CollapsibleProps { label: string; CustomLabelComponent?: (props: any) => JSX.Element; isDisabled?: boolean; - datasourceId?: string; + datasource?: Partial; containerRef?: MutableRefObject; } @@ -189,7 +190,7 @@ export function Collapsible({ children, containerRef, CustomLabelComponent, - datasourceId, + datasource, expand = true, label, }: CollapsibleProps) { @@ -220,7 +221,7 @@ export function Collapsible({ /> {!!CustomLabelComponent ? ( handleCollapse(true)} /> ) : ( @@ -427,7 +428,7 @@ function ActionSidebar({ diff --git a/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx b/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx index e3636825e4..eaa4053b6f 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/DatasourceSection.tsx @@ -181,9 +181,11 @@ export function renderDatasourceSection( if ( !value && !!viewMode && - !!section.hidden && - "comparison" in section.hidden && - section.hidden.comparison === ComparisonOperationsEnum.VIEW_MODE + (!section.hidden || + (!!section.hidden && + "comparison" in section.hidden && + section.hidden.comparison === + ComparisonOperationsEnum.VIEW_MODE)) ) { value = section.initialValue; } diff --git a/app/client/src/pages/Editor/DataSourceEditor/Debugger.tsx b/app/client/src/pages/Editor/DataSourceEditor/Debugger.tsx index 65bcc5f526..14c5df524b 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/Debugger.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/Debugger.tsx @@ -78,12 +78,16 @@ export const ResizerContentContainer = styled.div` border-bottom: 1px solid var(--ads-v2-color-border); } } - &.db-form-resizer-content.db-form-resizer-content-show-tabs { + &.db-form-resizer-content.db-form-resizer-content-show-tabs, + &.saas-form-resizer-content.saas-form-resizer-content-show-tabs { padding: 0; & .t--ds-form-header { border-bottom: none; } } + &.saas-form-resizer-content.saas-form-resizer-content-show-tabs form { + padding-bottom: 0; + } border-top: none; .db-form-content-container { display: flex; diff --git a/app/client/src/pages/Editor/DataSourceEditor/index.tsx b/app/client/src/pages/Editor/DataSourceEditor/index.tsx index 08b79ebbe4..26980a75f8 100644 --- a/app/client/src/pages/Editor/DataSourceEditor/index.tsx +++ b/app/client/src/pages/Editor/DataSourceEditor/index.tsx @@ -871,16 +871,9 @@ class DatasourceEditorRouter extends React.Component { }; shouldShowTabs = () => { - const { - isEnabledForDSViewModeSchema, - isPluginAllowedToPreviewData, - pluginDatasourceForm, - } = this.props; - const isRestAPI = - pluginDatasourceForm === DatasourceComponentTypes.RestAPIDatasourceForm; - return ( - isEnabledForDSViewModeSchema && isPluginAllowedToPreviewData && !isRestAPI - ); + const { isEnabledForDSViewModeSchema, isPluginAllowedToPreviewData } = + this.props; + return isEnabledForDSViewModeSchema && isPluginAllowedToPreviewData; }; renderTabsForViewMode = () => { diff --git a/app/client/src/pages/Editor/DatasourceInfo/DatasorceTabs.tsx b/app/client/src/pages/Editor/DatasourceInfo/DatasorceTabs.tsx index 9661bfa318..891aa1cc6e 100644 --- a/app/client/src/pages/Editor/DatasourceInfo/DatasorceTabs.tsx +++ b/app/client/src/pages/Editor/DatasourceInfo/DatasorceTabs.tsx @@ -13,8 +13,11 @@ import DatasourceViewModeSchema from "./DatasourceViewModeSchema"; import { getCurrentEnvironmentId } from "@appsmith/selectors/environmentSelectors"; import { isEnvironmentValid } from "@appsmith/utils/Environments"; import type { Datasource } from "entities/Datasource"; -import { isGoogleSheetPluginDS } from "utils/editorContextUtils"; -import { getPluginNameFromId } from "@appsmith/selectors/entitiesSelector"; +import { + isDatasourceAuthorizedForQueryCreation, + isGoogleSheetPluginDS, +} from "utils/editorContextUtils"; +import { getPlugin } from "@appsmith/selectors/entitiesSelector"; import GoogleSheetSchema from "./GoogleSheetSchema"; const TabsContainer = styled(Tabs)` @@ -55,14 +58,22 @@ const DatasourceTabs = (props: DatasourceTabProps) => { const setDatasourceViewModeFlagClick = (value: boolean) => { dispatch(setDatasourceViewModeFlag(value)); }; - const pluginName = useSelector((state) => - getPluginNameFromId(state, props.datasource.pluginId), + const plugin = useSelector((state) => + getPlugin(state, props.datasource.pluginId), ); - const isGoogleSheetPlugin = isGoogleSheetPluginDS(pluginName); + const isGoogleSheetPlugin = isGoogleSheetPluginDS(plugin?.packageName); + const isPluginAuthorized = + !!plugin && !!props.datasource + ? isDatasourceAuthorizedForQueryCreation( + props.datasource, + plugin, + currentEnvironmentId, + ) + : false; return ( = [ PluginName.OPEN_AI, ]; -const DatasourceStructureSearchContainer = styled.div` - margin-bottom: 8px; - position: sticky; - top: 0; - overflow: hidden; - z-index: 10; - background: white; -`; - const Container = (props: Props) => { const isLoading = useSelector((state: AppState) => getIsFetchingDatasourceStructure(state, props.datasourceId), @@ -113,7 +104,7 @@ const Container = (props: Props) => { const filteredDastasourceStructure = props.datasourceStructure.tables.filter((table) => - table.name.includes(value), + table.name.toLowerCase().includes(value.toLowerCase()), ); setDatasourceStructure({ tables: filteredDastasourceStructure }); @@ -129,7 +120,9 @@ const Container = (props: Props) => { view = ( <> {props.context !== DatasourceStructureContext.EXPLORER && ( - + { placeholder={createMessage( DATASOURCE_STRUCTURE_INPUT_PLACEHOLDER_TEXT, )} - size={"md"} + size={"sm"} startIcon="search" type="text" /> @@ -199,7 +192,7 @@ const Container = (props: Props) => { props.context !== DatasourceStructureContext.EXPLORER && isLoading ) { - view = ; + view = ; } return view; diff --git a/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureHeader.tsx b/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureHeader.tsx index 5fec794940..5344370766 100644 --- a/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureHeader.tsx +++ b/app/client/src/pages/Editor/DatasourceInfo/DatasourceStructureHeader.tsx @@ -1,15 +1,23 @@ import React, { useCallback } from "react"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { Button, Text } from "design-system"; import styled from "styled-components"; import { refreshDatasourceStructure } from "actions/datasourceActions"; -import { SCHEMA_LABEL, createMessage } from "@appsmith/constants/messages"; +import { + GSHEET_SPREADSHEET_LABEL, + SCHEMA_LABEL, + createMessage, +} from "@appsmith/constants/messages"; +import type { Datasource } from "entities/Datasource"; import { DatasourceStructureContext } from "entities/Datasource"; +import { getPluginPackageNameFromId } from "@appsmith/selectors/entitiesSelector"; +import { isGoogleSheetPluginDS } from "utils/editorContextUtils"; interface Props { - datasourceId: string; + datasource?: Datasource; onRefreshCallback?: () => void; paddingBottom?: boolean; + refetchFn?: () => void; } const HeaderWrapper = styled.div<{ paddingBottom: boolean }>` @@ -24,27 +32,41 @@ export default function DatasourceStructureHeader(props: Props) { const dispatch = useDispatch(); const dispatchRefresh = useCallback( - (event: React.MouseEvent) => { - event.stopPropagation(); - dispatch( - refreshDatasourceStructure( - props.datasourceId, - DatasourceStructureContext.QUERY_EDITOR, - ), - ); + (event: React.MouseEvent) => { + if (props.datasource?.id) { + event.stopPropagation(); - !!props.onRefreshCallback && props.onRefreshCallback(); + if (props.refetchFn) { + props.refetchFn(); + } else { + dispatch( + refreshDatasourceStructure( + props.datasource?.id, + DatasourceStructureContext.QUERY_EDITOR, + ), + ); + } + + !!props.onRefreshCallback && props.onRefreshCallback(); + } }, - [dispatch, props.datasourceId], + [dispatch, props.datasource?.id], ); + const pluginPackageName = useSelector((state) => + getPluginPackageNameFromId(state, props.datasource?.pluginId || ""), + ); + const isGoogleSheetPlugin = isGoogleSheetPluginDS(pluginPackageName); + return ( - {createMessage(SCHEMA_LABEL)} + {createMessage( + isGoogleSheetPlugin ? GSHEET_SPREADSHEET_LABEL : SCHEMA_LABEL, + )}