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 { ListWithHeader } from "./ListWithHeader";
|
||||||
export { EditorSegments } from "./EditorSegments";
|
export { EditorSegments } from "./EditorSegments";
|
||||||
export * from "./SearchAndAdd";
|
export * from "./SearchAndAdd";
|
||||||
|
export { EmptyState } from "./EmptyState";
|
||||||
|
export { NoSearchResults } from "./NoSearchResults";
|
||||||
|
export * from "./ExplorerContainer";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Flex } from "@appsmith/ads";
|
import { ExplorerContainer } from "@appsmith/ads";
|
||||||
import { Switch, useRouteMatch } from "react-router";
|
import { Switch, useRouteMatch } from "react-router";
|
||||||
import { SentryRoute } from "ee/AppRouter";
|
import { SentryRoute } from "ee/AppRouter";
|
||||||
import {
|
import {
|
||||||
|
|
@ -26,15 +26,11 @@ const EditorPaneExplorer = () => {
|
||||||
const ideViewMode = useSelector(getIDEViewMode);
|
const ideViewMode = useSelector(getIDEViewMode);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<ExplorerContainer
|
||||||
borderRight={
|
borderRight={
|
||||||
ideViewMode === EditorViewMode.SplitScreen
|
ideViewMode === EditorViewMode.SplitScreen ? "NONE" : "STANDARD"
|
||||||
? ""
|
|
||||||
: "1px solid var(--ads-v2-color-border)"
|
|
||||||
}
|
}
|
||||||
className="relative ide-editor-left-pane__content"
|
className="ide-editor-left-pane__content"
|
||||||
flexDirection="column"
|
|
||||||
overflow="hidden"
|
|
||||||
width={
|
width={
|
||||||
ideViewMode === EditorViewMode.FullScreen
|
ideViewMode === EditorViewMode.FullScreen
|
||||||
? DEFAULT_EXPLORER_PANE_WIDTH
|
? DEFAULT_EXPLORER_PANE_WIDTH
|
||||||
|
|
@ -61,7 +57,7 @@ const EditorPaneExplorer = () => {
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Flex>
|
</ExplorerContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useCallback, useState } from "react";
|
||||||
import SegmentAddHeader from "../components/SegmentAddHeader";
|
import SegmentAddHeader from "../components/SegmentAddHeader";
|
||||||
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
||||||
import type { ListItemProps } from "@appsmith/ads";
|
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 { useDispatch, useSelector } from "react-redux";
|
||||||
import { getCurrentPageId } from "selectors/editorSelectors";
|
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||||
import GroupedList from "../components/GroupedList";
|
import GroupedList from "../components/GroupedList";
|
||||||
|
|
@ -13,7 +13,6 @@ import {
|
||||||
import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils";
|
import type { ActionOperation } from "components/editorComponents/GlobalSearch/utils";
|
||||||
import { createAddClassName } from "../utils";
|
import { createAddClassName } from "../utils";
|
||||||
import { FocusEntity } from "navigation/FocusEntity";
|
import { FocusEntity } from "navigation/FocusEntity";
|
||||||
import { EmptySearchResult } from "../components/EmptySearchResult";
|
|
||||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||||
import type { FlexProps } from "@appsmith/ads";
|
import type { FlexProps } from "@appsmith/ads";
|
||||||
import { EditorViewMode } from "ee/entities/IDE/constants";
|
import { EditorViewMode } from "ee/entities/IDE/constants";
|
||||||
|
|
@ -98,8 +97,11 @@ const AddJS = () => {
|
||||||
<GroupedList groups={filteredItemGroups} />
|
<GroupedList groups={filteredItemGroups} />
|
||||||
) : null}
|
) : null}
|
||||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||||
<EmptySearchResult
|
<NoSearchResults
|
||||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject)}
|
text={createMessage(
|
||||||
|
EDITOR_PANE_TEXTS.empty_search_result,
|
||||||
|
createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
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 { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
||||||
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
||||||
import { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks";
|
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 BlankState: React.FC = () => {
|
||||||
const pagePermissions = useSelector(getPagePermissions);
|
const pagePermissions = useSelector(getPagePermissions);
|
||||||
|
|
@ -18,14 +18,21 @@ const BlankState: React.FC = () => {
|
||||||
);
|
);
|
||||||
const { openAddJS } = useJSAdd();
|
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 (
|
return (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
buttonClassName="t--add-item"
|
button={buttonProps}
|
||||||
buttonTestId="t--add-item"
|
|
||||||
buttonText={createMessage(EDITOR_PANE_TEXTS.js_add_button)}
|
|
||||||
description={createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)}
|
description={createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)}
|
||||||
icon={"js-square-v3"}
|
icon={"js-square-v3"}
|
||||||
onClick={canCreateActions ? openAddJS : undefined}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useSelector } from "react-redux";
|
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 styled from "styled-components";
|
||||||
|
|
||||||
import { selectJSSegmentEditorList } from "ee/selectors/appIDESelectors";
|
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 { useJSAdd } from "ee/pages/Editor/IDE/EditorPane/JS/hooks";
|
||||||
import { JSListItem } from "ee/pages/Editor/IDE/EditorPane/JS/ListItem";
|
import { JSListItem } from "ee/pages/Editor/IDE/EditorPane/JS/ListItem";
|
||||||
import { BlankState } from "./BlankState";
|
import { BlankState } from "./BlankState";
|
||||||
import { EmptySearchResult } from "../components/EmptySearchResult";
|
|
||||||
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
||||||
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
||||||
|
|
||||||
|
|
@ -111,8 +110,11 @@ const ListJSObjects = () => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||||
<EmptySearchResult
|
<NoSearchResults
|
||||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject)}
|
text={createMessage(
|
||||||
|
EDITOR_PANE_TEXTS.empty_search_result,
|
||||||
|
createMessage(EDITOR_PANE_TEXTS.search_objects.jsObject),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
import React, { useState } from "react";
|
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 { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages";
|
||||||
import SegmentAddHeader from "../components/SegmentAddHeader";
|
import SegmentAddHeader from "../components/SegmentAddHeader";
|
||||||
|
|
@ -9,10 +14,8 @@ import {
|
||||||
useGroupedAddQueryOperations,
|
useGroupedAddQueryOperations,
|
||||||
useQueryAdd,
|
useQueryAdd,
|
||||||
} from "ee/pages/Editor/IDE/EditorPane/Query/hooks";
|
} from "ee/pages/Editor/IDE/EditorPane/Query/hooks";
|
||||||
import { EmptySearchResult } from "../components/EmptySearchResult";
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||||
import type { FlexProps } from "@appsmith/ads";
|
|
||||||
import { EditorViewMode } from "ee/entities/IDE/constants";
|
import { EditorViewMode } from "ee/entities/IDE/constants";
|
||||||
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
||||||
|
|
||||||
|
|
@ -66,8 +69,11 @@ const AddQuery = () => {
|
||||||
<GroupedList groups={filteredItemGroups} />
|
<GroupedList groups={filteredItemGroups} />
|
||||||
) : null}
|
) : null}
|
||||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||||
<EmptySearchResult
|
<NoSearchResults
|
||||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.datasources)}
|
text={createMessage(
|
||||||
|
EDITOR_PANE_TEXTS.empty_search_result,
|
||||||
|
createMessage(EDITOR_PANE_TEXTS.search_objects.datasources),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
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 { getPagePermissions } from "selectors/editorSelectors";
|
||||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
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";
|
import { useQueryAdd } from "ee/pages/Editor/IDE/EditorPane/Query/hooks";
|
||||||
|
|
||||||
const BlankState: React.FC = () => {
|
const BlankState: React.FC = () => {
|
||||||
|
|
@ -18,16 +18,23 @@ const BlankState: React.FC = () => {
|
||||||
);
|
);
|
||||||
const { openAddQuery } = useQueryAdd();
|
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 (
|
return (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
buttonClassName="t--add-item"
|
button={buttonProps}
|
||||||
buttonTestId="t--add-item"
|
|
||||||
buttonText={createMessage(EDITOR_PANE_TEXTS.query_add_button)}
|
|
||||||
description={createMessage(
|
description={createMessage(
|
||||||
EDITOR_PANE_TEXTS.query_blank_state_description,
|
EDITOR_PANE_TEXTS.query_blank_state_description,
|
||||||
)}
|
)}
|
||||||
icon={"queries-v3"}
|
icon={"queries-v3"}
|
||||||
onClick={canCreateActions ? openAddQuery : undefined}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from "react";
|
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 { useSelector } from "react-redux";
|
||||||
|
|
||||||
import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
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 { QueryListItem } from "ee/pages/Editor/IDE/EditorPane/Query/ListItem";
|
||||||
import { getShowWorkflowFeature } from "ee/selectors/workflowSelectors";
|
import { getShowWorkflowFeature } from "ee/selectors/workflowSelectors";
|
||||||
import { BlankState } from "./BlankState";
|
import { BlankState } from "./BlankState";
|
||||||
import { EmptySearchResult } from "../components/EmptySearchResult";
|
|
||||||
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
import { EDITOR_PANE_TEXTS, createMessage } from "ee/constants/messages";
|
||||||
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
import { filterEntityGroupsBySearchTerm } from "IDE/utils";
|
||||||
|
|
||||||
|
|
@ -95,8 +94,11 @@ const ListQuery = () => {
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
{filteredItemGroups.length === 0 && searchTerm !== "" ? (
|
||||||
<EmptySearchResult
|
<NoSearchResults
|
||||||
type={createMessage(EDITOR_PANE_TEXTS.search_objects.queries)}
|
text={createMessage(
|
||||||
|
EDITOR_PANE_TEXTS.empty_search_result,
|
||||||
|
createMessage(EDITOR_PANE_TEXTS.search_objects.queries),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
||||||
import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
||||||
import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages";
|
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 history from "utils/history";
|
||||||
import { builderURL } from "ee/RouteBuilder";
|
import { builderURL } from "ee/RouteBuilder";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
@ -26,6 +26,7 @@ const ListContainer = styled(Flex)`
|
||||||
const ListWidgets = (props: {
|
const ListWidgets = (props: {
|
||||||
setFocusSearchInput: (focusSearchInput: boolean) => void;
|
setFocusSearchInput: (focusSearchInput: boolean) => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { setFocusSearchInput } = props;
|
||||||
const basePageId = useSelector(getCurrentBasePageId) as string;
|
const basePageId = useSelector(getCurrentBasePageId) as string;
|
||||||
const widgets = useSelector(selectWidgetsForCurrentPage);
|
const widgets = useSelector(selectWidgetsForCurrentPage);
|
||||||
const pagePermissions = useSelector(getPagePermissions);
|
const pagePermissions = useSelector(getPagePermissions);
|
||||||
|
|
@ -41,16 +42,29 @@ const ListWidgets = (props: {
|
||||||
}, [widgets?.children]);
|
}, [widgets?.children]);
|
||||||
|
|
||||||
const addButtonClickHandler = useCallback(() => {
|
const addButtonClickHandler = useCallback(() => {
|
||||||
props.setFocusSearchInput(true);
|
setFocusSearchInput(true);
|
||||||
history.push(builderURL({}));
|
history.push(builderURL({}));
|
||||||
}, []);
|
}, [setFocusSearchInput]);
|
||||||
|
|
||||||
const widgetsExist =
|
const widgetsExist =
|
||||||
widgets && widgets.children && widgets.children.length > 0;
|
widgets && widgets.children && widgets.children.length > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(
|
||||||
props.setFocusSearchInput(false);
|
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 (
|
return (
|
||||||
<ListContainer
|
<ListContainer
|
||||||
|
|
@ -62,14 +76,11 @@ const ListWidgets = (props: {
|
||||||
{!widgetsExist ? (
|
{!widgetsExist ? (
|
||||||
/* If no widgets exist, show the blank state */
|
/* If no widgets exist, show the blank state */
|
||||||
<EmptyState
|
<EmptyState
|
||||||
buttonClassName="t--add-item"
|
button={blankStateButtonProps}
|
||||||
buttonTestId="t--add-item"
|
|
||||||
buttonText={createMessage(EDITOR_PANE_TEXTS.widget_add_button)}
|
|
||||||
description={createMessage(
|
description={createMessage(
|
||||||
EDITOR_PANE_TEXTS.widget_blank_state_description,
|
EDITOR_PANE_TEXTS.widget_blank_state_description,
|
||||||
)}
|
)}
|
||||||
icon={"widgets-v3"}
|
icon={"widgets-v3"}
|
||||||
onClick={canManagePages ? addButtonClickHandler : undefined}
|
|
||||||
/>
|
/>
|
||||||
) : canManagePages ? (
|
) : canManagePages ? (
|
||||||
/* We show the List Add button when side by side is not enabled */
|
/* 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 React from "react";
|
||||||
import { Flex } from "@appsmith/ads";
|
import { ExplorerContainerBorder, Flex } from "@appsmith/ads";
|
||||||
import EditorPaneExplorer from "./Explorer";
|
import EditorPaneExplorer from "./Explorer";
|
||||||
import Editor from "./Editor";
|
import Editor from "./Editor";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
@ -14,8 +14,8 @@ const EditorPane = () => {
|
||||||
<Flex
|
<Flex
|
||||||
borderRight={
|
borderRight={
|
||||||
ideViewMode === EditorViewMode.SplitScreen
|
ideViewMode === EditorViewMode.SplitScreen
|
||||||
? "1px solid var(--ads-v2-color-border)"
|
? ExplorerContainerBorder.STANDARD
|
||||||
: ""
|
: ExplorerContainerBorder.NONE
|
||||||
}
|
}
|
||||||
className="ide-editor-left-pane"
|
className="ide-editor-left-pane"
|
||||||
flexDirection={
|
flexDirection={
|
||||||
|
|
@ -24,7 +24,7 @@ const EditorPane = () => {
|
||||||
// @ts-expect-error Fix this the next time the file is edited
|
// @ts-expect-error Fix this the next time the file is edited
|
||||||
gap="spacing-2"
|
gap="spacing-2"
|
||||||
height="100%"
|
height="100%"
|
||||||
width={"100%"}
|
width="100%"
|
||||||
>
|
>
|
||||||
{/** Entity Properties component is necessary to render
|
{/** Entity Properties component is necessary to render
|
||||||
the Bindings popover in the context menu.
|
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 styled from "styled-components";
|
||||||
import { Flex, List, Text } from "@appsmith/ads";
|
import { Flex, List, Text } from "@appsmith/ads";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
@ -27,7 +27,7 @@ import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors"
|
||||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
|
||||||
import { getHasCreateDatasourcePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
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 { getAssetUrl } from "ee/utils/airgapHelpers";
|
||||||
import { getCurrentBasePageId } from "selectors/editorSelectors";
|
import { getCurrentBasePageId } from "selectors/editorSelectors";
|
||||||
|
|
||||||
|
|
@ -86,13 +86,24 @@ const DataSidePane = (props: DataSidePaneProps) => {
|
||||||
userWorkspacePermissions,
|
userWorkspacePermissions,
|
||||||
);
|
);
|
||||||
|
|
||||||
const addButtonClickHandler = () =>
|
const addButtonClickHandler = useCallback(() => {
|
||||||
history.push(
|
history.push(
|
||||||
integrationEditorURL({
|
integrationEditorURL({
|
||||||
basePageId,
|
basePageId,
|
||||||
selectedTab: INTEGRATION_TABS.NEW,
|
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 (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
|
|
@ -112,11 +123,9 @@ const DataSidePane = (props: DataSidePaneProps) => {
|
||||||
<PaneBody>
|
<PaneBody>
|
||||||
{datasources.length === 0 ? (
|
{datasources.length === 0 ? (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
buttonClassName={"t--add-datasource-button-blank-screen"}
|
button={blankStateButtonProps}
|
||||||
buttonText={"Bring your data"}
|
|
||||||
description={createMessage(DATASOURCE_LIST_BLANK_DESCRIPTION)}
|
description={createMessage(DATASOURCE_LIST_BLANK_DESCRIPTION)}
|
||||||
icon={"datasource-v3"}
|
icon={"datasource-v3"}
|
||||||
onClick={canCreateDatasource ? addButtonClickHandler : undefined}
|
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Flex
|
<Flex
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user