Skip to content
Snippets Groups Projects
Unverified Commit e56f1b64 authored by Nemanja Glumac's avatar Nemanja Glumac Committed by GitHub
Browse files

MS3: Open notebook data source in new tab (tooltip) (#46552)

* Add tooltip to the data step cell

* Conditionally display tooltip

* Add unit tests for the data step

* Add unit tests for the join step

* Move the abstraction to the NotebookDataPicker

* Cover the tooltip behavior with E2E test

* Update test
parent a4bec904
No related branches found
No related tags found
No related merge requests found
......@@ -20,6 +20,7 @@ import {
visualize,
type NativeQuestionDetails,
} from "e2e/support/helpers";
import { METAKEY } from "metabase/lib/browser";
const { ORDERS, PRODUCTS_ID, REVIEWS, REVIEWS_ID, PEOPLE_ID, PRODUCTS } =
SAMPLE_DATABASE;
......@@ -74,6 +75,17 @@ describe("scenarios > notebook > link to data source", () => {
"Deselecting columns should have no effect on the linked data source in new tab/window",
);
openNotebook();
cy.log("Make sure tooltip is being shown on hover");
getNotebookStep("data")
.findByText("Reviews")
.should("be.visible")
.realHover();
cy.findByRole("tooltip").should(
"have.text",
`${METAKEY}+click to open in new tab`,
);
getNotebookStep("data").findByText("Reviews").click(clickConfig);
cy.wait("@dataset"); // already intercepted in `visualize()`
......@@ -86,6 +98,11 @@ describe("scenarios > notebook > link to data source", () => {
);
cy.findByTestId("qb-save-button").should("be.enabled");
cy.go("back");
cy.log("Tooltip should not linger open when we go back");
getNotebookStep("data").findByText("Reviews").should("be.visible");
cy.findByRole("tooltip").should("not.exist");
});
context("questions", () => {
......
import { useMemo, useState, type MouseEvent } from "react";
import { useLatest } from "react-use";
import { t } from "ttag";
import {
DataPickerModal,
getDataPickerValue,
} from "metabase/common/components/DataPicker";
import { METAKEY } from "metabase/lib/browser";
import { useDispatch, useStore } from "metabase/lib/redux";
import { checkNotNull } from "metabase/lib/types";
import { loadMetadataForTable } from "metabase/questions/actions";
import { getMetadata } from "metabase/selectors/metadata";
import type { IconName } from "metabase/ui";
import { Group, Icon, UnstyledButton } from "metabase/ui";
import { Group, Icon, UnstyledButton, Tooltip } from "metabase/ui";
import * as Lib from "metabase-lib";
import type { DatabaseId, TableId } from "metabase-types/api";
......@@ -95,20 +97,30 @@ export function NotebookDataPicker({
return (
<>
<UnstyledButton
c="inherit"
fz="inherit"
fw="inherit"
p={NotebookCell.CONTAINER_PADDING}
disabled={isDisabled}
onClick={handleClick}
onAuxClick={handleAuxClick}
<Tooltip
label={t`${METAKEY}+click to open in new tab`}
hidden={!table}
events={{
hover: true,
focus: false,
touch: false,
}}
>
<Group spacing="xs">
{tableInfo && <Icon name={getTableIcon(tableInfo)} />}
{tableInfo?.displayName ?? placeholder}
</Group>
</UnstyledButton>
<UnstyledButton
c="inherit"
fz="inherit"
fw="inherit"
p={NotebookCell.CONTAINER_PADDING}
disabled={isDisabled}
onClick={handleClick}
onAuxClick={handleAuxClick}
>
<Group spacing="xs">
{tableInfo && <Icon name={getTableIcon(tableInfo)} />}
{tableInfo?.displayName ?? placeholder}
</Group>
</UnstyledButton>
</Tooltip>
{isOpen && (
<DataPickerModal
title={title}
......
......@@ -8,6 +8,7 @@ import {
setupSearchEndpoints,
} from "__support__/server-mocks";
import { getIcon, renderWithProviders, screen, within } from "__support__/ui";
import { METAKEY } from "metabase/lib/browser";
import type { IconName } from "metabase/ui";
import * as Lib from "metabase-lib";
import {
......@@ -295,6 +296,28 @@ describe("DataStep", () => {
});
describe("link to data source", () => {
it("should show the tooltip on hover", async () => {
setup();
await userEvent.hover(screen.getByText("Orders"));
expect(screen.getByRole("tooltip")).toHaveTextContent(
`${METAKEY}+click to open in new tab`,
);
});
it("should not show the tooltip when there is no table selected", async () => {
setupEmptyQuery();
const modal = await screen.findByTestId("entity-picker-modal");
const closeButton = await screen.findByRole("button", { name: /close/i });
await userEvent.click(closeButton);
expect(modal).not.toBeInTheDocument();
await userEvent.hover(screen.getByText("Pick your starting data"));
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
});
it("meta click should open the data source in a new window", () => {
const { mockWindowOpen } = setup();
......
......@@ -17,6 +17,7 @@ import {
waitForLoaderToBeRemoved,
within,
} from "__support__/ui";
import { METAKEY } from "metabase/lib/browser";
import * as Lib from "metabase-lib";
import { columnFinder, createQuery } from "metabase-lib/test-helpers";
import type { CollectionItem, RecentItem } from "metabase-types/api";
......@@ -1170,4 +1171,31 @@ describe("Notebook Editor > Join Step", () => {
).not.toBeInTheDocument();
});
});
describe("link to data source", () => {
it("should show the tooltip on hover only for the actual data source (right table)", async () => {
setup({ step: createMockNotebookStep({ query: getJoinedQuery() }) });
await expect(
userEvent.hover(
within(screen.getByLabelText("Left table")).getByText("Orders"),
),
).rejects.toThrow(/pointer-events: none/);
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
await userEvent.hover(
within(screen.getByLabelText("Right table")).getByText("Products"),
);
expect(screen.getByRole("tooltip")).toHaveTextContent(
`${METAKEY}+click to open in new tab`,
);
});
it("should not show the tooltip when the right table data source is missing", async () => {
setup();
await userEvent.hover(screen.getByLabelText("Right table"));
expect(screen.queryByRole("tooltip")).not.toBeInTheDocument();
});
});
});
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