chore: Move smaller Entity Explorer components into ADS (#38321)
This commit is contained in:
parent
d3ea54d6a2
commit
ddb83c0094
|
|
@ -0,0 +1,35 @@
|
|||
import { Canvas, Meta } from "@storybook/blocks";
|
||||
|
||||
import * as EmptyStateStories from "./EmptyState.stories";
|
||||
|
||||
<Meta of={EmptyStateStories} />
|
||||
|
||||
# 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.
|
||||
|
||||
<Canvas of={EmptyStateStories.Basic} />
|
||||
|
||||
### With Button
|
||||
|
||||
Button kind can be supplied. If no kind is supplied, default is "secondary".
|
||||
|
||||
<Canvas of={EmptyStateStories.WithButton} />
|
||||
|
||||
### With Button but no onClick is supplied
|
||||
|
||||
onClick is optional. If not supplied, the button will not be shown.
|
||||
|
||||
<Canvas of={EmptyStateStories.WithButtonWithoutOnClick} />
|
||||
|
|
@ -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<typeof EmptyState> = {
|
||||
title: "ADS/Templates/Entity Explorer/Empty State",
|
||||
component: EmptyState,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
const Template = (props: EmptyStateProps) => {
|
||||
const { button, description, icon } = props;
|
||||
|
||||
return (
|
||||
<EmptyState
|
||||
{...{
|
||||
description,
|
||||
icon,
|
||||
button,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
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",
|
||||
},
|
||||
};
|
||||
|
|
@ -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 (
|
||||
<Flex
|
||||
alignItems={"center"}
|
||||
flexDirection="column"
|
||||
gap="spaces-4"
|
||||
justifyContent={"center"}
|
||||
px="spaces-3"
|
||||
py="spaces-7"
|
||||
>
|
||||
<Flex
|
||||
alignItems="center"
|
||||
backgroundColor="var(--ads-v2-color-bg-subtle)"
|
||||
borderRadius="var(--ads-v2-border-radius)"
|
||||
height="var(--ads-v2-spaces-11)"
|
||||
justifyContent="center"
|
||||
padding="spaces-3"
|
||||
width="var(--ads-v2-spaces-11)"
|
||||
>
|
||||
<Icon name={icon} size="lg" />
|
||||
</Flex>
|
||||
<Text
|
||||
className="text-center"
|
||||
color="var(--ads-v2-color-fg)"
|
||||
kind="heading-xs"
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
{button && button.onClick ? (
|
||||
<Button
|
||||
className={button.className}
|
||||
data-testid={button.testId}
|
||||
kind={button.kind || "secondary"}
|
||||
onClick={button.onClick}
|
||||
size="sm"
|
||||
>
|
||||
{button.text}
|
||||
</Button>
|
||||
) : null}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export { EmptyState };
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { type IconNames, type ButtonKind } from "../../..";
|
||||
|
||||
export interface EmptyStateProps {
|
||||
icon: IconNames;
|
||||
description: string;
|
||||
button?: {
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
kind?: Extract<ButtonKind, "primary" | "secondary">;
|
||||
className?: string;
|
||||
testId?: string;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export { EmptyState } from "./EmptyState";
|
||||
export * from "./EmptyState.types";
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
export const ExplorerContainerBorder = {
|
||||
STANDARD: "1px solid var(--ads-v2-color-border)",
|
||||
NONE: "",
|
||||
};
|
||||
|
|
@ -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<typeof ExplorerContainer> = {
|
||||
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 (
|
||||
<ExplorerContainer
|
||||
{...{
|
||||
children,
|
||||
width,
|
||||
height,
|
||||
className,
|
||||
borderRight,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Basic = Template.bind({}) as StoryObj;
|
||||
|
||||
const Children = () => {
|
||||
return (
|
||||
<Flex flexDirection="column" p="spaces-2">
|
||||
<SearchAndAdd showAddButton={false} />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
Basic.args = {
|
||||
children: <Children />,
|
||||
borderRight: "STANDARD",
|
||||
height: "300px",
|
||||
width: "255px",
|
||||
};
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import React from "react";
|
||||
import { ExplorerContainerBorder, Flex } from "../../..";
|
||||
import type { ExplorerContainerProps } from "./ExplorerContainer.types";
|
||||
|
||||
export const ExplorerContainer = (props: ExplorerContainerProps) => {
|
||||
return (
|
||||
<Flex
|
||||
borderRight={ExplorerContainerBorder[props.borderRight]}
|
||||
className={`relative ${props.className}`}
|
||||
flexDirection="column"
|
||||
height={props.height}
|
||||
overflow="hidden"
|
||||
width={props.width}
|
||||
>
|
||||
{props.children}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export { ExplorerContainer } from "./ExplorerContainer";
|
||||
export * from "./ExplorerContainer.types";
|
||||
export { ExplorerContainerBorder } from "./ExplorerContainer.constants";
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { Canvas, Meta } from "@storybook/blocks";
|
||||
|
||||
import * as NoSearchResultStories from "./NoSearchResults.stories";
|
||||
|
||||
<Meta of={NoSearchResultStories} />
|
||||
|
||||
# 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
|
||||
|
||||
<Canvas of={NoSearchResultStories.Basic} />
|
||||
|
|
@ -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<typeof NoSearchResults> = {
|
||||
title: "ADS/Templates/Entity Explorer/No Search Results",
|
||||
component: NoSearchResults,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
const Template = (props: NoSearchResultsProps) => {
|
||||
const { text } = props;
|
||||
|
||||
return <NoSearchResults text={text} />;
|
||||
};
|
||||
|
||||
export const Basic = Template.bind({}) as StoryObj;
|
||||
|
||||
Basic.args = {
|
||||
text: "No files found",
|
||||
};
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import { Text } from "../../..";
|
||||
import type { NoSearchResultsProps } from "./NoSearchResults.types";
|
||||
|
||||
const NoSearchResults = ({ text }: NoSearchResultsProps) => {
|
||||
return (
|
||||
<Text
|
||||
className="font-normal text-center"
|
||||
color="var(--ads-v2-color-fg-muted)"
|
||||
kind="body-s"
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
export { NoSearchResults };
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export interface NoSearchResultsProps {
|
||||
text: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export { NoSearchResults } from "./NoSearchResults";
|
||||
export * from "./NoSearchResults.types";
|
||||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Flex
|
||||
<ExplorerContainer
|
||||
borderRight={
|
||||
ideViewMode === EditorViewMode.SplitScreen
|
||||
? ""
|
||||
: "1px solid var(--ads-v2-color-border)"
|
||||
ideViewMode === EditorViewMode.SplitScreen ? "NONE" : "STANDARD"
|
||||
}
|
||||
className="relative ide-editor-left-pane__content"
|
||||
flexDirection="column"
|
||||
overflow="hidden"
|
||||
className="ide-editor-left-pane__content"
|
||||
width={
|
||||
ideViewMode === EditorViewMode.FullScreen
|
||||
? DEFAULT_EXPLORER_PANE_WIDTH
|
||||
|
|
@ -61,7 +57,7 @@ const EditorPaneExplorer = () => {
|
|||
]}
|
||||
/>
|
||||
</Switch>
|
||||
</Flex>
|
||||
</ExplorerContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
|||
<GroupedList groups={filteredItemGroups} />
|
||||
) : null}
|
||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||
<EmptySearchResult
|
||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject)}
|
||||
<NoSearchResults
|
||||
text={createMessage(
|
||||
EDITOR_PANE_TEXTS.empty_search_result,
|
||||
createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject),
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonTestId="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.js_add_button)}
|
||||
button={buttonProps}
|
||||
description={createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)}
|
||||
icon={"js-square-v3"}
|
||||
onClick={canCreateActions ? openAddJS : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 !== "" ? (
|
||||
<EmptySearchResult
|
||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject)}
|
||||
<NoSearchResults
|
||||
text={createMessage(
|
||||
EDITOR_PANE_TEXTS.empty_search_result,
|
||||
createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject),
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
|||
<GroupedList groups={filteredItemGroups} />
|
||||
) : null}
|
||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||
<EmptySearchResult
|
||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.datasources)}
|
||||
<NoSearchResults
|
||||
text={createMessage(
|
||||
EDITOR_PANE_TEXTS.empty_search_result,
|
||||
createMessage(EDITOR_PANE_TEXTS.search_objects.datasources),
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonTestId="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.query_add_button)}
|
||||
button={buttonProps}
|
||||
description={createMessage(
|
||||
EDITOR_PANE_TEXTS.query_blank_state_description,
|
||||
)}
|
||||
icon={"queries-v3"}
|
||||
onClick={canCreateActions ? openAddQuery : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 !== "" ? (
|
||||
<EmptySearchResult
|
||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.queries)}
|
||||
<NoSearchResults
|
||||
text={createMessage(
|
||||
EDITOR_PANE_TEXTS.empty_search_result,
|
||||
createMessage(EDITOR_PANE_TEXTS.search_objects.queries),
|
||||
)}
|
||||
/>
|
||||
) : null}
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<ListContainer
|
||||
|
|
@ -62,14 +76,11 @@ const ListWidgets = (props: {
|
|||
{!widgetsExist ? (
|
||||
/* If no widgets exist, show the blank state */
|
||||
<EmptyState
|
||||
buttonClassName="t--add-item"
|
||||
buttonTestId="t--add-item"
|
||||
buttonText={createMessage(EDITOR_PANE_TEXTS.widget_add_button)}
|
||||
button={blankStateButtonProps}
|
||||
description={createMessage(
|
||||
EDITOR_PANE_TEXTS.widget_blank_state_description,
|
||||
)}
|
||||
icon={"widgets-v3"}
|
||||
onClick={canManagePages ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
) : canManagePages ? (
|
||||
/* We show the List Add button when side by side is not enabled */
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Text
|
||||
className="font-normal text-center"
|
||||
color="var(--ads-v2-color-fg-muted)"
|
||||
kind="body-s"
|
||||
>
|
||||
{createMessage(EDITOR_PANE_TEXTS.empty_search_result, type)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
export { EmptySearchResult };
|
||||
|
|
@ -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 (
|
||||
<Flex
|
||||
alignItems={"center"}
|
||||
flexDirection="column"
|
||||
gap="spaces-4"
|
||||
justifyContent={"center"}
|
||||
px="spaces-3"
|
||||
py="spaces-7"
|
||||
>
|
||||
<Flex
|
||||
alignItems={"center"}
|
||||
backgroundColor={"var(--ads-v2-color-bg-subtle)"}
|
||||
borderRadius={"var(--ads-v2-border-radius)"}
|
||||
height={"40px"}
|
||||
justifyContent={"center"}
|
||||
padding={"spaces-3"}
|
||||
width={"40px"}
|
||||
>
|
||||
<Icon name={icon} size={"lg"} />
|
||||
</Flex>
|
||||
<Text
|
||||
className={"text-center"}
|
||||
color={"var(--ads-v2-color-fg)"}
|
||||
kind={"heading-xs"}
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
{onClick && (
|
||||
<Button
|
||||
className={buttonClassName}
|
||||
data-testid={buttonTestId}
|
||||
kind={"secondary"}
|
||||
onClick={onClick}
|
||||
size={"sm"}
|
||||
>
|
||||
{buttonText}
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export { EmptyState };
|
||||
|
|
@ -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 = () => {
|
|||
<Flex
|
||||
borderRight={
|
||||
ideViewMode === EditorViewMode.SplitScreen
|
||||
? "1px solid var(--ads-v2-color-border)"
|
||||
: ""
|
||||
? ExplorerContainerBorder.STANDARD
|
||||
: ExplorerContainerBorder.NONE
|
||||
}
|
||||
className="ide-editor-left-pane"
|
||||
flexDirection={
|
||||
|
|
@ -24,7 +24,7 @@ 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.
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Flex
|
||||
|
|
@ -112,11 +123,9 @@ const DataSidePane = (props: DataSidePaneProps) => {
|
|||
<PaneBody>
|
||||
{datasources.length === 0 ? (
|
||||
<EmptyState
|
||||
buttonClassName={"t--add-datasource-button-blank-screen"}
|
||||
buttonText={"Bring your data"}
|
||||
button={blankStateButtonProps}
|
||||
description={createMessage(DATASOURCE_LIST_BLANK_DESCRIPTION)}
|
||||
icon={"datasource-v3"}
|
||||
onClick={canCreateDatasource ? addButtonClickHandler : undefined}
|
||||
/>
|
||||
) : null}
|
||||
<Flex
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user