Skip to content
Snippets Groups Projects
Unverified Commit 64d2f1bc authored by Anton Kulyk's avatar Anton Kulyk Committed by GitHub
Browse files

Browsing | Automatically close navbar in certain scenarios (#21358)

parent f18b48f5
No related branches found
No related tags found
No related merge requests found
Showing
with 92 additions and 25 deletions
......@@ -10,7 +10,7 @@ import Search from "metabase/entities/search";
import { getUserIsAdmin } from "metabase/selectors/user";
import { getMetadata } from "metabase/selectors/metadata";
import { getIsBookmarked } from "metabase/collections/selectors";
import { getIsNavbarOpen } from "metabase/redux/app";
import { getIsNavbarOpen, openNavbar } from "metabase/redux/app";
import BulkActions from "metabase/collections/components/BulkActions";
import CollectionEmptyState from "metabase/components/CollectionEmptyState";
......@@ -22,6 +22,7 @@ import { isPersonalCollectionChild } from "metabase/collections/utils";
import ItemsDragLayer from "metabase/containers/dnd/ItemsDragLayer";
import PaginationControls from "metabase/components/PaginationControls";
import { useOnMount } from "metabase/hooks/use-on-mount";
import { usePagination } from "metabase/hooks/use-pagination";
import { useListSelect } from "metabase/hooks/use-list-select";
import {
......@@ -47,6 +48,7 @@ function mapStateToProps(state, props) {
}
const mapDispatchToProps = {
openNavbar,
createBookmark: (id, type) => Bookmark.actions.create({ id, type }),
deleteBookmark: (id, type) => Bookmark.actions.delete({ id, type }),
};
......@@ -62,6 +64,7 @@ function CollectionContent({
isRoot,
metadata,
isNavbarOpen,
openNavbar,
}) {
const [isBookmarked, setIsBookmarked] = useState(false);
const [selectedItems, setSelectedItems] = useState(null);
......@@ -79,6 +82,10 @@ function CollectionContent({
clear,
} = useListSelect(itemKeyFn);
useOnMount(() => {
openNavbar();
});
useEffect(() => {
const shouldBeBookmarked = bookmarks.some(
bookmark =>
......
......@@ -14,6 +14,7 @@ import VirtualizedList from "metabase/components/VirtualizedList";
import Search from "metabase/entities/search";
import listSelect from "metabase/hoc/ListSelect";
import { openNavbar } from "metabase/redux/app";
import { getUserIsAdmin } from "metabase/selectors/user";
import {
ArchiveBarContent,
......@@ -28,6 +29,10 @@ const mapStateToProps = (state, props) => ({
isAdmin: getUserIsAdmin(state, props),
});
const mapDispatchToProps = {
openNavbar,
};
const ROW_HEIGHT = 68;
@Search.loadList({
......@@ -36,8 +41,12 @@ const ROW_HEIGHT = 68;
wrapped: true,
})
@listSelect({ keyForItem: item => `${item.model}:${item.id}` })
@connect(mapStateToProps, null)
@connect(mapStateToProps, mapDispatchToProps)
export default class ArchiveApp extends Component {
componentDidMount() {
this.props.openNavbar();
}
render() {
const {
isAdmin,
......
......@@ -2,7 +2,7 @@ import React, { Fragment } from "react";
import { t } from "ttag";
import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
import EmptyState from "metabase/components/EmptyState";
import ErrorDetails from "metabase/components/ErrorDetails";
import { useOnMount } from "metabase/hooks/use-on-mount";
import CollectionSection from "../CollectionSection";
import DatabaseSection from "../DatabaseSection";
import GreetingSection from "../GreetingSection";
......@@ -27,6 +27,7 @@ export interface HomepageProps {
showData?: boolean;
showPinMessage?: boolean;
showSyncingModal?: boolean;
openNavbar: () => void;
onHideData?: () => void;
onHideXrays?: () => void;
onHidePinMessage?: () => void;
......@@ -46,6 +47,7 @@ const Homepage = ({
showData,
showPinMessage,
showSyncingModal,
openNavbar,
onHideData,
onHideXrays,
onHidePinMessage,
......@@ -55,6 +57,10 @@ const Homepage = ({
onDatabaseClick,
allError,
}: HomepageProps): JSX.Element => {
useOnMount(() => {
openNavbar();
});
return (
<HomepageRoot>
<GreetingSection user={user} />
......
......@@ -4,6 +4,7 @@ import Databases from "metabase/entities/databases";
import { ROOT_COLLECTION } from "metabase/entities/collections";
import DatabaseCandidates from "metabase/entities/database-candidates";
import Search from "metabase/entities/search";
import { openNavbar } from "metabase/redux/app";
import { getUser } from "metabase/selectors/user";
import { State } from "metabase-types/store";
import Homepage from "../../components/Homepage";
......@@ -69,6 +70,7 @@ const mapStateToProps = (state: State) => ({
});
const mapDispatchToProps = {
openNavbar,
onHideData: hideData,
onHideXrays: hideXrays,
onHidePinMessage: hidePinMessage,
......
......@@ -5,6 +5,7 @@ import { t } from "ttag";
import EntityMenu from "metabase/components/EntityMenu";
import Icon from "metabase/components/Icon";
import Link from "metabase/core/components/Link";
import { closeNavbar } from "metabase/redux/app";
import * as Urls from "metabase/lib/urls";
const MODAL_NEW_DASHBOARD = "MODAL_NEW_DASHBOARD";
......@@ -23,6 +24,7 @@ function NewButton({
hasNativeWrite,
hasDbWithJsonEngine,
setModal,
closeNavbar,
}) {
return (
<EntityMenu
......@@ -49,6 +51,7 @@ function NewButton({
creationType: "custom_question",
}),
event: `NavBar;New Question Click;`,
onClose: closeNavbar,
},
]
: []),
......@@ -62,6 +65,7 @@ function NewButton({
creationType: "native_question",
}),
event: `NavBar;New SQL Query Click;`,
onClose: closeNavbar,
},
]
: []),
......@@ -90,4 +94,8 @@ const mapStateToProps = (state, props) => ({
hasDbWithJsonEngine: getHasDbWithJsonEngine(state, props),
});
export default connect(mapStateToProps)(NewButton);
const mapDispatchToProps = {
closeNavbar,
};
export default connect(mapStateToProps, mapDispatchToProps)(NewButton);
......@@ -6,9 +6,7 @@ import { color } from "metabase/lib/colors";
export const ViewSidebarAside = styled.aside`
overflow-x: hidden;
overflow-y: auto;
opacity: 0;
position: relative;
transition: width 0.3s, opacity 0.3s;
width: 0;
${({ side }) =>
......@@ -26,13 +24,8 @@ export const ViewSidebarAside = styled.aside`
isOpen &&
width &&
css`
opacity: 1;
width: ${width}px;
`}
@media (prefers-reduced-motion) {
transition: none;
}
`;
export const ViewSidebarContent = styled.div`
......
......@@ -8,6 +8,7 @@ import _ from "underscore";
import Bookmark from "metabase/entities/bookmarks";
import Collections from "metabase/entities/collections";
import Timelines from "metabase/entities/timelines";
import { closeNavbar } from "metabase/redux/app";
import { MetabaseApi } from "metabase/services";
import { getMetadata } from "metabase/selectors/metadata";
import { getUser, getUserIsAdmin } from "metabase/selectors/user";
......@@ -68,6 +69,7 @@ import {
getSelectedTimelineEventIds,
getFilteredTimelines,
getTimeseriesXDomain,
getIsAnySidebarOpen,
} from "../selectors";
import * as actions from "../actions";
......@@ -130,6 +132,7 @@ const mapStateToProps = (state, props) => {
// includes isShowingDataReference, isEditing, isRunning, etc
// NOTE: should come before other selectors that override these like getIsPreviewing and getIsNativeEditorOpen
...state.qb.uiControls,
isAnySidebarOpen: getIsAnySidebarOpen(state),
isBookmarked: getIsBookmarked(state, props),
isDirty: getIsDirty(state),
......@@ -168,6 +171,7 @@ const mapStateToProps = (state, props) => {
const mapDispatchToProps = {
...actions,
closeNavbar,
onChangeLocation: push,
createBookmark: id => Bookmark.actions.create({ id, type: "card" }),
deleteBookmark: id => Bookmark.actions.delete({ id, type: "card" }),
......@@ -180,6 +184,9 @@ function QueryBuilder(props) {
params,
fromUrl,
uiControls,
isNativeEditorOpen,
isAnySidebarOpen,
closeNavbar,
initializeQB,
apiCreateQuestion,
apiUpdateQuestion,
......@@ -204,6 +211,8 @@ function QueryBuilder(props) {
const previousUIControls = usePrevious(uiControls);
const previousLocation = usePrevious(location);
const wasShowingAnySidebar = usePrevious(isAnySidebarOpen);
const wasNativeEditorOpen = usePrevious(isNativeEditorOpen);
const hasQuestion = question != null;
const collectionId = question?.collectionId();
......@@ -285,6 +294,21 @@ function QueryBuilder(props) {
clearTimeout(timeout.current);
});
useEffect(() => {
if (
(isAnySidebarOpen && !wasShowingAnySidebar) ||
(isNativeEditorOpen && !wasNativeEditorOpen)
) {
closeNavbar();
}
}, [
isAnySidebarOpen,
wasShowingAnySidebar,
isNativeEditorOpen,
wasNativeEditorOpen,
closeNavbar,
]);
useEffect(() => {
if (allLoaded && hasQuestion) {
showTimelinesForCollection(collectionId);
......
......@@ -44,6 +44,25 @@ export const getIsShowingDataReference = state =>
getUiControls(state).isShowingDataReference;
export const getIsShowingRawTable = state =>
getUiControls(state).isShowingRawTable;
const SIDEBARS = [
"isShowingQuestionDetailsSidebar",
"isShowingChartTypeSidebar",
"isShowingChartSettingsSidebar",
"isShowingTimelineSidebar",
"isShowingSummarySidebar",
"isShowingFilterSidebar",
"isShowingDataReference",
"isShowingTemplateTagsEditor",
"isShowingSnippetSidebar",
];
export const getIsAnySidebarOpen = createSelector([getUiControls], uiControls =>
SIDEBARS.some(sidebar => uiControls[sidebar]),
);
export const getIsEditing = state => getUiControls(state).isEditing;
export const getIsRunning = state => getUiControls(state).isRunning;
......
......@@ -28,7 +28,6 @@ describe("scenarios > binning > correctness > longitude", () => {
.and("contain", selected);
cy.findByText("Done").click();
cy.findByTestId("sidebar-right").should("not.be.visible");
getTitle(`Count by Longitude: ${selected}`);
cy.get(".bar");
......@@ -49,7 +48,6 @@ describe("scenarios > binning > correctness > longitude", () => {
.and("contain", "Unbinned");
cy.findByText("Done").click();
cy.findByTestId("sidebar-right").should("not.be.visible");
getTitle("Count by Longitude");
cy.get(".cellData")
......
......@@ -58,7 +58,6 @@ describe("scenarios > binning > correctness > time series", () => {
}).should("have.text", selected);
cy.findByText("Done").click();
cy.findByTestId("sidebar-right").should("not.be.visible");
getTitle(titleRegex);
......
import {
restore,
openNativeEditor,
closeNavigationSidebar,
filterWidget,
popover,
} from "__support__/e2e/cypress";
......@@ -57,7 +56,6 @@ describe("scenarios > filters > sql filters > basic filter types", () => {
SQLFilter.openTypePickerFromDefaultFilterType();
SQLFilter.chooseType("Number");
closeNavigationSidebar();
});
it("when set through the filter widget", () => {
......
......@@ -49,12 +49,10 @@ describe("URLs", () => {
});
describe("collections", () => {
["/", "/collection/root"].forEach(url => {
it(`should slugify collection name when opening it from "${url}"`, () => {
cy.visit(url);
cy.findByText("First collection").click();
cy.location("pathname").should("eq", "/collection/9-first-collection");
});
it("should slugify collection name", () => {
cy.visit("/collection/root");
cy.findByText("First collection").click();
cy.location("pathname").should("eq", "/collection/9-first-collection");
});
it("should slugify current user's personal collection name correctly", () => {
......
import { restore, popover } from "__support__/e2e/cypress";
import {
restore,
popover,
openNavigationSidebar,
} from "__support__/e2e/cypress";
describe("issue 19742", () => {
beforeEach(() => {
......@@ -14,6 +18,7 @@ describe("issue 19742", () => {
selectFromDropdown("Question");
selectFromDropdown("Sample Database");
openNavigationSidebar();
cy.icon("gear").click();
selectFromDropdown("Admin settings");
......
......@@ -34,6 +34,7 @@ describe("issue 9027", () => {
openNavigationSidebar();
archiveQuestion(QUESTION_NAME);
goToSavedQuestionPickerAndAssertQuestion(QUESTION_NAME, false);
openNavigationSidebar();
unarchiveQuestion(QUESTION_NAME);
goToSavedQuestionPickerAndAssertQuestion(QUESTION_NAME);
});
......
......@@ -6,6 +6,7 @@ import {
openPeopleTable,
visualize,
openNotebookEditor,
openNavigationSidebar,
visitQuestion,
} from "__support__/e2e/cypress";
import { USERS } from "__support__/e2e/cypress_data";
......@@ -553,6 +554,7 @@ describe("smoketest > admin_setup", () => {
// Check column names and visiblity
openNavigationSidebar();
browse().click();
cy.findByTextEnsureVisible("Sample Database").click();
cy.findByTextEnsureVisible("Test Table").click();
......
......@@ -3,7 +3,6 @@ import {
sidebar,
popover,
visualize,
closeNavigationSidebar,
openNotebookEditor,
summarize,
} from "__support__/e2e/cypress";
......@@ -158,7 +157,6 @@ describe("smoketest > user", () => {
it("should summarize via both the sidebar and notebook editor", () => {
// Sidebar summary
closeNavigationSidebar();
summarize();
cy.findByText("Category").click();
cy.findByText("Done").click();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment