diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.mdx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.mdx new file mode 100644 index 0000000000..3eef0d1cb2 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.mdx @@ -0,0 +1,35 @@ +import { Canvas, Meta } from "@storybook/blocks"; + +import * as EmptyStateStories from "./EmptyState.stories"; + + + +# Empty State + +A placeholder for when there is no data to display. It can be used to guide users on what to do next. + +## Anatomy + +icon: The icon of the file type or the entity type that is being displayed. + +description: The details of the empty state. It should be a short and clear message. + +button: A button that can be used to trigger an action. This is optional. + +### Default implementation + +Below is the default implementation of the Empty State component. It does not have a button. + + + +### With Button + +Button kind can be supplied. If no kind is supplied, default is "secondary". + + + +### With Button but no onClick is supplied + +onClick is optional. If not supplied, the button will not be shown. + + diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.stories.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.stories.tsx new file mode 100644 index 0000000000..9b756418db --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.stories.tsx @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { EmptyState, type EmptyStateProps } from "."; + +const meta: Meta = { + title: "ADS/Templates/Entity Explorer/Empty State", + component: EmptyState, +}; + +export default meta; + +const Template = (props: EmptyStateProps) => { + const { button, description, icon } = props; + + return ( + + ); +}; + +export const Basic = Template.bind({}) as StoryObj; + +Basic.args = { + description: "No data available", + icon: "folder-line", +}; + +export const WithButton = Template.bind({}) as StoryObj; + +WithButton.args = { + description: "No data available", + icon: "file-line", + button: { + text: "Add new", + onClick: () => console.log("Add clicked"), + }, +}; + +export const WithButtonWithoutOnClick = Template.bind({}) as StoryObj; + +WithButtonWithoutOnClick.args = { + description: "No data available", + icon: "file-line", + button: { + text: "Add new", + }, +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.tsx new file mode 100644 index 0000000000..269bc1ecdc --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import { Button, Flex, Icon, Text } from "../../.."; +import type { EmptyStateProps } from "./EmptyState.types"; + +const EmptyState = ({ button, description, icon }: EmptyStateProps) => { + return ( + + + + + + {description} + + {button && button.onClick ? ( + + ) : null} + + ); +}; + +export { EmptyState }; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.types.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.types.ts new file mode 100644 index 0000000000..e77047e508 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/EmptyState.types.ts @@ -0,0 +1,13 @@ +import { type IconNames, type ButtonKind } from "../../.."; + +export interface EmptyStateProps { + icon: IconNames; + description: string; + button?: { + text: string; + onClick?: () => void; + kind?: Extract; + className?: string; + testId?: string; + }; +} diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/index.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/index.ts new file mode 100644 index 0000000000..73c3c2eaf9 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/EmptyState/index.ts @@ -0,0 +1,2 @@ +export { EmptyState } from "./EmptyState"; +export * from "./EmptyState.types"; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.constants.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.constants.ts new file mode 100644 index 0000000000..989f72dd54 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.constants.ts @@ -0,0 +1,4 @@ +export const ExplorerContainerBorder = { + STANDARD: "1px solid var(--ads-v2-color-border)", + NONE: "", +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.stories.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.stories.tsx new file mode 100644 index 0000000000..7a9560cef7 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.stories.tsx @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { type ExplorerContainerProps, ExplorerContainer } from "."; + +import { SearchAndAdd } from ".."; +import { Flex } from "../../../Flex"; + +const meta: Meta = { + title: "ADS/Templates/Entity Explorer/Container", + component: ExplorerContainer, + argTypes: { + borderRight: { + options: ["STANDARD", "NONE"], + control: { type: "select" }, + }, + }, +}; + +export default meta; + +const Template = (props: ExplorerContainerProps) => { + const { borderRight, children, className, height, width } = props; + + return ( + + ); +}; + +export const Basic = Template.bind({}) as StoryObj; + +const Children = () => { + return ( + + + + ); +}; + +Basic.args = { + children: , + borderRight: "STANDARD", + height: "300px", + width: "255px", +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.tsx new file mode 100644 index 0000000000..2674552b44 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { ExplorerContainerBorder, Flex } from "../../.."; +import type { ExplorerContainerProps } from "./ExplorerContainer.types"; + +export const ExplorerContainer = (props: ExplorerContainerProps) => { + return ( + + {props.children} + + ); +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.types.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.types.ts new file mode 100644 index 0000000000..b9638fc983 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/ExplorerContainer.types.ts @@ -0,0 +1,10 @@ +import { type ReactNode } from "react"; +import type { ExplorerContainerBorder } from "./ExplorerContainer.constants"; + +export interface ExplorerContainerProps { + children: ReactNode | ReactNode[]; + borderRight: keyof typeof ExplorerContainerBorder; + className?: string; + width?: string | number; + height?: string | number; +} diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/index.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/index.ts new file mode 100644 index 0000000000..eeb571c08c --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/ExplorerContainer/index.ts @@ -0,0 +1,3 @@ +export { ExplorerContainer } from "./ExplorerContainer"; +export * from "./ExplorerContainer.types"; +export { ExplorerContainerBorder } from "./ExplorerContainer.constants"; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.mdx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.mdx new file mode 100644 index 0000000000..5f817ae34c --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.mdx @@ -0,0 +1,16 @@ +import { Canvas, Meta } from "@storybook/blocks"; + +import * as NoSearchResultStories from "./NoSearchResults.stories"; + + + +# No Search Results + +A placeholder for when there are no search results to display. It can be used to guide users on what to do next. +What you get is an ADS styled message from this component. + +### Default implementation + +Below is the default implementation + + diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.stories.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.stories.tsx new file mode 100644 index 0000000000..4110b78586 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.stories.tsx @@ -0,0 +1,24 @@ +/* eslint-disable no-console */ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { NoSearchResults, type NoSearchResultsProps } from "."; + +const meta: Meta = { + title: "ADS/Templates/Entity Explorer/No Search Results", + component: NoSearchResults, +}; + +export default meta; + +const Template = (props: NoSearchResultsProps) => { + const { text } = props; + + return ; +}; + +export const Basic = Template.bind({}) as StoryObj; + +Basic.args = { + text: "No files found", +}; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.tsx b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.tsx new file mode 100644 index 0000000000..645b4c5d1a --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.tsx @@ -0,0 +1,17 @@ +import React from "react"; +import { Text } from "../../.."; +import type { NoSearchResultsProps } from "./NoSearchResults.types"; + +const NoSearchResults = ({ text }: NoSearchResultsProps) => { + return ( + + {text} + + ); +}; + +export { NoSearchResults }; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.types.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.types.ts new file mode 100644 index 0000000000..74e9a3faf3 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/NoSearchResults.types.ts @@ -0,0 +1,3 @@ +export interface NoSearchResultsProps { + text: string; +} diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/index.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/index.ts new file mode 100644 index 0000000000..d63aea8808 --- /dev/null +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/NoSearchResults/index.ts @@ -0,0 +1,2 @@ +export { NoSearchResults } from "./NoSearchResults"; +export * from "./NoSearchResults.types"; diff --git a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/index.ts b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/index.ts index 2c77164ada..5e42c9c115 100644 --- a/app/client/packages/design-system/ads/src/Templates/EntityExplorer/index.ts +++ b/app/client/packages/design-system/ads/src/Templates/EntityExplorer/index.ts @@ -2,3 +2,6 @@ export { ListItemContainer, ListHeaderContainer } from "./styles"; export { ListWithHeader } from "./ListWithHeader"; export { EditorSegments } from "./EditorSegments"; export * from "./SearchAndAdd"; +export { EmptyState } from "./EmptyState"; +export { NoSearchResults } from "./NoSearchResults"; +export * from "./ExplorerContainer"; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Explorer.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Explorer.tsx index 7896b28f3a..25f31d1b19 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/Explorer.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Explorer.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Flex } from "@appsmith/ads"; +import { ExplorerContainer } from "@appsmith/ads"; import { Switch, useRouteMatch } from "react-router"; import { SentryRoute } from "ee/AppRouter"; import { @@ -26,15 +26,11 @@ const EditorPaneExplorer = () => { const ideViewMode = useSelector(getIDEViewMode); return ( - { ]} /> - + ); }; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx index 077100ed56..88c686152a 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/Add.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useState } from "react"; import SegmentAddHeader from "../components/SegmentAddHeader"; import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; import type { ListItemProps } from "@appsmith/ads"; -import { Flex, SearchInput } from "@appsmith/ads"; +import { Flex, SearchInput, NoSearchResults } from "@appsmith/ads"; import { useDispatch, useSelector } from "react-redux"; import { getCurrentPageId } from "selectors/editorSelectors"; import GroupedList from "../components/GroupedList"; @@ -13,7 +13,6 @@ import { import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils"; import { createAddClassName } from "../utils"; import { FocusEntity } from "navigation/FocusEntity"; -import { EmptySearchResult } from "../components/EmptySearchResult"; import { getIDEViewMode } from "selectors/ideSelectors"; import type { FlexProps } from "@appsmith/ads"; import { EditorViewMode } from "ee/entities/IDE/constants"; @@ -98,8 +97,11 @@ const AddJS = () => { ) : null} {filteredItemGroups.length === 0 && searchTerm !== "" ? ( - ) : null} diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx index f1858a8f66..7aa6667e02 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/BlankState.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { useSelector } from "react-redux"; import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; @@ -7,7 +7,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks"; -import { EmptyState } from "../components/EmptyState"; +import { EmptyState } from "@appsmith/ads"; const BlankState: React.FC = () => { const pagePermissions = useSelector(getPagePermissions); @@ -18,14 +18,21 @@ const BlankState: React.FC = () => { ); const { openAddJS } = useJSAdd(); + const buttonProps = useMemo( + () => ({ + className: "t--add-item", + testId: "t--add-item", + text: createMessage(EDITOR_PANE_TEXTS.js_add_button), + onClick: canCreateActions ? openAddJS : undefined, + }), + [canCreateActions, openAddJS], + ); + return ( ); }; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx index 7812572bc7..e068499e4b 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/List.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import { useSelector } from "react-redux"; -import { Flex, Text, SearchAndAdd } from "@appsmith/ads"; +import { Flex, Text, SearchAndAdd, NoSearchResults } from "@appsmith/ads"; import styled from "styled-components"; import { selectJSSegmentEditorList } from "ee/selectors/appIDESelectors"; @@ -18,7 +18,6 @@ import { FilesContextProvider } from "pages/Editor/Explorer/Files/FilesContextPr import { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks"; import { JSListItem } from "ee/pages/Editor/IDE/EditorPane/JS/ListItem"; import { BlankState } from "./BlankState"; -import { EmptySearchResult } from "../components/EmptySearchResult"; import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; import { filterEntityGroupsBySearchTerm } from "IDE/utils"; @@ -111,8 +110,11 @@ const ListJSObjects = () => { ); })} {filteredItemGroups.length === 0 && searchTerm !== "" ? ( - ) : null} diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx index b28548f126..b262ea2ad4 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/Add.tsx @@ -1,5 +1,10 @@ import React, { useState } from "react"; -import { Flex, SearchInput } from "@appsmith/ads"; +import { + Flex, + SearchInput, + NoSearchResults, + type FlexProps, +} from "@appsmith/ads"; import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; import SegmentAddHeader from "../components/SegmentAddHeader"; @@ -9,10 +14,8 @@ import { useGroupedAddQueryOperations, useQueryAdd, } from "ee/pages/Editor/IDE/EditorPane/Query/hooks"; -import { EmptySearchResult } from "../components/EmptySearchResult"; import { useSelector } from "react-redux"; import { getIDEViewMode } from "selectors/ideSelectors"; -import type { FlexProps } from "@appsmith/ads"; import { EditorViewMode } from "ee/entities/IDE/constants"; import { filterEntityGroupsBySearchTerm } from "IDE/utils"; @@ -66,8 +69,11 @@ const AddQuery = () => { ) : null} {filteredItemGroups.length === 0 && searchTerm !== "" ? ( - ) : null} diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/BlankState.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/BlankState.tsx index 06fff7e028..623b0fafed 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/Query/BlankState.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/BlankState.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { useSelector } from "react-redux"; import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; @@ -6,7 +6,7 @@ import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissi import { getPagePermissions } from "selectors/editorSelectors"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { EmptyState } from "../components/EmptyState"; +import { EmptyState } from "@appsmith/ads"; import { useQueryAdd } from "ee/pages/Editor/IDE/EditorPane/Query/hooks"; const BlankState: React.FC = () => { @@ -18,16 +18,23 @@ const BlankState: React.FC = () => { ); const { openAddQuery } = useQueryAdd(); + const buttonProps = useMemo( + () => ({ + className: "t--add-item", + testId: "t--add-item", + text: createMessage(EDITOR_PANE_TEXTS.query_add_button), + onClick: canCreateActions ? openAddQuery : undefined, + }), + [canCreateActions, openAddQuery], + ); + return ( ); }; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx index 789711f873..6c169fabb6 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/List.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { Flex, Text, SearchAndAdd } from "@appsmith/ads"; +import { Flex, Text, SearchAndAdd, NoSearchResults } from "@appsmith/ads"; import { useSelector } from "react-redux"; import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; @@ -18,7 +18,6 @@ import { useQueryAdd } from "ee/pages/Editor/IDE/EditorPane/Query/hooks"; import { QueryListItem } from "ee/pages/Editor/IDE/EditorPane/Query/ListItem"; import { getShowWorkflowFeature } from "ee/selectors/workflowSelectors"; import { BlankState } from "./BlankState"; -import { EmptySearchResult } from "../components/EmptySearchResult"; import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; import { filterEntityGroupsBySearchTerm } from "IDE/utils"; @@ -95,8 +94,11 @@ const ListQuery = () => { ); })} {filteredItemGroups.length === 0 && searchTerm !== "" ? ( - ) : null} diff --git a/app/client/src/pages/Editor/IDE/EditorPane/UI/List.tsx b/app/client/src/pages/Editor/IDE/EditorPane/UI/List.tsx index 491d89ce9a..7bd081a473 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/UI/List.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/UI/List.tsx @@ -12,7 +12,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; -import { EmptyState } from "../components/EmptyState"; +import { EmptyState } from "@appsmith/ads"; import history from "utils/history"; import { builderURL } from "ee/RouteBuilder"; import styled from "styled-components"; @@ -26,6 +26,7 @@ const ListContainer = styled(Flex)` const ListWidgets = (props: { setFocusSearchInput: (focusSearchInput: boolean) => void; }) => { + const { setFocusSearchInput } = props; const basePageId = useSelector(getCurrentBasePageId) as string; const widgets = useSelector(selectWidgetsForCurrentPage); const pagePermissions = useSelector(getPagePermissions); @@ -41,16 +42,29 @@ const ListWidgets = (props: { }, [widgets?.children]); const addButtonClickHandler = useCallback(() => { - props.setFocusSearchInput(true); + setFocusSearchInput(true); history.push(builderURL({})); - }, []); + }, [setFocusSearchInput]); const widgetsExist = widgets && widgets.children && widgets.children.length > 0; - useEffect(() => { - props.setFocusSearchInput(false); - }, []); + useEffect( + function resetFocusOnSearch() { + setFocusSearchInput(false); + }, + [setFocusSearchInput], + ); + + const blankStateButtonProps = useMemo( + () => ({ + className: "t--add-item", + testId: "t--add-item", + text: createMessage(EDITOR_PANE_TEXTS.widget_add_button), + onClick: canManagePages ? addButtonClickHandler : undefined, + }), + [addButtonClickHandler, canManagePages], + ); return ( ) : canManagePages ? ( /* We show the List Add button when side by side is not enabled */ diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx deleted file mode 100644 index 007aee2e14..0000000000 --- a/app/client/src/pages/Editor/IDE/EditorPane/components/EmptySearchResult.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from "react"; -import { Text } from "@appsmith/ads"; -import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages"; - -const EmptySearchResult = ({ type }: { type: string }) => { - return ( - - {createMessage(EDITOR_PANE_TEXTS.empty_search_result, type)} - - ); -}; - -export { EmptySearchResult }; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/EmptyState.tsx b/app/client/src/pages/Editor/IDE/EditorPane/components/EmptyState.tsx deleted file mode 100644 index 8347215b93..0000000000 --- a/app/client/src/pages/Editor/IDE/EditorPane/components/EmptyState.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from "react"; -import { Button, Flex, Text, Icon } from "@appsmith/ads"; - -interface EmptyStateProps { - icon: string; - description: string; - buttonText: string; - onClick?: () => void; - buttonClassName?: string; - buttonTestId?: string; -} - -const EmptyState = ({ - buttonClassName, - buttonTestId, - buttonText, - description, - icon, - onClick, -}: EmptyStateProps) => { - return ( - - - - - - {description} - - {onClick && ( - - )} - - ); -}; - -export { EmptyState }; diff --git a/app/client/src/pages/Editor/IDE/EditorPane/index.tsx b/app/client/src/pages/Editor/IDE/EditorPane/index.tsx index 03e4755aa9..5f52076057 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/index.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Flex } from "@appsmith/ads"; +import { ExplorerContainerBorder, Flex } from "@appsmith/ads"; import EditorPaneExplorer from "./Explorer"; import Editor from "./Editor"; import { useSelector } from "react-redux"; @@ -14,8 +14,8 @@ const EditorPane = () => { { // @ts-expect-error Fix this the next time the file is edited gap="spacing-2" height="100%" - width={"100%"} + width="100%" > {/** Entity Properties component is necessary to render the Bindings popover in the context menu. diff --git a/app/client/src/pages/Editor/IDE/LeftPane/DataSidePane.tsx b/app/client/src/pages/Editor/IDE/LeftPane/DataSidePane.tsx index 6f590fea20..914f070f81 100644 --- a/app/client/src/pages/Editor/IDE/LeftPane/DataSidePane.tsx +++ b/app/client/src/pages/Editor/IDE/LeftPane/DataSidePane.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import styled from "styled-components"; import { Flex, List, Text } from "@appsmith/ads"; import { useSelector } from "react-redux"; @@ -27,7 +27,7 @@ import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors" import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getHasCreateDatasourcePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; -import { EmptyState } from "../EditorPane/components/EmptyState"; +import { EmptyState } from "@appsmith/ads"; import { getAssetUrl } from "ee/utils/airgapHelpers"; import { getCurrentBasePageId } from "selectors/editorSelectors"; @@ -86,13 +86,24 @@ const DataSidePane = (props: DataSidePaneProps) => { userWorkspacePermissions, ); - const addButtonClickHandler = () => + const addButtonClickHandler = useCallback(() => { history.push( integrationEditorURL({ basePageId, selectedTab: INTEGRATION_TABS.NEW, }), ); + }, [basePageId]); + + const blankStateButtonProps = useMemo( + () => ({ + className: "t--add-datasource-button-blank-screen", + testId: "t--add-datasource-button-blank-screen", + text: createMessage(DATA_PANE_TITLE), + onClick: canCreateDatasource ? addButtonClickHandler : undefined, + }), + [addButtonClickHandler, canCreateDatasource], + ); return ( { {datasources.length === 0 ? ( ) : null}