fix: remove transition delay in the switch between explorer and widgets. (#13942)

This commit is contained in:
arunvjn 2022-05-20 10:32:13 +05:30 committed by GitHub
parent 961d412a9f
commit 9753df54f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 97 additions and 113 deletions

View File

@ -74,6 +74,7 @@
"evaluatedType": ".t--CodeEditor-evaluatedValue > div:first-of-type pre",
"evaluatedCurrentValue": "div:last-of-type .t--CodeEditor-evaluatedValue > div:last-of-type pre",
"entityExplorersearch": "#entity-explorer-search",
"searchEntityInExplorer": "#search-entity",
"entitySearchResult": ".t--entity-name:contains('",
"saveStatusContainer": ".t--save-status-container",
"saveStatusIsSaving": "t--save-status-is-saving",
@ -156,9 +157,9 @@
"debugErrorMsg": ".t--debugger-message",
"tableButtonVariant": ".t--property-control-buttonvariant .bp3-popover-target",
"debuggerLabel": "span.debugger-label",
"debuggerContextMenu":".t--debugger-contextual-error-menu",
"debuggerContextMenu": ".t--debugger-contextual-error-menu",
"cyclicDependencyError": "//div[@class='Toastify']//span[contains(text(),'Cyclic dependency found while evaluating')]",
"openDocumentationfromErrorTab":"//span[@name='book-line']",
"openDocumentationfromErrorTab": "//span[@name='book-line']",
"appNameDeployMenu": ".t--app-name-menu-deploy-parent",
"appNameDeployMenuPublish": ".t--app-name-menu-deploy",
"appNameDeployMenuCurrentVersion": ".t--app-name-menu-deploy-current-version",
@ -178,4 +179,4 @@
"saveThemeBtn": ".t--save-theme-btn",
"selectThemeBackBtn": ".t--theme-select-back-btn",
"themeAppBorderRadiusBtn": ".t--theme-appBorderRadius"
}
}

View File

