From fe0ccaaf0aa93b4987437b7d6fd9638a55edcd66 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Thu, 4 Jul 2024 10:19:41 +0530 Subject: [PATCH] chore: Show only a limited set of widgets in the beginning (#34644) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Controls the collapsible sections of the Widget Add pane. This will ensure we do not show all the widgets for add when a new user is exploring for the first time. Once the users adds a widget, the other sections opens up automatically. Also removes List and JSONForm widgets from the SuggestedWidget tag Fixes #34386 ## Automation /ok-to-test tags="@tag.Widget, @tag.IDE" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: a604723af91330158f513764b45051d8be75dc6c > Cypress dashboard. > Tags: `@tag.Widget, @tag.IDE` ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit - **New Features** - Sidebar and tag groups now dynamically open based on widget presence. - **Improvements** - Enhanced initial open state control for tag groups. - Updated widget tag assignments to prioritize layout and display widgets. - **Bug Fixes** - Corrected widget tag selectors to ensure accurate UI element targeting. - **Tests** - Refactored and updated test cases for widget sidebar functionality and UI consistency. --- .../ExplorerTests/Widgets_Sidebar.ts | 19 ++++--- .../cypress/support/Pages/EntityExplorer.ts | 6 +-- app/client/src/constants/WidgetConstants.tsx | 8 ++- .../Editor/widgetSidebar/UIEntitySidebar.tsx | 22 ++++++-- .../Editor/widgetSidebar/UIEntityTagGroup.tsx | 8 ++- .../tests/UIEntitySidebar.test.tsx | 54 +++++++++++-------- .../widgets/JSONFormWidget/widget/index.tsx | 2 +- .../src/widgets/ListWidgetV2/widget/index.tsx | 2 +- 8 files changed, 76 insertions(+), 45 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts index 37921036bea..ef45ab628b6 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Widgets_Sidebar.ts @@ -2,7 +2,9 @@ import { entityExplorer, agHelper, locators, + draggableWidgets, } from "../../../../support/Objects/ObjectsCore"; +import { PageLeftPane } from "../../../../support/Pages/EditorNavigation"; describe( "Entity explorer tests related to widgets and validation", @@ -26,16 +28,14 @@ describe( // Taken from here appsmith/app/client/src/constants/WidgetConstants.tsx const SUGGESTED_WIDGETS_ORDER: Record = { TABLE_WIDGET_V2: 1, - JSON_FORM_WIDGET: 2, - INPUT_WIDGET_V2: 3, - TEXT_WIDGET: 4, - SELECT_WIDGET: 5, - LIST_WIDGET_V2: 6, + INPUT_WIDGET_V2: 2, + TEXT_WIDGET: 3, + SELECT_WIDGET: 4, }; // When adding a new widget or tag, we need to manually add it to this list. const WIDGETS_CATALOG: Record = { - Suggested: ["Input", "JSON Form", "List", "Select", "Table", "Text"], + Suggested: ["Input", "Select", "Table", "Text"], Inputs: [ "Currency Input", "DatePicker", @@ -86,7 +86,12 @@ describe( ); }; - it("1. All widget tags should be visible and open by default.", () => { + before(() => { + entityExplorer.DragDropWidgetNVerify(draggableWidgets.INPUT_V2); + PageLeftPane.switchToAddNew(); + }); + + it("1. All widget tags should be visible but only Suggested tag is open.", () => { agHelper.AssertElementLength( entityExplorer._widgetTagsList, Object.keys(WIDGET_TAGS).length, diff --git a/app/client/cypress/support/Pages/EntityExplorer.ts b/app/client/cypress/support/Pages/EntityExplorer.ts index 7a8386f8b59..4741b6393f3 100644 --- a/app/client/cypress/support/Pages/EntityExplorer.ts +++ b/app/client/cypress/support/Pages/EntityExplorer.ts @@ -65,12 +65,12 @@ export class EntityExplorer { _adsPopup = "div[role='menu']"; _entityExplorerWrapper = ".t--entity-explorer-wrapper"; _widgetTagsList = - "[data-testid='t--widget-sidebar-scrollable-wrapper'] .widget-tag-collapisble"; + "[data-testid='t--widget-sidebar-scrollable-wrapper'] .widget-tag-collapsible"; _widgetCards = ".t--widget-card-draggable"; _widgetSearchInput = "#entity-explorer-search"; _widgetCardTitle = ".t--widget-card-draggable span.ads-v2-text"; - _widgetTagSuggestedWidgets = ".widget-tag-collapisble-suggested"; - _widgetTagBuildingBlocks = ".widget-tag-collapisble-building-blocks"; + _widgetTagSuggestedWidgets = ".widget-tag-collapsible-suggested"; + _widgetTagBuildingBlocks = ".widget-tag-collapsible-building-blocks"; _widgetSeeMoreButton = "[data-testid='t--explorer-ui-entity-tag-see-more']"; public ActionContextMenuByEntityName({ diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index 8835309ff19..073f17e9128 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -256,11 +256,9 @@ export const initialEntityCountForExplorerTag: Partial< export const SUGGESTED_WIDGETS_ORDER: Record = { TABLE_WIDGET_V2: 1, - JSON_FORM_WIDGET: 2, - INPUT_WIDGET_V2: 3, - TEXT_WIDGET: 4, - SELECT_WIDGET: 5, - LIST_WIDGET_V2: 6, + INPUT_WIDGET_V2: 2, + TEXT_WIDGET: 3, + SELECT_WIDGET: 4, }; // Constant key to show walkthrough for a widget -> stores widget id diff --git a/app/client/src/pages/Editor/widgetSidebar/UIEntitySidebar.tsx b/app/client/src/pages/Editor/widgetSidebar/UIEntitySidebar.tsx index 619f536194f..afe18dba518 100644 --- a/app/client/src/pages/Editor/widgetSidebar/UIEntitySidebar.tsx +++ b/app/client/src/pages/Editor/widgetSidebar/UIEntitySidebar.tsx @@ -19,6 +19,8 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { groupWidgetCardsByTags } from "../utils"; import UIEntityTagGroup from "./UIEntityTagGroup"; import { useUIExplorerItems } from "./hooks"; +import { useSelector } from "react-redux"; +import { widgetsExistCurrentPage } from "@appsmith/selectors/entitiesSelector"; function UIEntitySidebar({ focusSearchInput, @@ -36,6 +38,7 @@ function UIEntitySidebar({ const isDragDropBuildingBlocksEnabled = useFeatureFlag( FEATURE_FLAG.release_drag_drop_building_blocks_enabled, ); + const hasWidgets = useSelector(widgetsExistCurrentPage); const hideSuggestedWidgets = useMemo( () => (isSearching && !areSearchResultsEmpty) || @@ -137,9 +140,7 @@ function UIEntitySidebar({ )}
- {Object.keys(filteredCards).map((tag) => { - const cardsForThisTag = filteredCards[tag as WidgetTags]; - + {Object.entries(filteredCards).map(([tag, cardsForThisTag]) => { if (!cardsForThisTag?.length && !entityLoading[tag as WidgetTags]) { return null; } @@ -148,9 +149,24 @@ function UIEntitySidebar({ return null; } + // Do not expand all the widget tags when the user does not have any + // widgets yet. + // Only show Suggested or Building Blocks + let isInitiallyOpen = false; + if ( + hasWidgets || + [ + WIDGET_TAGS.SUGGESTED_WIDGETS as string, + WIDGET_TAGS.BUILDING_BLOCKS as string, + ].includes(tag) + ) { + isInitiallyOpen = true; + } + return ( { + const [isOpen, setIsOpen] = React.useState(props.isInitiallyOpen); const [showFullItems, setShowFullItems] = React.useState(false); const toggleShowFullItems = () => { setShowFullItems(!showFullItems); @@ -77,11 +79,12 @@ const UIEntityTagGroup = (props: Props) => { return ( {
{props.tag === WIDGET_TAGS.SUGGESTED_WIDGETS diff --git a/app/client/src/pages/Editor/widgetSidebar/tests/UIEntitySidebar.test.tsx b/app/client/src/pages/Editor/widgetSidebar/tests/UIEntitySidebar.test.tsx index 4ea53cab7fa..05096d2908f 100644 --- a/app/client/src/pages/Editor/widgetSidebar/tests/UIEntitySidebar.test.tsx +++ b/app/client/src/pages/Editor/widgetSidebar/tests/UIEntitySidebar.test.tsx @@ -1,21 +1,15 @@ +import React from "react"; import { UI_ELEMENT_PANEL_SEARCH_TEXT, createMessage, } from "@appsmith/constants/messages"; -import * as Sentry from "@sentry/react"; import "@testing-library/jest-dom"; -import { fireEvent, render, waitFor } from "@testing-library/react"; +import { fireEvent, waitFor } from "@testing-library/react"; import { WIDGET_TAGS } from "constants/WidgetConstants"; -import { unitTestBaseMockStore } from "layoutSystems/common/dropTarget/unitTestUtils"; -import React from "react"; -import { Provider } from "react-redux"; -import configureStore from "redux-mock-store"; -import { lightTheme } from "selectors/themeSelectors"; -import { ThemeProvider } from "styled-components"; import UIEntitySidebar from "../UIEntitySidebar"; import { cards, groupedCards } from "./UIEntitySidebar.fixture"; - -const mockStore = configureStore([]); +import { render } from "test/testUtils"; +import { getIDETestState } from "test/factories/AppIDEFactoryUtils"; jest.mock("utils/hooks/useFeatureFlag", () => ({ useFeatureFlag: jest.fn(), @@ -32,16 +26,13 @@ describe("UIEntitySidebar", () => { focusSearchInput: boolean, ) => { return render( - - - - - - - , + , + { + initialState: getIDETestState({}), + }, ); }; @@ -104,9 +95,9 @@ describe("UIEntitySidebar", () => { // Render the UIEntitySidebar component const { container } = renderUIEntitySidebar(true, true); - // in the mock data we have 12 tags + // in the mock data, we have 12 tags expect( - container.getElementsByClassName("widget-tag-collapisble").length, + container.getElementsByClassName("widget-tag-collapsible").length, ).toBe(12); }); @@ -125,7 +116,7 @@ describe("UIEntitySidebar", () => { await waitFor(() => { // one from building blocks and one from normal widgets expect( - container.getElementsByClassName("widget-tag-collapisble").length, + container.getElementsByClassName("widget-tag-collapsible").length, ).toBe(2); }); }); @@ -136,4 +127,21 @@ describe("UIEntitySidebar", () => { const { queryByText } = renderUIEntitySidebar(true, true); expect(queryByText(WIDGET_TAGS.SUGGESTED_WIDGETS)).toBeNull(); }); + + it("6. should have `Building Blocks` section open when no widgets exist", () => { + mockUIExplorerItems(); + const { getAllByTestId, getByText } = renderUIEntitySidebar(true, true); + expect(getByText(WIDGET_TAGS.BUILDING_BLOCKS)).not.toBeNull(); + const groups = getAllByTestId("ui-entity-tag-group"); + for (const group of groups) { + if ( + group.getElementsByClassName("t--widget-card-draggable-buildingblock") + .length + ) { + expect(group.getAttribute("data-collapsed")).toBe("false"); + } else { + expect(group.getAttribute("data-collapsed")).toBe("true"); + } + } + }); }); diff --git a/app/client/src/widgets/JSONFormWidget/widget/index.tsx b/app/client/src/widgets/JSONFormWidget/widget/index.tsx index 7e95a2233ed..5e67b286c4e 100644 --- a/app/client/src/widgets/JSONFormWidget/widget/index.tsx +++ b/app/client/src/widgets/JSONFormWidget/widget/index.tsx @@ -152,7 +152,7 @@ class JSONFormWidget extends BaseWidget< name: "JSON Form", iconSVG: IconSVG, thumbnailSVG: ThumbnailSVG, - tags: [WIDGET_TAGS.SUGGESTED_WIDGETS, WIDGET_TAGS.LAYOUT], + tags: [WIDGET_TAGS.LAYOUT], needsMeta: true, }; } diff --git a/app/client/src/widgets/ListWidgetV2/widget/index.tsx b/app/client/src/widgets/ListWidgetV2/widget/index.tsx index 01d0f854b1c..673f78c54f9 100644 --- a/app/client/src/widgets/ListWidgetV2/widget/index.tsx +++ b/app/client/src/widgets/ListWidgetV2/widget/index.tsx @@ -159,7 +159,7 @@ class ListWidget extends BaseWidget< name: "List", iconSVG: IconSVG, thumbnailSVG: ThumbnailSVG, - tags: [WIDGET_TAGS.SUGGESTED_WIDGETS, WIDGET_TAGS.DISPLAY], + tags: [WIDGET_TAGS.DISPLAY], needsMeta: true, isCanvas: true, };