chore: Move Sidebar to IDE/Components (#34487)
## Description Separate the Sidebar Component from the various IDEs and move it to the IDE module. Fixes #34554 ## Automation /ok-to-test tags="@tag.IDE" ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/9869212078> > Commit: 0b685d46ba18bb98e37fde87a96c930172fc5c15 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9869212078&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.IDE` > Spec: > <hr>Wed, 10 Jul 2024 06:47:16 UTC <!-- end of auto-generated comment: Cypress test results --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new sidebar component (`IDESidebar`) managing button states and handling interactions. - Added `Condition` enum for better condition management with icons and colors in the sidebar buttons. - **Enhancements** - Improved click handling for sidebar buttons with a new `handleOnClick` function. - **Tests** - Added test cases for `SidebarButton` component to validate different conditions and click behaviors. - **Components** - New React components and interfaces for managing the IDE's sidebar functionality and state. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
cdd33a846f
commit
00a7d3c9a8
|
|
@ -3,8 +3,8 @@ import styled from "styled-components";
|
|||
import Resizer, {
|
||||
ResizerCSS,
|
||||
} from "components/editorComponents/Debugger/Resizer";
|
||||
import { CodeEditorWithGutterStyles } from "pages/Editor/JSEditor/constants";
|
||||
import { ViewHideBehaviour, ViewDisplayMode } from "IDE/Interfaces/View";
|
||||
import { CodeEditorWithGutterStyles } from "pages/Editor/JSEditor/styledComponents";
|
||||
import { ViewDisplayMode, ViewHideBehaviour } from "IDE/Interfaces/View";
|
||||
import { Button } from "design-system";
|
||||
|
||||
const VIEW_MIN_HEIGHT = 38;
|
||||
|
|
|
|||
69
app/client/src/IDE/Components/Sidebar/Sidebar.tsx
Normal file
69
app/client/src/IDE/Components/Sidebar/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import SidebarButton from "./SidebarButton";
|
||||
import type { EditorState } from "@appsmith/entities/IDE/constants";
|
||||
import type { SidebarButtonProps } from "./SidebarButton/SidebarButton";
|
||||
import { Flex } from "design-system";
|
||||
|
||||
const Container = styled(Flex)`
|
||||
width: 50px;
|
||||
border-right: 1px solid var(--ads-v2-color-border);
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: var(--ads-v2-color-bg);
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
// Sidebar handles the correct handling of sidebar button. It will check if
|
||||
// the button should be selected and only handle calling the onClick
|
||||
export interface IDESidebarButton
|
||||
extends Omit<SidebarButtonProps, "onClick" | "selected"> {
|
||||
state: EditorState;
|
||||
urlSuffix: string;
|
||||
}
|
||||
|
||||
interface IDESidebarProps {
|
||||
id?: string;
|
||||
topButtons: IDESidebarButton[];
|
||||
bottomButtons: IDESidebarButton[];
|
||||
editorState: EditorState;
|
||||
onClick: (suffix: string) => void;
|
||||
}
|
||||
|
||||
function IDESidebar(props: IDESidebarProps) {
|
||||
const { bottomButtons, editorState, onClick, topButtons } = props;
|
||||
|
||||
return (
|
||||
<Container className="t--sidebar" id={props.id}>
|
||||
<div>
|
||||
{topButtons.map((button) => (
|
||||
<SidebarButton
|
||||
icon={button.icon}
|
||||
key={button.state}
|
||||
onClick={onClick}
|
||||
selected={editorState === button.state}
|
||||
title={button.title}
|
||||
tooltip={button.tooltip}
|
||||
urlSuffix={button.urlSuffix}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
{bottomButtons.map((button) => (
|
||||
<SidebarButton
|
||||
icon={button.icon}
|
||||
key={button.state}
|
||||
onClick={onClick}
|
||||
selected={editorState === button.state}
|
||||
title={button.title}
|
||||
tooltip={button.tooltip}
|
||||
urlSuffix={button.urlSuffix}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default IDESidebar;
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import { render } from "test/testUtils";
|
||||
import React from "react";
|
||||
import SidebarButton, { type SidebarButtonProps } from "./SidebarButton";
|
||||
|
||||
import { Condition } from "../../../enums";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
const sidebarButtonProps: SidebarButtonProps = {
|
||||
icon: "down-arrow",
|
||||
onClick: () => {},
|
||||
selected: false,
|
||||
title: "Test",
|
||||
urlSuffix: "/test",
|
||||
};
|
||||
|
||||
describe("SidebarButton", () => {
|
||||
it("should render the warning icon in case the datasource list is empty", () => {
|
||||
const withWarningCondition = {
|
||||
...sidebarButtonProps,
|
||||
condition: Condition.Warn,
|
||||
};
|
||||
|
||||
const { container } = render(<SidebarButton {...withWarningCondition} />);
|
||||
|
||||
const svgs = container.querySelectorAll("svg");
|
||||
expect(svgs).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("should call onClick with urlSuffix", async () => {
|
||||
const checkOnClick = {
|
||||
...sidebarButtonProps,
|
||||
onClick: jest.fn(),
|
||||
};
|
||||
const { getByRole } = render(<SidebarButton {...checkOnClick} />);
|
||||
|
||||
await userEvent.click(getByRole("button"));
|
||||
expect(checkOnClick.onClick).toHaveBeenCalledWith(checkOnClick.urlSuffix);
|
||||
});
|
||||
|
||||
it("should not call onClick when button is already selected", async () => {
|
||||
const withSelected = {
|
||||
...sidebarButtonProps,
|
||||
selected: true,
|
||||
onClick: jest.fn(),
|
||||
};
|
||||
const { getByRole } = render(<SidebarButton {...withSelected} />);
|
||||
|
||||
await userEvent.click(getByRole("button"));
|
||||
expect(withSelected.onClick).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
import React, { useCallback } from "react";
|
||||
import { Flex, Icon, Text, Tooltip } from "design-system";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { Condition } from "../../../enums";
|
||||
|
||||
const ConditionConfig: Record<Condition, { icon: string; color: string }> = {
|
||||
[Condition.Warn]: {
|
||||
icon: "warning",
|
||||
color: "#ffe283",
|
||||
},
|
||||
// TODO add this information for further conditions
|
||||
// Error: { color: "", icon: "" },
|
||||
// Success: { color: "", icon: "" },
|
||||
};
|
||||
|
||||
export interface SidebarButtonProps {
|
||||
title?: string;
|
||||
selected: boolean;
|
||||
icon: string;
|
||||
onClick: (urlSuffix: string) => void;
|
||||
urlSuffix: string;
|
||||
tooltip?: string;
|
||||
condition?: Condition;
|
||||
}
|
||||
|
||||
const Container = styled(Flex)`
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div<{ selected: boolean }>`
|
||||
padding: 2px;
|
||||
background-color: ${(props) =>
|
||||
props.selected ? "var(--colors-raw-orange-100, #fbe6dc)" : "white"};
|
||||
border-radius: 3px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: ${(props) =>
|
||||
props.selected
|
||||
? "var(--colors-raw-orange-100, #fbe6dc)"
|
||||
: "var(--ads-v2-color-bg-subtle, #f1f5f9);"};
|
||||
}
|
||||
`;
|
||||
|
||||
const ConditionIcon = styled(Icon)`
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
right: -1px;
|
||||
|
||||
&.t--sidebar-${Condition.Warn}-condition-icon {
|
||||
color: ${ConditionConfig[Condition.Warn].color};
|
||||
}
|
||||
|
||||
// TODO add more condition colors here
|
||||
`;
|
||||
|
||||
function SidebarButton(props: SidebarButtonProps) {
|
||||
const { condition, icon, onClick, selected, title, tooltip, urlSuffix } =
|
||||
props;
|
||||
const handleOnClick = useCallback(() => {
|
||||
if (!selected) {
|
||||
onClick(urlSuffix);
|
||||
}
|
||||
}, [selected, onClick, urlSuffix]);
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip
|
||||
content={tooltip}
|
||||
isDisabled={!!title && !tooltip}
|
||||
placement={"right"}
|
||||
>
|
||||
<IconContainer
|
||||
className={`t--sidebar-${title || tooltip}`}
|
||||
data-selected={selected}
|
||||
onClick={handleOnClick}
|
||||
role="button"
|
||||
selected={selected}
|
||||
>
|
||||
<Icon name={icon} size="lg" />
|
||||
{condition && (
|
||||
<ConditionIcon
|
||||
className={`t--sidebar-${condition}-condition-icon`}
|
||||
name={ConditionConfig[condition].icon}
|
||||
size="md"
|
||||
/>
|
||||
)}
|
||||
</IconContainer>
|
||||
</Tooltip>
|
||||
{title ? <Text kind="body-s">{title}</Text> : null}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default SidebarButton;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./SidebarButton";
|
||||
2
app/client/src/IDE/Components/Sidebar/index.tsx
Normal file
2
app/client/src/IDE/Components/Sidebar/index.tsx
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./Sidebar";
|
||||
export type { IDESidebarButton } from "./Sidebar";
|
||||
5
app/client/src/IDE/enums.ts
Normal file
5
app/client/src/IDE/enums.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export enum Condition {
|
||||
Warn = "Warn",
|
||||
// Error = "Error",
|
||||
// Success = "Success",
|
||||
}
|
||||
|
|
@ -40,9 +40,17 @@ export { default as IDEHeaderDropdown } from "./Components/HeaderDropdown";
|
|||
*/
|
||||
export { default as IDEBottomView } from "./Components/BottomView";
|
||||
|
||||
/**
|
||||
* IDESidebar is used inside the IDE to have a navigation menu on the left side of the screen.
|
||||
* It switches between different editor states
|
||||
*/
|
||||
export { default as IDESidebar } from "./Components/Sidebar";
|
||||
|
||||
/* ====================================================
|
||||
**** Interfaces ****
|
||||
Common types that are used by the different components of the IDE
|
||||
=======================================================**/
|
||||
|
||||
export { ViewHideBehaviour, ViewDisplayMode } from "./Interfaces/View";
|
||||
export { Condition } from "./enums";
|
||||
export type { IDESidebarButton } from "./Components/Sidebar";
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export default class LibraryApi extends Api {
|
|||
library: Partial<JSLibrary>,
|
||||
) {
|
||||
const url = LibraryApi.getUpdateLibraryBaseURL(applicationId) + "/remove";
|
||||
return Api.patch(url, { accessor: library.accessor, url: library.url });
|
||||
return Api.patch(url, library);
|
||||
}
|
||||
|
||||
static async getLibraries(applicationId: string, mode: APP_MODE) {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,8 @@ import {
|
|||
SAAS_EDITOR_DATASOURCE_ID_PATH,
|
||||
} from "pages/Editor/SaaSEditor/constants";
|
||||
import type { PluginType } from "entities/Action";
|
||||
import type { ReactNode, ComponentType } from "react";
|
||||
import {
|
||||
EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import type { ComponentType, ReactNode } from "react";
|
||||
import type { IDESidebarButton } from "IDE";
|
||||
|
||||
export enum EditorState {
|
||||
DATA = "DATA",
|
||||
|
|
@ -60,20 +57,7 @@ export enum EditorViewMode {
|
|||
SplitScreen = "SplitScreen",
|
||||
}
|
||||
|
||||
export enum SideButtonType {
|
||||
DATSOURCE = "DATASOURCE",
|
||||
}
|
||||
|
||||
export interface SidebarButton {
|
||||
state: EditorState;
|
||||
icon: string;
|
||||
title?: string;
|
||||
urlSuffix: string;
|
||||
conditionType?: SideButtonType;
|
||||
conditionTooltip?: string;
|
||||
}
|
||||
|
||||
export const TopButtons: SidebarButton[] = [
|
||||
export const TopButtons: IDESidebarButton[] = [
|
||||
{
|
||||
state: EditorState.EDITOR,
|
||||
icon: "editor-v3",
|
||||
|
|
@ -85,22 +69,20 @@ export const TopButtons: SidebarButton[] = [
|
|||
icon: "datasource-v3",
|
||||
title: SidebarTopButtonTitles.DATA,
|
||||
urlSuffix: "datasource",
|
||||
conditionType: SideButtonType.DATSOURCE,
|
||||
conditionTooltip: createMessage(EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON),
|
||||
},
|
||||
];
|
||||
|
||||
export const BottomButtons: SidebarButton[] = [
|
||||
export const BottomButtons: IDESidebarButton[] = [
|
||||
{
|
||||
state: EditorState.LIBRARIES,
|
||||
icon: "packages-v3",
|
||||
title: SidebarBottomButtonTitles.LIBRARIES,
|
||||
tooltip: SidebarBottomButtonTitles.LIBRARIES,
|
||||
urlSuffix: "libraries",
|
||||
},
|
||||
{
|
||||
state: EditorState.SETTINGS,
|
||||
icon: "settings-v3",
|
||||
title: SidebarBottomButtonTitles.SETTINGS,
|
||||
tooltip: SidebarBottomButtonTitles.SETTINGS,
|
||||
urlSuffix: "settings",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
75
app/client/src/pages/Editor/IDE/Sidebar.tsx
Normal file
75
app/client/src/pages/Editor/IDE/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import React, { useCallback, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { builderURL } from "@appsmith/RouteBuilder";
|
||||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import history, { NavigationMethod } from "utils/history";
|
||||
import { useCurrentAppState } from "./hooks";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import { fetchWorkspace } from "@appsmith/actions/workspaceActions";
|
||||
import { IDESidebar, Condition } from "IDE";
|
||||
import {
|
||||
BottomButtons,
|
||||
EditorState,
|
||||
TopButtons,
|
||||
} from "@appsmith/entities/IDE/constants";
|
||||
import { getDatasources } from "@appsmith/selectors/entitiesSelector";
|
||||
import {
|
||||
createMessage,
|
||||
EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON,
|
||||
} from "@appsmith/constants/messages";
|
||||
|
||||
function Sidebar() {
|
||||
const dispatch = useDispatch();
|
||||
const appState = useCurrentAppState();
|
||||
const pageId = useSelector(getCurrentPageId);
|
||||
const currentWorkspaceId = useSelector(getCurrentWorkspaceId);
|
||||
const datasources = useSelector(getDatasources);
|
||||
const datasourcesExist = datasources.length > 0;
|
||||
|
||||
// Updates the top button config based on datasource existence
|
||||
const topButtons = React.useMemo(() => {
|
||||
return datasourcesExist
|
||||
? TopButtons
|
||||
: TopButtons.map((button) => {
|
||||
if (button.state === EditorState.DATA) {
|
||||
return {
|
||||
...button,
|
||||
condition: Condition.Warn,
|
||||
tooltip: createMessage(EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON),
|
||||
};
|
||||
}
|
||||
return button;
|
||||
});
|
||||
}, [datasourcesExist]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchWorkspace(currentWorkspaceId));
|
||||
}, [currentWorkspaceId, dispatch]);
|
||||
|
||||
const onClick = useCallback(
|
||||
(suffix) => {
|
||||
history.push(
|
||||
builderURL({
|
||||
pageId,
|
||||
suffix,
|
||||
}),
|
||||
{
|
||||
invokedBy: NavigationMethod.AppSidebar,
|
||||
},
|
||||
);
|
||||
},
|
||||
[pageId],
|
||||
);
|
||||
|
||||
return (
|
||||
<IDESidebar
|
||||
bottomButtons={BottomButtons}
|
||||
editorState={appState}
|
||||
id={"t--app-sidebar"}
|
||||
onClick={onClick}
|
||||
topButtons={topButtons}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Sidebar;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import { render } from "test/testUtils";
|
||||
import React from "react";
|
||||
import type { SidebarButtonProps } from "./SidebarButton";
|
||||
import SidebarButton from "./SidebarButton";
|
||||
import { TopButtons } from "@appsmith/entities/IDE/constants";
|
||||
|
||||
const sidebarButtonProps: SidebarButtonProps = {
|
||||
icon: TopButtons[1].icon,
|
||||
onClick: () => {},
|
||||
selected: false,
|
||||
title: TopButtons[1].title,
|
||||
conditionIcon: "warning",
|
||||
tooltip: TopButtons[1].conditionTooltip,
|
||||
};
|
||||
|
||||
describe("SidebarButton", () => {
|
||||
it("should render the warning icon incase the datasource list is empty", () => {
|
||||
const { container } = render(<SidebarButton {...sidebarButtonProps} />);
|
||||
|
||||
const svgs = container.querySelectorAll("svg");
|
||||
expect(svgs).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
import React from "react";
|
||||
import { Icon, Text, Tooltip } from "design-system";
|
||||
import styled from "styled-components";
|
||||
import { SidebarTopButtonTitles } from "@appsmith/entities/IDE/constants";
|
||||
|
||||
export interface SidebarButtonProps {
|
||||
title?: string;
|
||||
selected: boolean;
|
||||
icon: string;
|
||||
onClick: () => void;
|
||||
tooltip?: string;
|
||||
conditionIcon?: string;
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div<{ selected: boolean }>`
|
||||
padding: 2px;
|
||||
background-color: ${(props) =>
|
||||
props.selected ? "var(--colors-raw-orange-100, #fbe6dc)" : "white"};
|
||||
border-radius: 3px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
&:hover {
|
||||
background: ${(props) =>
|
||||
props.selected
|
||||
? "var(--colors-raw-orange-100, #fbe6dc)"
|
||||
: "var(--ads-v2-color-bg-subtle, #f1f5f9);"};
|
||||
}
|
||||
`;
|
||||
|
||||
const ConditionIcon = styled(Icon)`
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
right: -1px;
|
||||
&.t--sidebar-${SidebarTopButtonTitles.DATA}-condition-icon {
|
||||
color: #ffe283;
|
||||
}
|
||||
`;
|
||||
|
||||
function SidebarButton(props: SidebarButtonProps) {
|
||||
return (
|
||||
<Container>
|
||||
{props.title === SidebarTopButtonTitles.DATA}
|
||||
<Tooltip
|
||||
content={props.tooltip}
|
||||
isDisabled={!!props.title && !props.tooltip}
|
||||
placement={"right"}
|
||||
>
|
||||
<IconContainer
|
||||
className={`t--sidebar-${props.title || props.tooltip}`}
|
||||
data-selected={props.selected}
|
||||
onClick={props.onClick}
|
||||
selected={props.selected}
|
||||
>
|
||||
<Icon name={props.icon} size="lg" />
|
||||
{props.conditionIcon && (
|
||||
<ConditionIcon
|
||||
className={`t--sidebar-${props.title}-condition-icon`}
|
||||
name={props.conditionIcon}
|
||||
size="md"
|
||||
/>
|
||||
)}
|
||||
</IconContainer>
|
||||
</Tooltip>
|
||||
{props.title ? <Text kind="body-s">{props.title}</Text> : null}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default SidebarButton;
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import SidebarButton from "./SidebarButton";
|
||||
import type { SidebarButton as SidebarButtonType } from "@appsmith/entities/IDE/constants";
|
||||
import { SideButtonType } from "@appsmith/entities/IDE/constants";
|
||||
import { useSelector } from "react-redux";
|
||||
import { getDatasources } from "@appsmith/selectors/entitiesSelector";
|
||||
|
||||
const Container = styled.div`
|
||||
width: 50px;
|
||||
border-right: 1px solid var(--ads-v2-color-border);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: var(--ads-v2-color-bg);
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
interface SidebarComponentProps {
|
||||
topButtons: SidebarButtonType[];
|
||||
bottomButtons: SidebarButtonType[];
|
||||
appState: string;
|
||||
onClick: (suffix: string) => void;
|
||||
}
|
||||
|
||||
function SidebarComponent(props: SidebarComponentProps) {
|
||||
const { appState, bottomButtons, onClick, topButtons } = props;
|
||||
const datasources = useSelector(getDatasources);
|
||||
const getConditionalIconAndTooltip = (
|
||||
type?: SideButtonType,
|
||||
conditionTooltip?: string,
|
||||
) => {
|
||||
switch (type) {
|
||||
case SideButtonType.DATSOURCE:
|
||||
if (datasources.length === 0)
|
||||
return {
|
||||
conditionIcon: "warning",
|
||||
tooltip: conditionTooltip,
|
||||
};
|
||||
return {};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Container className="t--sidebar" id="t--app-sidebar">
|
||||
<div>
|
||||
{topButtons.map((b) => (
|
||||
<SidebarButton
|
||||
icon={b.icon}
|
||||
key={b.state}
|
||||
onClick={() => {
|
||||
if (appState !== b.state) {
|
||||
onClick(b.urlSuffix);
|
||||
}
|
||||
}}
|
||||
selected={appState === b.state}
|
||||
title={b.title}
|
||||
{...getConditionalIconAndTooltip(
|
||||
b.conditionType,
|
||||
b.conditionTooltip,
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
{bottomButtons.map((b) => (
|
||||
<SidebarButton
|
||||
icon={b.icon}
|
||||
key={b.state}
|
||||
onClick={() => {
|
||||
if (appState !== b.state) {
|
||||
onClick(b.urlSuffix);
|
||||
}
|
||||
}}
|
||||
selected={appState === b.state}
|
||||
tooltip={b.title}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default SidebarComponent;
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
import React, { useCallback, useEffect } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { builderURL } from "@appsmith/RouteBuilder";
|
||||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import history, { NavigationMethod } from "utils/history";
|
||||
import { useCurrentAppState } from "../hooks";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import { fetchWorkspace } from "@appsmith/actions/workspaceActions";
|
||||
import SidebarComponent from "./SidebarComponent";
|
||||
import { BottomButtons, TopButtons } from "@appsmith/entities/IDE/constants";
|
||||
|
||||
function Sidebar() {
|
||||
const dispatch = useDispatch();
|
||||
const appState = useCurrentAppState();
|
||||
const pageId = useSelector(getCurrentPageId);
|
||||
|
||||
const currentWorkspaceId = useSelector(getCurrentWorkspaceId);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchWorkspace(currentWorkspaceId));
|
||||
}, [currentWorkspaceId]);
|
||||
|
||||
const onClick = useCallback(
|
||||
(suffix) => {
|
||||
history.push(
|
||||
builderURL({
|
||||
pageId,
|
||||
suffix,
|
||||
}),
|
||||
{
|
||||
invokedBy: NavigationMethod.AppSidebar,
|
||||
},
|
||||
);
|
||||
},
|
||||
[pageId],
|
||||
);
|
||||
|
||||
return (
|
||||
<SidebarComponent
|
||||
appState={appState}
|
||||
bottomButtons={BottomButtons}
|
||||
onClick={onClick}
|
||||
topButtons={TopButtons}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Sidebar;
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
import { css } from "styled-components";
|
||||
import type { JSActionDropdownOption } from "./utils";
|
||||
|
||||
export const RUN_BUTTON_DEFAULTS = {
|
||||
|
|
@ -52,26 +51,3 @@ export const ANIMATE_RUN_GUTTER = "animate-run-marker";
|
|||
export const testLocators = {
|
||||
runJSAction: "run-js-action",
|
||||
};
|
||||
|
||||
export const CodeEditorWithGutterStyles = css`
|
||||
.${RUN_GUTTER_ID} {
|
||||
width: 0.5em;
|
||||
background: #f0f0f0;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.${RUN_GUTTER_CLASSNAME} {
|
||||
cursor: pointer;
|
||||
color: var(--ads-v2-color-fg-brand);
|
||||
}
|
||||
.CodeMirror-linenumbers {
|
||||
width: max-content;
|
||||
}
|
||||
.CodeMirror-linenumber {
|
||||
text-align: right;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.cm-s-duotone-light.CodeMirror {
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user