From d070ca76b0ce86d36b705f282dbf8d9d8549d5a9 Mon Sep 17 00:00:00 2001 From: Aman Agarwal Date: Thu, 23 May 2024 12:43:56 +0530 Subject: [PATCH] fix: add a warning icon and tooltip to indicate empty datasources (#33618) --- app/client/src/ce/constants/messages.ts | 3 +++ app/client/src/ce/entities/IDE/constants.ts | 12 ++++++++++ .../Editor/IDE/Sidebar/SidebarButton.test.tsx | 23 ++++++++++++++++++ .../Editor/IDE/Sidebar/SidebarButton.tsx | 22 +++++++++++++++-- .../Editor/IDE/Sidebar/SidebarComponent.tsx | 24 +++++++++++++++++++ 5 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.test.tsx diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index b30644012c..f0cf7e81c3 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -2514,3 +2514,6 @@ export const BETA_TAG = () => `Beta`; export const BUTTON_WIDGET_DEFAULT_LABEL = () => "Do something"; export const PAGE_ENTITY_NAME = "Page"; + +export const EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON = () => + "Create a datasource to power your app with data."; diff --git a/app/client/src/ce/entities/IDE/constants.ts b/app/client/src/ce/entities/IDE/constants.ts index 4eeb674a04..982b012437 100644 --- a/app/client/src/ce/entities/IDE/constants.ts +++ b/app/client/src/ce/entities/IDE/constants.ts @@ -22,6 +22,10 @@ import { } 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"; export enum EditorState { DATA = "DATA", @@ -57,11 +61,17 @@ 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[] = [ @@ -76,6 +86,8 @@ export const TopButtons: SidebarButton[] = [ icon: "datasource-v3", title: SidebarTopButtonTitles.DATA, urlSuffix: "datasource", + conditionType: SideButtonType.DATSOURCE, + conditionTooltip: createMessage(EMPTY_DATASOURCE_TOOLTIP_SIDEBUTTON), }, ]; diff --git a/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.test.tsx b/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.test.tsx new file mode 100644 index 0000000000..15c2b9de9c --- /dev/null +++ b/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.test.tsx @@ -0,0 +1,23 @@ +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(); + + const svgs = container.querySelectorAll("svg"); + expect(svgs).toHaveLength(2); + }); +}); diff --git a/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.tsx b/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.tsx index c94e7375ba..f217b05fc3 100644 --- a/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.tsx +++ b/app/client/src/pages/Editor/IDE/Sidebar/SidebarButton.tsx @@ -4,12 +4,13 @@ import styled from "styled-components"; import DatasourceStarterLayoutPrompt from "pages/Editor/Explorer/Datasources/DatasourceStarterLayoutPrompt"; import { SidebarTopButtonTitles } from "@appsmith/entities/IDE/constants"; -interface Props { +export interface SidebarButtonProps { title?: string; selected: boolean; icon: string; onClick: () => void; tooltip?: string; + conditionIcon?: string; } const Container = styled.div` @@ -33,6 +34,7 @@ const IconContainer = styled.div<{ selected: boolean }>` align-items: center; justify-content: center; cursor: pointer; + position: relative; &:hover { background: ${(props) => props.selected @@ -41,7 +43,16 @@ const IconContainer = styled.div<{ selected: boolean }>` } `; -function SidebarButton(props: Props) { +const ConditionIcon = styled(Icon)` + position: absolute; + bottom: 3px; + right: -1px; + &.t--sidebar-${SidebarTopButtonTitles.DATA}-condition-icon { + color: #ffe283; + } +`; + +function SidebarButton(props: SidebarButtonProps) { return ( {props.title === SidebarTopButtonTitles.DATA && ( @@ -59,6 +70,13 @@ function SidebarButton(props: Props) { selected={props.selected} > + {props.conditionIcon && ( + + )} {props.title ? {props.title} : null} diff --git a/app/client/src/pages/Editor/IDE/Sidebar/SidebarComponent.tsx b/app/client/src/pages/Editor/IDE/Sidebar/SidebarComponent.tsx index 9bb3618c28..d5e9ccf2f4 100644 --- a/app/client/src/pages/Editor/IDE/Sidebar/SidebarComponent.tsx +++ b/app/client/src/pages/Editor/IDE/Sidebar/SidebarComponent.tsx @@ -2,6 +2,9 @@ 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; @@ -23,6 +26,23 @@ interface SidebarComponentProps { 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 ( @@ -38,6 +58,10 @@ function SidebarComponent(props: SidebarComponentProps) { }} selected={appState === b.state} title={b.title} + {...getConditionalIconAndTooltip( + b.conditionType, + b.conditionTooltip, + )} /> ))}