diff --git a/app/client/src/actions/onboardingActions.ts b/app/client/src/actions/onboardingActions.ts index 2f3412a871ad..59c907edbde5 100644 --- a/app/client/src/actions/onboardingActions.ts +++ b/app/client/src/actions/onboardingActions.ts @@ -1,5 +1,4 @@ import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import type { SIGNPOSTING_STEP } from "pages/Editor/FirstTimeUserOnboarding/Utils"; export const toggleInOnboardingWidgetSelection = (payload: boolean) => { return { @@ -58,27 +57,6 @@ export const signpostingMarkAllRead = () => { }; }; -export const signpostingStepUpdateInit = (payload: { - step: SIGNPOSTING_STEP; - completed: boolean; -}) => { - return { - type: ReduxActionTypes.SIGNPOSTING_STEP_UPDATE_INIT, - payload, - }; -}; - -export const signpostingStepUpdate = (payload: { - step: SIGNPOSTING_STEP; - completed: boolean; - read?: boolean; -}) => { - return { - type: ReduxActionTypes.SIGNPOSTING_STEP_UPDATE, - payload, - }; -}; - export const showSignpostingTooltip = (payload: boolean) => { return { type: ReduxActionTypes.SIGNPOSTING_SHOW_TOOLTIP, diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index bcb0b248ce1e..a25e2fc70c60 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -389,8 +389,6 @@ const OnboardingActionTypes = { UNDO_END_FIRST_TIME_USER_ONBOARDING: "UNDO_END_FIRST_TIME_USER_ONBOARDING", SET_SIGNPOSTING_OVERLAY: "SET_SIGNPOSTING_OVERLAY", SIGNPOSTING_MARK_ALL_READ: "SIGNPOSTING_MARK_ALL_READ", - SIGNPOSTING_STEP_UPDATE_INIT: "SIGNPOSTING_STEP_UPDATE_INIT", - SIGNPOSTING_STEP_UPDATE: "SIGNPOSTING_STEP_UPDATE", SIGNPOSTING_SHOW_TOOLTIP: "SIGNPOSTING_SHOW_TOOLTIP", SHOW_ANONYMOUS_DATA_POPUP: "SHOW_ANONYMOUS_DATA_POPUP", FIRST_TIME_USER_ONBOARDING_INIT: "FIRST_TIME_USER_ONBOARDING_INIT", @@ -1190,8 +1188,6 @@ const AppThemeActionErrorTypes = { }; const AppSettingsActionTypes = { - OPEN_APP_SETTINGS_PANE: "OPEN_APP_SETTINGS_PANE", - CLOSE_APP_SETTINGS_PANE: "CLOSE_APP_SETTINGS_PANE", UPDATE_APP_SETTINGS_PANE_SELECTED_TAB: "UPDATE_APP_SETTINGS_PANE_SELECTED_TAB", }; diff --git a/app/client/src/ce/reducers/uiReducers/explorerReducer.ts b/app/client/src/ce/reducers/uiReducers/explorerReducer.ts index 79875226f326..7b7867c70ab0 100644 --- a/app/client/src/ce/reducers/uiReducers/explorerReducer.ts +++ b/app/client/src/ce/reducers/uiReducers/explorerReducer.ts @@ -196,29 +196,6 @@ export const handlers = { active: action.payload, }; }, - [ReduxActionTypes.OPEN_APP_SETTINGS_PANE]: ( - state: ExplorerReduxState, - ): ExplorerReduxState => { - return { - ...state, - pinnedState: - state.pinnedState === ExplorerPinnedState.PINNED - ? ExplorerPinnedState.HIDDEN - : state.pinnedState, - active: false, - }; - }, - [ReduxActionTypes.CLOSE_APP_SETTINGS_PANE]: ( - state: ExplorerReduxState, - ): ExplorerReduxState => { - return { - ...state, - pinnedState: - state.pinnedState === ExplorerPinnedState.HIDDEN - ? ExplorerPinnedState.PINNED - : state.pinnedState, - }; - }, }; const explorerReducer = createReducer(initialState, handlers); diff --git a/app/client/src/pages/Editor/Explorer/Common/EntityExplorerResizeHandler.tsx b/app/client/src/pages/Editor/Explorer/Common/EntityExplorerResizeHandler.tsx index 9e4fb680ca57..d8aa2cf21a31 100644 --- a/app/client/src/pages/Editor/Explorer/Common/EntityExplorerResizeHandler.tsx +++ b/app/client/src/pages/Editor/Explorer/Common/EntityExplorerResizeHandler.tsx @@ -1,8 +1,10 @@ import { tailwindLayers } from "constants/Layers"; import React from "react"; import styled from "styled-components"; -import type { CallbackResponseType } from "utils/hooks/useResize"; -import useResize, { DIRECTION } from "utils/hooks/useResize"; +import useResize, { + DIRECTION, + type CallbackResponseType, +} from "utils/hooks/useResize"; const ResizeHandler = styled.div` &:hover { @@ -33,8 +35,8 @@ export const EntityExplorerResizeHandler = ({ onMouseDown={() => setMouseDown(true)} > diff --git a/app/client/src/pages/Editor/Explorer/Common/components.tsx b/app/client/src/pages/Editor/Explorer/Common/components.tsx index d72fac82c317..270c003f3c4d 100644 --- a/app/client/src/pages/Editor/Explorer/Common/components.tsx +++ b/app/client/src/pages/Editor/Explorer/Common/components.tsx @@ -1,7 +1,6 @@ import styled from "styled-components"; import Entity, { EntityClassNames } from "../Entity"; -export const ENTITY_HEIGHT = 36; export const MIN_PAGES_HEIGHT = 60; export const RelativeContainer = styled.div` diff --git a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx b/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx deleted file mode 100644 index c86c3c293053..000000000000 --- a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import React, { useRef, useCallback, useEffect } from "react"; -import styled from "styled-components"; -import { NonIdealState, Classes } from "@blueprintjs/core"; -import { useDispatch, useSelector } from "react-redux"; - -import { Colors } from "constants/Colors"; - -import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; -import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions"; - -import { forceOpenWidgetPanel } from "actions/widgetSidebarActions"; -import Files from "./Files"; -import ExplorerWidgetGroup from "./Widgets/WidgetGroup"; -import { builderURL } from "ee/RouteBuilder"; -import history from "utils/history"; -import { - getCurrentBasePageId, - getCurrentPageId, - getPagePermissions, -} from "selectors/editorSelectors"; -import { fetchWorkspace } from "ee/actions/workspaceActions"; -import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors"; -import { importSvg } from "@appsmith/ads-old"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { EntityExplorerWrapper } from "./Common/EntityExplorerWrapper"; -import { getCurrentApplicationId } from "selectors/editorSelectors"; -import { FilesContextProvider } from "./Files/FilesContextProvider"; -import { getHasCreateActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { ActionParentEntityType } from "ee/entities/Engine/actionHelpers"; -import { getShowWorkflowFeature } from "ee/selectors/workflowSelectors"; - -const NoEntityFoundSvg = importSvg( - async () => import("assets/svg/no_entities_found.svg"), -); - -const NoResult = styled(NonIdealState)` - &.${Classes.NON_IDEAL_STATE} { - height: auto; - margin: 20px 0; - - .${Classes.NON_IDEAL_STATE_VISUAL} { - margin-bottom: 16px; - height: 52px; - - svg { - height: 52px; - width: 144px; - } - } - - div { - color: ${Colors.DOVE_GRAY2}; - } - - .${Classes.HEADING} { - margin-bottom: 4px; - color: ${(props) => props.theme.colors.textOnWhiteBG}; - } - } -`; - -function EntityExplorer({ isActive }: { isActive: boolean }) { - const dispatch = useDispatch(); - const explorerRef = useRef(null); - const isFirstTimeUserOnboardingEnabled = useSelector( - getIsFirstTimeUserOnboardingEnabled, - ); - const noResults = false; - const basePageId = useSelector(getCurrentBasePageId); - const pageId = useSelector(getCurrentPageId); - const showWidgetsSidebar = useCallback(() => { - AnalyticsUtil.logEvent("EXPLORER_WIDGET_CLICK"); - history.push(builderURL({ basePageId })); - dispatch(forceOpenWidgetPanel(true)); - - if (isFirstTimeUserOnboardingEnabled) { - dispatch(toggleInOnboardingWidgetSelection(true)); - } - }, [isFirstTimeUserOnboardingEnabled, basePageId]); - - const currentWorkspaceId = useSelector(getCurrentWorkspaceId); - - useEffect(() => { - dispatch(fetchWorkspace(currentWorkspaceId)); - }, [currentWorkspaceId]); - - const applicationId = useSelector(getCurrentApplicationId); - - const pagePermissions = useSelector(getPagePermissions); - - const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - - const canCreateActions = getHasCreateActionPermission( - isFeatureEnabled, - pagePermissions, - ); - - const showWorkflows = useSelector(getShowWorkflowFeature); - - return ( - - - - - - {noResults && ( - } - title="No entities found" - /> - )} - - ); -} - -EntityExplorer.displayName = "EntityExplorer"; - -export default EntityExplorer; diff --git a/app/client/src/pages/Editor/Explorer/Pages/index.tsx b/app/client/src/pages/Editor/Explorer/Pages/index.tsx deleted file mode 100644 index db37964f5f8d..000000000000 --- a/app/client/src/pages/Editor/Explorer/Pages/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { - getCurrentApplicationId, - getCurrentPageId, -} from "selectors/editorSelectors"; -import { EntityClassNames } from "../Entity"; -import { createNewPageFromEntities } from "actions/pageActions"; -import { ADD_PAGE_TOOLTIP, createMessage } from "ee/constants/messages"; -import type { Page } from "entities/Page"; -import { getNextEntityName } from "utils/AppsmithUtils"; -import { getExplorerPinned } from "selectors/explorerSelector"; -import { setExplorerPinnedAction } from "actions/explorerActions"; -import { selectAllPages } from "ee/selectors/entitiesSelector"; -import { - getExplorerStatus, - saveExplorerStatus, -} from "ee/pages/Editor/Explorer/helpers"; -import AddPageContextMenu from "./AddPageContextMenu"; -import { useLocation } from "react-router"; -import type { AppState } from "ee/reducers"; -import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors"; -import { getInstanceId } from "ee//selectors/tenantSelectors"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { getHasCreatePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; -import { - ENTITY_HEIGHT, - RelativeContainer, - StyledEntity, -} from "../Common/components"; -import { EntityExplorerResizeHandler } from "../Common/EntityExplorerResizeHandler"; -import { PageElement } from "pages/Editor/IDE/EditorPane/components/PageElement"; -import { getCurrentApplication } from "ee/selectors/applicationSelectors"; - -function Pages() { - const applicationId = useSelector(getCurrentApplicationId); - const pages: Page[] = useSelector(selectAllPages); - const currentPageId = useSelector(getCurrentPageId); - const pinned = useSelector(getExplorerPinned); - const dispatch = useDispatch(); - const isPagesOpen = getExplorerStatus(applicationId, "pages"); - const pageResizeRef = useRef(null); - const storedHeightKey = "pagesContainerHeight_" + applicationId; - const storedHeight = localStorage.getItem(storedHeightKey); - const location = useLocation(); - - useEffect(() => { - if ((isPagesOpen === null ? true : isPagesOpen) && pageResizeRef.current) { - pageResizeRef.current.style.height = storedHeight + "px"; - } - }, [pageResizeRef]); - - useEffect(() => { - // scroll to the current page - const currentPage = document.getElementById("entity-" + currentPageId); - - if (currentPage) { - setTimeout(() => currentPage.scrollIntoView(), 0); - } - }, [currentPageId]); - - const [isMenuOpen, openMenu] = useState(false); - - const workspaceId = useSelector(getCurrentWorkspaceId); - const instanceId = useSelector(getInstanceId); - - const createPageCallback = useCallback(() => { - const name = getNextEntityName( - "Page", - pages.map((page: Page) => page.pageName), - ); - - dispatch( - createNewPageFromEntities(applicationId, name, workspaceId, instanceId), - ); - }, [dispatch, pages, applicationId]); - - const onMenuClose = useCallback(() => openMenu(false), [openMenu]); - - /** - * toggles the pinned state of sidebar - */ - const onPin = useCallback(() => { - dispatch(setExplorerPinnedAction(!pinned)); - }, [pinned, dispatch, setExplorerPinnedAction]); - - const onPageToggle = useCallback( - (isOpen: boolean) => { - saveExplorerStatus(applicationId, "pages", isOpen); - }, - [applicationId], - ); - - const userAppPermissions = useSelector( - (state: AppState) => getCurrentApplication(state)?.userPermissions ?? [], - ); - - const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - - const canCreatePages = getHasCreatePagePermission( - isFeatureEnabled, - userAppPermissions, - ); - - const pageElements = useMemo( - () => pages.map((page) => ), - [pages, location.pathname], - ); - - return ( - - - } - entityId="Pages" - entitySize={ENTITY_HEIGHT * pages.length} - icon={""} - isDefaultExpanded={ - isPagesOpen === null || isPagesOpen === undefined ? true : isPagesOpen - } - name="Pages" - onClickPreRightIcon={onPin} - onToggle={onPageToggle} - searchKeyword={""} - showAddButton={canCreatePages} - step={0} - > - {pageElements} - - - - ); -} - -Pages.displayName = "Pages"; - -export default React.memo(Pages); diff --git a/app/client/src/pages/Editor/Explorer/Widgets/WidgetGroup.tsx b/app/client/src/pages/Editor/Explorer/Widgets/WidgetGroup.tsx deleted file mode 100644 index 46239a22ca15..000000000000 --- a/app/client/src/pages/Editor/Explorer/Widgets/WidgetGroup.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { memo, useCallback, useMemo } from "react"; -import { useSelector } from "react-redux"; -import Entity from "../Entity"; -import WidgetEntity from "./WidgetEntity"; -import { - getCurrentApplicationId, - getCurrentBasePageId, - getPagePermissions, -} from "selectors/editorSelectors"; -import { - ADD_WIDGET_BUTTON, - ADD_WIDGET_TOOLTIP, - createMessage, - EMPTY_WIDGET_BUTTON_TEXT, - EMPTY_WIDGET_MAIN_TEXT, -} from "ee/constants/messages"; -import { selectWidgetsForCurrentPage } from "ee/selectors/entitiesSelector"; -import { - getExplorerStatus, - saveExplorerStatus, -} from "ee/pages/Editor/Explorer/helpers"; -import { AddEntity, EmptyComponent } from "../common"; -import { noop } from "lodash"; -import { Icon } from "@appsmith/ads"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; - -interface ExplorerWidgetGroupProps { - step: number; - searchKeyword?: string; - addWidgetsFn?: () => void; -} - -export const ExplorerWidgetGroup = memo((props: ExplorerWidgetGroupProps) => { - const applicationId = useSelector(getCurrentApplicationId); - const basePageId = useSelector(getCurrentBasePageId) || ""; - const widgets = useSelector(selectWidgetsForCurrentPage); - let isWidgetsOpen = getExplorerStatus(applicationId, "widgets"); - - if (isWidgetsOpen === null || isWidgetsOpen === undefined) { - isWidgetsOpen = widgets?.children?.length === 0; - saveExplorerStatus(applicationId, "widgets", isWidgetsOpen); - } - - const widgetsInStep = useMemo(() => { - return widgets?.children?.map((child) => child.widgetId) || []; - }, [widgets?.children]); - - const onWidgetToggle = useCallback( - (isOpen: boolean) => { - saveExplorerStatus(applicationId, "widgets", isOpen); - }, - [applicationId], - ); - - const pagePermissions = useSelector(getPagePermissions); - - const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - - const canManagePages = getHasManagePagePermission( - isFeatureEnabled, - pagePermissions, - ); - - return ( - - {widgets?.children?.map((child) => ( - - ))} - {(!widgets?.children || widgets?.children.length === 0) && - !props.searchKeyword && ( - - )} - {widgets?.children && widgets?.children?.length > 0 && canManagePages && ( - } - name={createMessage(ADD_WIDGET_BUTTON)} - step={props.step + 1} - /> - )} - - ); -}); - -ExplorerWidgetGroup.displayName = "ExplorerWidgetGroup"; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -(ExplorerWidgetGroup as any).whyDidYouRender = { - logOnDifferentValues: false, -}; - -export default ExplorerWidgetGroup; diff --git a/app/client/src/pages/Editor/Explorer/index.tsx b/app/client/src/pages/Editor/Explorer/index.tsx deleted file mode 100644 index 61bc6b77ac4b..000000000000 --- a/app/client/src/pages/Editor/Explorer/index.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import React, { useEffect } from "react"; -import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions"; -import { forceOpenWidgetPanel } from "actions/widgetSidebarActions"; -import { SegmentedControl } from "@appsmith/ads"; -import { useDispatch, useSelector } from "react-redux"; -import { useLocation } from "react-router"; -import type { AppState } from "ee/reducers"; -import { builderURL } from "ee/RouteBuilder"; -import { getCurrentBasePageId } from "selectors/editorSelectors"; -import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { trimQueryString } from "utils/helpers"; -import history from "utils/history"; -import EntityExplorer from "./EntityExplorer"; -import { getExplorerSwitchIndex } from "selectors/editorContextSelectors"; -import { setExplorerSwitchIndex } from "actions/editorContextActions"; -import UIEntitySidebar from "../widgetSidebar/UIEntitySidebar"; -import { ExplorerWrapper } from "./Common/ExplorerWrapper"; - -const selectForceOpenWidgetPanel = (state: AppState) => - state.ui.onBoarding.forceOpenWidgetPanel; - -const options = [ - { - value: "explorer", - label: "Explorer", - }, - { - value: "widgets", - label: "Widgets", - }, -]; - -function ExplorerContent() { - const dispatch = useDispatch(); - const isFirstTimeUserOnboardingEnabled = useSelector( - getIsFirstTimeUserOnboardingEnabled, - ); - const basePageId = useSelector(getCurrentBasePageId); - const location = useLocation(); - const activeSwitchIndex = useSelector(getExplorerSwitchIndex); - - const setActiveSwitchIndex = (index: number) => { - dispatch(setExplorerSwitchIndex(index)); - }; - const openWidgetPanel = useSelector(selectForceOpenWidgetPanel); - - useEffect(() => { - const currentIndex = openWidgetPanel ? 1 : 0; - - if (currentIndex !== activeSwitchIndex) { - setActiveSwitchIndex(currentIndex); - } - }, [openWidgetPanel]); - - const onChange = (value: string) => { - if (value === options[0].value) { - dispatch(forceOpenWidgetPanel(false)); - } else if (value === options[1].value) { - if ( - !(trimQueryString(builderURL({ basePageId })) === location.pathname) - ) { - history.push(builderURL({ basePageId })); - AnalyticsUtil.logEvent("WIDGET_TAB_CLICK", { - type: "WIDGET_TAB", - fromUrl: location.pathname, - toUrl: builderURL({ basePageId }), - }); - } - - AnalyticsUtil.logEvent("EXPLORER_WIDGET_CLICK"); - dispatch(forceOpenWidgetPanel(true)); - dispatch(setExplorerSwitchIndex(1)); - - if (isFirstTimeUserOnboardingEnabled) { - dispatch(toggleInOnboardingWidgetSelection(true)); - } - } - }; - const { value: activeOption } = options[activeSwitchIndex]; - - return ( - -
- -
- - - - -
- ); -} - -export default ExplorerContent; diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.test.tsx b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.test.tsx deleted file mode 100644 index 2e0d8384dc9c..000000000000 --- a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.test.tsx +++ /dev/null @@ -1,238 +0,0 @@ -const dispatch = jest.fn(); - -import React from "react"; -import { Provider } from "react-redux"; -import { render } from "test/testUtils"; -import OnboardingStatusbar from "./Statusbar"; -import { getStore } from "./testUtils"; -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import { SIGNPOSTING_STEP } from "./Utils"; -import { signpostingStepUpdateInit } from "actions/onboardingActions"; -import * as onboardingSelectors from "selectors/onboardingSelectors"; - -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -let container: any = null; - -jest.mock("react-redux", () => { - const originalModule = jest.requireActual("react-redux"); - - return { - ...originalModule, - useDispatch: () => dispatch, - }; -}); - -jest.mock("../../../selectors/onboardingSelectors", () => { - const originalModule = jest.requireActual( - "../../../selectors/onboardingSelectors", - ); - - return { - ...originalModule, - isWidgetActionConnectionPresent: jest.fn(), - }; -}); - -const originalOnboardingSelectors = jest.requireActual( - "../../../selectors/onboardingSelectors", -); - -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function renderComponent(store: any) { - render( - - - , - container, - ); -} - -describe("Statusbar", () => { - beforeEach(() => { - container = document.createElement("div"); - document.body.appendChild(container); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it("is rendered", async () => { - renderComponent(getStore(0)); - expect(dispatch).toHaveBeenCalledTimes(5); - expect(dispatch).toHaveBeenCalledWith( - expect.objectContaining({ - payload: { - completed: false, - step: expect.any(String), - }, - type: ReduxActionTypes.SIGNPOSTING_STEP_UPDATE_INIT, - }), - ); - }); - - it("on completing first step", async () => { - renderComponent(getStore(1)); - expect(dispatch).toHaveBeenNthCalledWith( - 1, - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CONNECT_A_DATASOURCE, - completed: true, - }), - ); - }); - - it("on completing second step", async () => { - renderComponent(getStore(2)); - expect(dispatch).toHaveBeenNthCalledWith( - 2, - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CREATE_A_QUERY, - completed: true, - }), - ); - }); - - it("on completing third step", async () => { - renderComponent(getStore(3)); - expect(dispatch).toHaveBeenNthCalledWith( - 3, - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.ADD_WIDGETS, - completed: true, - }), - ); - }); - - it("on completing fourth step", async () => { - const isWidgetActionConnectionPresentSelector = jest.spyOn( - onboardingSelectors, - "isWidgetActionConnectionPresent", - ); - - isWidgetActionConnectionPresentSelector.mockImplementation(() => { - return true; - }); - renderComponent(getStore(4)); - expect(dispatch).toHaveBeenNthCalledWith( - 4, - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CONNECT_DATA_TO_WIDGET, - completed: true, - }), - ); - }); - - it("on completing fifth step", async () => { - renderComponent(getStore(5)); - expect(dispatch).toHaveBeenNthCalledWith( - 5, - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.DEPLOY_APPLICATIONS, - completed: true, - }), - ); - }); - - it("should test useIsWidgetActionConnectionPresent function", () => { - // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const store = getStore(4).getState() as any; - const isWidgetActionConnectionPresentHelper = () => { - return originalOnboardingSelectors.isWidgetActionConnectionPresent.resultFunc( - store.entities.canvasWidgets, - store.entities.actions, - store.evaluations.dependencies.inverseDependencyMap, - ); - }; - - //Both property and trigger dependency present - expect(isWidgetActionConnectionPresentHelper()).toBe(true); - //only trigger dependency present - store.evaluations.dependencies.inverseDependencyMap = {}; - expect(isWidgetActionConnectionPresentHelper()).toBe(true); - //no dependency present - store.entities.canvasWidgets = {}; - store.entities.actions = []; - expect(isWidgetActionConnectionPresentHelper()).toBe(false); - //only trigger dependency present - store.entities.canvasWidgets = { - [Math.random()]: { - widgetName: "widget", - onClick: "{{Query.run()}}", - dynamicTriggerPathList: [ - { - key: "onClick", - }, - ], - text: "{{Query.data}}", - }, - }; - store.entities.actions = [ - { - config: { - id: Math.random(), - pageId: 1, - name: "Query", - }, - }, - ]; - expect(isWidgetActionConnectionPresentHelper()).toBe(true); - //no dependency present - store.entities.canvasWidgets = {}; - store.entities.actions = []; - expect(isWidgetActionConnectionPresentHelper()).toBe(false); - //only nested trigger dependency present - store.entities.canvasWidgets = { - [Math.random()]: { - widgetName: "widget", - column: { - onClick: "{{Query.run()}}", - }, - dynamicTriggerPathList: [ - { - key: "column.onClick", - }, - ], - text: "label", - }, - }; - store.entities.actions = [ - { - config: { - id: Math.random(), - pageId: 1, - name: "Query", - }, - }, - ]; - expect(isWidgetActionConnectionPresentHelper()).toBe(true); - //no dependency present - store.entities.canvasWidgets = {}; - store.entities.actions = []; - expect(isWidgetActionConnectionPresentHelper()).toBe(false); - //only property dependency present - store.entities.canvasWidgets = { - [Math.random()]: { - widgetName: "widget", - dynamicTriggerPathList: [], - text: "{{Query.data}}", - }, - }; - store.entities.actions = [ - { - config: { - id: Math.random(), - pageId: 1, - name: "Query", - }, - }, - ]; - store.evaluations.dependencies.inverseDependencyMap = { - "Query.data": ["Query", "widget.text"], - }; - expect(isWidgetActionConnectionPresentHelper()).toBe(true); - }); -}); diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx deleted file mode 100644 index c073e8973b27..000000000000 --- a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { useEffect } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { - getApplicationLastDeployedAt, - getCurrentPageId, -} from "selectors/editorSelectors"; -import { - getCanvasWidgets, - getPageActions, - getSavedDatasources, -} from "ee/selectors/entitiesSelector"; -import { SIGNPOSTING_STEP } from "./Utils"; -import { - getFirstTimeUserOnboardingComplete, - isWidgetActionConnectionPresent, -} from "selectors/onboardingSelectors"; -import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; -import { signpostingStepUpdateInit } from "actions/onboardingActions"; - -const useStatusListener = () => { - const datasources = useSelector(getSavedDatasources); - const pageId = useSelector(getCurrentPageId); - const actions = useSelector(getPageActions(pageId)); - const widgets = useSelector(getCanvasWidgets); - const isConnectionPresent = useSelector(isWidgetActionConnectionPresent); - const isDeployed = !!useSelector(getApplicationLastDeployedAt); - const isFirstTimeUserOnboardingComplete = useSelector( - getFirstTimeUserOnboardingComplete, - ); - const dispatch = useDispatch(); - - let percentage = 0; - - if (datasources.length || actions.length) { - percentage += 20; - } - - if (actions.length) { - percentage += 20; - } - - if (Object.keys(widgets).length > 1) { - percentage += 20; - } - - if (isConnectionPresent) { - percentage += 20; - } - - if (isDeployed) { - percentage += 20; - } - - useEffect(() => { - dispatch( - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CONNECT_A_DATASOURCE, - completed: !!(datasources.length || actions.length), - }), - ); - }, [datasources.length, actions.length]); - - useEffect(() => { - dispatch( - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CREATE_A_QUERY, - completed: !!actions.length, - }), - ); - }, [actions.length]); - - useEffect(() => { - dispatch( - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.ADD_WIDGETS, - completed: Object.keys(widgets).length > 1, - }), - ); - }, [Object.keys(widgets).length]); - - useEffect(() => { - dispatch( - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.CONNECT_DATA_TO_WIDGET, - completed: isConnectionPresent, - }), - ); - }, [isConnectionPresent]); - - useEffect(() => { - dispatch( - signpostingStepUpdateInit({ - step: SIGNPOSTING_STEP.DEPLOY_APPLICATIONS, - completed: isDeployed, - }), - ); - }, [isDeployed]); - - useEffect(() => { - if (percentage === 100 && !isFirstTimeUserOnboardingComplete) { - dispatch({ - type: ReduxActionTypes.SET_FIRST_TIME_USER_ONBOARDING_COMPLETE, - payload: true, - }); - } - }, [percentage, isFirstTimeUserOnboardingComplete]); -}; - -export function OnboardingStatusbar() { - useStatusListener(); - - return null; -} - -export default OnboardingStatusbar; diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts b/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts index 6b207add1157..22c1f646a704 100644 --- a/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts +++ b/app/client/src/pages/Editor/FirstTimeUserOnboarding/constants.ts @@ -1,16 +1,6 @@ -import { SIGNPOSTING_STEP } from "./Utils"; - //Hide Anonymous Data Popup after 15 seconds export const ANONYMOUS_DATA_POPOP_TIMEOUT = 15000; //Telemetry Docs Page export const TELEMETRY_DOCS_PAGE_URL = "https://docs.appsmith.com/product/telemetry"; - -export const SIGNPOSTING_ANALYTICS_STEP_NAME = { - [SIGNPOSTING_STEP.CONNECT_A_DATASOURCE]: "Connect to datasource", - [SIGNPOSTING_STEP.CREATE_A_QUERY]: "Created query", - [SIGNPOSTING_STEP.ADD_WIDGETS]: "Created Widget", - [SIGNPOSTING_STEP.CONNECT_DATA_TO_WIDGET]: "Binding success", - [SIGNPOSTING_STEP.DEPLOY_APPLICATIONS]: "Deployed app", -}; diff --git a/app/client/src/pages/Editor/Explorer/Pages/AddPageContextMenu.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Pages/AddPageContextMenu.tsx similarity index 96% rename from app/client/src/pages/Editor/Explorer/Pages/AddPageContextMenu.tsx rename to app/client/src/pages/Editor/IDE/EditorPane/Pages/AddPageContextMenu.tsx index e1501da44948..804b04f23a61 100644 --- a/app/client/src/pages/Editor/Explorer/Pages/AddPageContextMenu.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Pages/AddPageContextMenu.tsx @@ -1,6 +1,9 @@ import React, { useMemo, useState } from "react"; -import { AddButtonWrapper, EntityClassNames } from "../Entity"; -import EntityAddButton from "../Entity/AddButton"; +import { + AddButtonWrapper, + EntityClassNames, +} from "pages/Editor/Explorer/Entity"; +import EntityAddButton from "pages/Editor/Explorer/Entity/AddButton"; import styled from "styled-components"; import { useParams } from "react-router"; import { useDispatch } from "react-redux"; diff --git a/app/client/src/pages/Editor/Explorer/Pages/PageContextMenu.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Pages/PageContextMenu.tsx similarity index 100% rename from app/client/src/pages/Editor/Explorer/Pages/PageContextMenu.tsx rename to app/client/src/pages/Editor/IDE/EditorPane/Pages/PageContextMenu.tsx diff --git a/app/client/src/pages/Editor/IDE/EditorPane/components/PageElement.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Pages/PageElement.tsx similarity index 98% rename from app/client/src/pages/Editor/IDE/EditorPane/components/PageElement.tsx rename to app/client/src/pages/Editor/IDE/EditorPane/Pages/PageElement.tsx index cb880183451b..dcac18c33895 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/components/PageElement.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Pages/PageElement.tsx @@ -7,7 +7,7 @@ import { defaultPageIcon, pageIcon } from "pages/Editor/Explorer/ExplorerIcons"; import { getHasManagePagePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import PageContextMenu from "pages/Editor/Explorer/Pages/PageContextMenu"; +import PageContextMenu from "./PageContextMenu"; import { getCurrentApplicationId, getCurrentPageId, diff --git a/app/client/src/pages/Editor/IDE/EditorPane/PagesSection.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Pages/PagesSection.tsx similarity index 95% rename from app/client/src/pages/Editor/IDE/EditorPane/PagesSection.tsx rename to app/client/src/pages/Editor/IDE/EditorPane/Pages/PagesSection.tsx index b1ecd0dd7ede..56c9bf93b7d5 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/PagesSection.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Pages/PagesSection.tsx @@ -13,11 +13,11 @@ import { EntityClassNames } from "pages/Editor/Explorer/Entity"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; import type { AppState } from "ee/reducers"; import { createNewPageFromEntities } from "actions/pageActions"; -import AddPageContextMenu from "pages/Editor/Explorer/Pages/AddPageContextMenu"; +import AddPageContextMenu from "./AddPageContextMenu"; import { getNextEntityName } from "utils/AppsmithUtils"; import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors"; import { getInstanceId } from "ee/selectors/tenantSelectors"; -import { PageElement } from "pages/Editor/IDE/EditorPane/components/PageElement"; +import { PageElement } from "./PageElement"; import { PAGE_ENTITY_NAME } from "ee/constants/messages"; const PagesSection = ({ onItemSelected }: { onItemSelected: () => void }) => { diff --git a/app/client/src/pages/Editor/Explorer/EntityExplorer.test.tsx b/app/client/src/pages/Editor/IDE/EditorPane/UI/List.test.tsx similarity index 96% rename from app/client/src/pages/Editor/Explorer/EntityExplorer.test.tsx rename to app/client/src/pages/Editor/IDE/EditorPane/UI/List.test.tsx index 04091582d3cd..09b7af082f59 100644 --- a/app/client/src/pages/Editor/Explorer/EntityExplorer.test.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/UI/List.test.tsx @@ -13,7 +13,7 @@ import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import * as widgetSelectionsActions from "actions/widgetSelectionActions"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { NavigationMethod } from "utils/history"; -import WidgetsEditorEntityExplorer from "../WidgetsEditorEntityExplorer"; +import ListWidgets from "./List"; jest.useFakeTimers(); const pushState = jest.spyOn(window.history, "pushState"); @@ -51,7 +51,9 @@ jest .spyOn(explorerSelector, "getExplorerWidth") .mockImplementation(() => DEFAULT_ENTITY_EXPLORER_WIDTH); -describe("Entity Explorer tests", () => { +const setFocusSearchInput = jest.fn(); + +describe("Widget List in Explorer tests", () => { beforeAll(() => { runSagaMiddleware(); }); @@ -83,13 +85,13 @@ describe("Entity Explorer tests", () => { }); const component = render( - + , ); // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any const widgetsTree: Element = await component.findByText( - "Widgets", + children[0].widgetName, { selector: "div.t--entity-name", }, @@ -128,7 +130,7 @@ describe("Entity Explorer tests", () => { }); const component = render( - + , ); // TODO: Fix this the next time the file is edited @@ -169,7 +171,7 @@ describe("Entity Explorer tests", () => { }); const component = render( - + , ); // TODO: Fix this the next time the file is edited @@ -226,7 +228,7 @@ describe("Entity Explorer tests", () => { }); const component = render( - + , ); @@ -320,7 +322,7 @@ describe("Entity Explorer tests", () => { }); const component = render( - + , ); // TODO: Fix this the next time the file is edited diff --git a/app/client/src/pages/Editor/IDE/Header/EditorTitle.tsx b/app/client/src/pages/Editor/IDE/Header/EditorTitle.tsx index 327b6f72ed35..8817dced4805 100644 --- a/app/client/src/pages/Editor/IDE/Header/EditorTitle.tsx +++ b/app/client/src/pages/Editor/IDE/Header/EditorTitle.tsx @@ -2,7 +2,7 @@ import React from "react"; import { IDEHeaderSwitcher } from "@appsmith/ads"; import { createMessage, HEADER_TITLES } from "ee/constants/messages"; -import { PagesSection } from "../EditorPane/PagesSection"; +import { PagesSection } from "../EditorPane/Pages/PagesSection"; import { useBoolean } from "usehooks-ts"; import { useSelector } from "react-redux"; import { getCurrentPageId, getPageById } from "selectors/editorSelectors"; diff --git a/app/client/src/pages/Editor/WidgetsEditorEntityExplorer.tsx b/app/client/src/pages/Editor/WidgetsEditorEntityExplorer.tsx deleted file mode 100644 index 7826c0a6fac0..000000000000 --- a/app/client/src/pages/Editor/WidgetsEditorEntityExplorer.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react"; -import { useSelector } from "react-redux"; - -import EntityProperties from "./Explorer/Entity/EntityProperties"; -import Explorer from "./Explorer"; -import OnboardingStatusbar from "./FirstTimeUserOnboarding/Statusbar"; -import Pages from "./Explorer/Pages"; -import EntityExplorerSidebar from "components/editorComponents/EntityExplorerSidebar"; -import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; - -function WidgetsEditorEntityExplorer() { - const enableFirstTimeUserOnboarding = useSelector( - getIsFirstTimeUserOnboardingEnabled, - ); - - return ( - - {enableFirstTimeUserOnboarding && } - {/* PagesContainer */} - - {/* Popover that contains the bindings info */} - - {/* Contains entity explorer & widgets library along with a switcher*/} - - - ); -} - -export default WidgetsEditorEntityExplorer; diff --git a/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts b/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts index c49045b8bfcd..17689a2b4cf3 100644 --- a/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/appSettingsPaneReducer.ts @@ -11,25 +11,6 @@ const initialState: AppSettingsPaneReduxState = { }; const appSettingsPaneReducer = createReducer(initialState, { - [ReduxActionTypes.OPEN_APP_SETTINGS_PANE]: ( - state: AppSettingsPaneReduxState, - action: ReduxAction, - ): AppSettingsPaneReduxState => { - return { - ...state, - isOpen: true, - context: action.payload, - }; - }, - [ReduxActionTypes.CLOSE_APP_SETTINGS_PANE]: ( - state: AppSettingsPaneReduxState, - ): AppSettingsPaneReduxState => { - return { - ...state, - isOpen: false, - context: undefined, - }; - }, [ReduxActionTypes.UPDATE_APP_SETTINGS_PANE_SELECTED_TAB]: ( state: AppSettingsPaneReduxState, action: ReduxAction, diff --git a/app/client/src/reducers/uiReducers/onBoardingReducer.ts b/app/client/src/reducers/uiReducers/onBoardingReducer.ts index 7f3c295713ac..41be43fdbac1 100644 --- a/app/client/src/reducers/uiReducers/onBoardingReducer.ts +++ b/app/client/src/reducers/uiReducers/onBoardingReducer.ts @@ -77,26 +77,6 @@ const onboardingReducer = createReducer(initialState, { ) => { return { ...state, forceOpenWidgetPanel: action.payload }; }, - [ReduxActionTypes.SIGNPOSTING_STEP_UPDATE]: ( - state: OnboardingState, - action: ReduxAction, - ) => { - const index = state.stepState.findIndex( - (stepState) => stepState.step === action.payload.step, - ); - const newArray = [...state.stepState]; - - if (index >= 0) { - newArray[index] = action.payload; - } else { - newArray.push(action.payload); - } - - return { - ...state, - stepState: newArray, - }; - }, [ReduxActionTypes.SIGNPOSTING_MARK_ALL_READ]: (state: OnboardingState) => { return { ...state, diff --git a/app/client/src/sagas/OnboardingSagas.ts b/app/client/src/sagas/OnboardingSagas.ts index 3e8389329478..8e9c8b84e6c0 100644 --- a/app/client/src/sagas/OnboardingSagas.ts +++ b/app/client/src/sagas/OnboardingSagas.ts @@ -22,13 +22,10 @@ import { import { getCurrentUser } from "selectors/usersSelectors"; import history from "utils/history"; -import { getSignpostingStepStateByStep } from "selectors/onboardingSelectors"; import { disableStartSignpostingAction, removeFirstTimeUserOnboardingApplicationId as removeFirstTimeUserOnboardingApplicationIdAction, setSignpostingOverlay, - showSignpostingTooltip, - signpostingStepUpdate, } from "actions/onboardingActions"; import { getCurrentApplicationId, @@ -37,11 +34,7 @@ import { import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import type { User } from "constants/userConstants"; import { builderURL } from "ee/RouteBuilder"; -import type { SIGNPOSTING_STEP } from "pages/Editor/FirstTimeUserOnboarding/Utils"; -import type { StepState } from "reducers/uiReducers/onBoardingReducer"; -import { isUndefined } from "lodash"; import { isAirgapped } from "ee/utils/airgapHelpers"; -import { SIGNPOSTING_ANALYTICS_STEP_NAME } from "pages/Editor/FirstTimeUserOnboarding/constants"; // Signposting sagas function* setFirstTimeUserOnboardingApplicationId(action: ReduxAction) { @@ -150,42 +143,6 @@ function* disableStartFirstTimeUserOnboardingSaga() { yield call(setEnableStartSignposting, false); } -function* setSignpostingStepStateSaga( - action: ReduxAction<{ step: SIGNPOSTING_STEP; completed: boolean }>, -) { - const { completed, step } = action.payload; - const stepState: StepState | undefined = yield select( - getSignpostingStepStateByStep, - step, - ); - - // No changes to update so we ignore - if (stepState && stepState.completed === completed) return; - - const readProps = completed - ? { - read: false, - } - : {}; - - yield put( - signpostingStepUpdate({ - ...action.payload, - ...readProps, - }), - ); - - // Show tooltip when a step is completed - if (!isUndefined(readProps.read) && !readProps.read) { - // Show tooltip after a small delay to not be abrupt - yield delay(1000); - AnalyticsUtil.logEvent("SIGNPOSTING_STEP_COMPLETE", { - step_name: SIGNPOSTING_ANALYTICS_STEP_NAME[step], - }); - yield put(showSignpostingTooltip(true)); - } -} - export default function* onboardingActionSagas() { yield all([ takeLatest( @@ -216,9 +173,5 @@ export default function* onboardingActionSagas() { ReduxActionTypes.DISABLE_START_SIGNPOSTING, disableStartFirstTimeUserOnboardingSaga, ), - takeLatest( - ReduxActionTypes.SIGNPOSTING_STEP_UPDATE_INIT, - setSignpostingStepStateSaga, - ), ]); }