@ -313,7 +313,7 @@ Cypress.Commands.add("SearchApp", (appname) => {
});
Cypress.Commands.add("SearchEntity", (apiname1, apiname2) => {
cy.get(commonlocators.entityExplorersearch)
cy.get(commonlocators.searchEntityInExplorer)
.clear({ force: true })
.type(apiname1, { force: true });
// eslint-disable-next-line cypress/no-unnecessary-waiting
@ -329,7 +329,7 @@ Cypress.Commands.add("SearchEntity", (apiname1, apiname2) => {
Cypress.Commands.add("GlobalSearchEntity", (apiname1, dontAssertVisibility) => {
// entity explorer search will be hidden
cy.get(commonlocators.entityExplorersearch)
cy.get(commonlocators.searchEntityInExplorer)
.clear({ force: true })
.type(apiname1, { force: true });
// eslint-disable-next-line cypress/no-unnecessary-waiting
@ -413,7 +413,7 @@ Cypress.Commands.add("CheckAndUnfoldWidgets", () => {
});
Cypress.Commands.add("SearchEntityandOpen", (apiname1) => {
cy.get(commonlocators.entityExplorersearch)
cy.get(commonlocators.searchEntityInExplorer)
.clear({ force: true })
.type(apiname1, { force: true });
cy.CheckAndUnfoldWidgets();
@ -432,7 +432,7 @@ Cypress.Commands.add("SearchEntityandOpen", (apiname1) => {
});
Cypress.Commands.add("SearchEntityAndUnfold", (apiname1) => {
cy.get(commonlocators.entityExplorersearch)
cy.get(commonlocators.searchEntityInExplorer)
.clear({ force: true })
.type(apiname1, { force: true });
// eslint-disable-next-line cypress/no-unnecessary-waiting
@ -451,7 +451,7 @@ Cypress.Commands.add("SearchEntityAndUnfold", (apiname1) => {
Cypress.Commands.add("OpenBindings", (apiname1) => {
cy.wait(500);
cy.get(commonlocators.entityExplorersearch)
cy.get(commonlocators.searchEntityInExplorer)
.clear({ force: true })
.type(apiname1, { force: true });
cy.CheckAndUnfoldWidgets();

View File

@ -7,22 +7,17 @@ import React, {
useMemo,
} from "react";
import classNames from "classnames";
import history from "utils/history";
import * as Sentry from "@sentry/react";
import { PanelStack } from "@blueprintjs/core";
import { useDispatch, useSelector } from "react-redux";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
import { AppState } from "reducers";
import {
getFirstTimeUserOnboardingComplete,
getIsFirstTimeUserOnboardingEnabled,
} from "selectors/onboardingSelectors";
import Explorer from "pages/Editor/Explorer";
import Switcher from "components/ads/Switcher";
import { trimQueryString } from "utils/helpers";
import AppComments from "comments/AppComments/AppComments";
import { setExplorerActiveAction } from "actions/explorerActions";
import {
@ -33,14 +28,10 @@ import { tailwindLayers } from "constants/Layers";
import TooltipComponent from "components/ads/Tooltip";
import { previewModeSelector } from "selectors/editorSelectors";
import useHorizontalResize from "utils/hooks/useHorizontalResize";
import { forceOpenWidgetPanel } from "actions/widgetSidebarActions";
import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions";
import OnboardingStatusbar from "pages/Editor/FirstTimeUserOnboarding/Statusbar";
import Pages from "pages/Editor/Explorer/Pages";
import { Colors } from "constants/Colors";
import { EntityProperties } from "pages/Editor/Explorer/Entity/EntityProperties";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import { builderURL } from "RouteBuilder";
type Props = {
width: number;
@ -58,38 +49,12 @@ export const EntityExplorerSidebar = memo((props: Props) => {
const enableFirstTimeUserOnboarding = useSelector(
getIsFirstTimeUserOnboardingEnabled,
);
const isFirstTimeUserOnboardingEnabled = useSelector(
getIsFirstTimeUserOnboardingEnabled,
);
const resizer = useHorizontalResize(
sidebarRef,
props.onWidthChange,
props.onDragEnd,
);
const switches = [
{
id: "explorer",
text: "Explorer",
action: () => dispatch(forceOpenWidgetPanel(false)),
},
{
id: "widgets",
text: "Widgets",
action: () => {
!(trimQueryString(builderURL()) === window.location.pathname) &&
history.push(builderURL());
setTimeout(() => dispatch(forceOpenWidgetPanel(true)), 0);
if (isFirstTimeUserOnboardingEnabled) {
dispatch(toggleInOnboardingWidgetSelection(true));
}
},
},
];
const [activeSwitch, setActiveSwitch] = useState(switches[0]);
const [tooltipIsOpen, setTooltipIsOpen] = useState(false);
const isForceOpenWidgetPanel = useSelector(
(state: AppState) => state.ui.onBoarding.forceOpenWidgetPanel,
);
const isFirstTimeUserOnboardingComplete = useSelector(
getFirstTimeUserOnboardingComplete,
);
@ -98,14 +63,6 @@ export const EntityExplorerSidebar = memo((props: Props) => {
PerformanceTracker.stopTracking();
});
useEffect(() => {
if (isForceOpenWidgetPanel) {
setActiveSwitch(switches[1]);
} else {
setActiveSwitch(switches[0]);
}
}, [isForceOpenWidgetPanel]);
// registering event listeners
useEffect(() => {
document.addEventListener("mousemove", onMouseMove);
@ -191,7 +148,7 @@ export const EntityExplorerSidebar = memo((props: Props) => {
<div
className={classNames({
[`js-entity-explorer t--entity-explorer transform transition-all flex h-full duration-400 border-r border-gray-200 ${tailwindLayers.entityExplorer}`]: true,
"relative ": pinned && !isPreviewMode,
relative: pinned && !isPreviewMode,
"-translate-x-full": (!pinned && !active) || isPreviewMode,
"shadow-xl": !pinned,
fixed: !pinned || isPreviewMode,
@ -199,7 +156,7 @@ export const EntityExplorerSidebar = memo((props: Props) => {
>
{/* SIDEBAR */}
<div
className="flex flex-col p-0 overflow-y-auto bg-white t--sidebar min-w-48 max-w-96 group"
className="flex flex-col p-0 bg-white t--sidebar min-w-48 max-w-96 group"
ref={sidebarRef}
style={{ width: props.width }}
>
@ -209,19 +166,8 @@ export const EntityExplorerSidebar = memo((props: Props) => {
<Pages />
{/* Popover that contains the bindings info */}
<EntityProperties />
{/* SWITCHER */}
<div
className={`px-3 mt-1 py-2 border-t border-b border-[${Colors.Gallery}]`}
>
<Switcher activeObj={activeSwitch} switches={switches} />
</div>
<PanelStack
className="flex-grow"
initialPanel={{
component: Explorer,
}}
showPanelHeader={false}
/>
{/* Contains entity explorer & widgets library along with a switcher*/}
<Explorer />
<AppComments />
</div>
{/* RESIZER */}

View File

@ -1,2 +1,3 @@
export const ENTITY_EXPLORER_SEARCH_ID = "entity-explorer-search";
export const WIDGETS_SEARCH_ID = "#widgets-search";
export const SEARCH_ENTITY = "search-entity";

View File

@ -220,11 +220,11 @@ export const Entity = forwardRef(
/* eslint-disable react-hooks/exhaustive-deps */
useEffect(() => {
if (props.isDefaultExpanded) {
if (props.isDefaultExpanded || props.searchKeyword) {
open(true);
props.onToggle && props.onToggle(true);
}
}, [props.isDefaultExpanded]);
}, [props.isDefaultExpanded, props.searchKeyword]);
useEffect(() => {
if (!props.searchKeyword && !props.isDefaultExpanded) {
open(false);

View File

@ -8,9 +8,7 @@ import React, {
import styled from "styled-components";
import Divider from "components/editorComponents/Divider";
import Search from "./ExplorerSearch";
import { NonIdealState, Classes, IPanelProps } from "@blueprintjs/core";
import WidgetSidebar from "../WidgetSidebar";
import history from "utils/history";
import { NonIdealState, Classes } from "@blueprintjs/core";
import JSDependencies from "./JSDependencies";
import PerformanceTracker, {
PerformanceTransactionName,
@ -29,6 +27,8 @@ import Datasources from "./Datasources";
import Files from "./Files";
import ExplorerWidgetGroup from "./Widgets/WidgetGroup";
import { builderURL } from "RouteBuilder";
import history from "utils/history";
import { SEARCH_ENTITY } from "constants/Explorer";
const Wrapper = styled.div`
height: 100%;
@ -71,7 +71,7 @@ const StyledDivider = styled(Divider)`
border-bottom-color: #f0f0f0;
`;
function EntityExplorer(props: IPanelProps) {
function EntityExplorer({ isActive }: { isActive: boolean }) {
const dispatch = useDispatch();
const [searchKeyword, setSearchKeyword] = useState("");
const searchInputRef: MutableRefObject<HTMLInputElement | null> = useRef(
@ -86,15 +86,13 @@ function EntityExplorer(props: IPanelProps) {
getIsFirstTimeUserOnboardingEnabled,
);
const noResults = false;
const { openPanel } = props;
const showWidgetsSidebar = useCallback(() => {
history.push(builderURL());
openPanel({ component: WidgetSidebar });
dispatch(forceOpenWidgetPanel(true));
if (isFirstTimeUserOnboardingEnabled) {
dispatch(toggleInOnboardingWidgetSelection(true));
}
}, [openPanel, isFirstTimeUserOnboardingEnabled]);
}, [isFirstTimeUserOnboardingEnabled]);
/**
* filter entitites
@ -112,10 +110,14 @@ function EntityExplorer(props: IPanelProps) {
};
return (
<Wrapper className={"relative"} ref={explorerRef}>
<Wrapper
className={`relative overflow-y-auto ${isActive ? "" : "hidden"}`}
ref={explorerRef}
>
{/* SEARCH */}
<Search
clear={clearSearchInput}
id={SEARCH_ENTITY}
isHidden
onChange={search}
ref={searchInputRef}

View File

@ -15,6 +15,7 @@ export const ExplorerSearch = forwardRef(
autoFocus?: boolean;
isHidden?: boolean;
onChange?: (e: any) => void;
id?: string;
},
ref: Ref<HTMLInputElement>,
) => {
@ -62,7 +63,7 @@ export const ExplorerSearch = forwardRef(
autoComplete="off"
autoFocus
className="flex-grow py-2 text-gray-800 bg-transparent placeholder-trueGray-500"
id={ENTITY_EXPLORER_SEARCH_ID}
id={props.id || ENTITY_EXPLORER_SEARCH_ID}
onBlur={() => setFocussed(false)}
onChange={onChange}
onFocus={() => setFocussed(true)}
@ -78,8 +79,7 @@ export const ExplorerSearch = forwardRef(
</div>
<div
className={classNames({
"border-b border-primary-500 transition-all duration-400 absolute bottom-0": true,
"w-0": !focussed,
"border-b border-primary-500 absolute bottom-0": true,
"w-full": focussed,
})}
/>

View File

@ -1,23 +1,73 @@
import { IPanelProps } from "@blueprintjs/core";
import React from "react";
import { useEffect } from "react";
import { useSelector } from "react-redux";
import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions";
import { forceOpenWidgetPanel } from "actions/widgetSidebarActions";
import { Switcher } from "components/ads";
import { Colors } from "constants/Colors";
import { tailwindLayers } from "constants/Layers";
import React, { useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppState } from "reducers";
import { builderURL } from "RouteBuilder";
import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors";
import { trimQueryString } from "utils/helpers";
import history from "utils/history";
import WidgetSidebar from "../WidgetSidebar";
import EntityExplorer from "./EntityExplorer";
const isForceOpenWidgetPanelSelector = (state: AppState) =>
const selectForceOpenWidgetPanel = (state: AppState) =>
state.ui.onBoarding.forceOpenWidgetPanel;
function ExplorerContent(props: IPanelProps) {
const isForceOpenWidgetPanel = useSelector(isForceOpenWidgetPanelSelector);
useEffect(() => {
if (isForceOpenWidgetPanel) {
props.openPanel({ component: WidgetSidebar });
}
}, [isForceOpenWidgetPanel]);
function ExplorerContent() {
const dispatch = useDispatch();
const isFirstTimeUserOnboardingEnabled = useSelector(
getIsFirstTimeUserOnboardingEnabled,
);
const switches = useMemo(
() => [
{
id: "explorer",
text: "Explorer",
action: () => dispatch(forceOpenWidgetPanel(false)),
},
{
id: "widgets",
text: "Widgets",
action: () => {
!(trimQueryString(builderURL()) === window.location.pathname) &&
history.push(builderURL());
dispatch(forceOpenWidgetPanel(true));
if (isFirstTimeUserOnboardingEnabled) {
dispatch(toggleInOnboardingWidgetSelection(true));
}
},
},
],
[
dispatch,
forceOpenWidgetPanel,
isFirstTimeUserOnboardingEnabled,
toggleInOnboardingWidgetSelection,
],
);
const [activeSwitch, setActiveSwitch] = useState(switches[0]);
const openWidgetPanel = useSelector(selectForceOpenWidgetPanel);
return <EntityExplorer {...props} />;
useEffect(() => {
setActiveSwitch(switches[openWidgetPanel ? 1 : 0]);
}, [openWidgetPanel]);
return (
<div
className={`flex-1 flex flex-col overflow-hidden ${tailwindLayers.entityExplorer}`}
>
<div
className={`flex-shrink-0 px-3 mt-1 py-2 border-t border-b border-[${Colors.Gallery}]`}
>
<Switcher activeObj={activeSwitch} switches={switches} />
</div>
<WidgetSidebar isActive={activeSwitch.id === "widgets"} />
<EntityExplorer isActive={activeSwitch.id === "explorer"} />
</div>
);
}
export default ExplorerContent;

View File

@ -33,7 +33,6 @@ import {
ONBOARDING_STATUS_STEPS_THIRD_ALT,
} from "@appsmith/constants/messages";
import { getTypographyByKey } from "constants/DefaultTheme";
import { Colors } from "constants/Colors";
import { onboardingCheckListUrl } from "RouteBuilder";

View File

@ -1,22 +1,16 @@
import React, { useRef, useEffect, useState } from "react";
import React, { useRef, useState } from "react";
import { useSelector } from "react-redux";
import WidgetCard from "./WidgetCard";
import { getWidgetCards } from "selectors/editorSelectors";
import { IPanelProps } from "@blueprintjs/core";
import ExplorerSearch from "./Explorer/ExplorerSearch";
import { debounce } from "lodash";
import produce from "immer";
import { useLocation } from "react-router";
import {
createMessage,
WIDGET_SIDEBAR_CAPTION,
} from "@appsmith/constants/messages";
import { matchBuilderPath } from "constants/routes";
import { AppState } from "reducers";
function WidgetSidebar(props: IPanelProps) {
const location = useLocation();
function WidgetSidebar({ isActive }: { isActive: boolean }) {
const cards = useSelector(getWidgetCards);
const [filteredCards, setFilteredCards] = useState(cards);
const searchInputRef = useRef<HTMLInputElement | null>(null);
@ -33,17 +27,6 @@ function WidgetSidebar(props: IPanelProps) {
}
setFilteredCards(filteredCards);
};
const isForceOpenWidgetPanel = useSelector(
(state: AppState) => state.ui.onBoarding.forceOpenWidgetPanel,
);
const onCanvas = matchBuilderPath(window.location.pathname);
useEffect(() => {
if (!onCanvas || isForceOpenWidgetPanel === false) {
props.closePanel();
}
}, [onCanvas, location, isForceOpenWidgetPanel]);
/**
* filter widgets
@ -64,7 +47,9 @@ function WidgetSidebar(props: IPanelProps) {
};
return (
<div className="flex flex-col overflow-hidden">
<div
className={`flex flex-col overflow-hidden ${isActive ? "" : "hidden"}`}
>
<ExplorerSearch
autoFocus
clear={clearSearchInput}