Skip to content
Snippets Groups Projects
Unverified Commit aec41f45 authored by Raphael Krut-Landau's avatar Raphael Krut-Landau Committed by GitHub
Browse files

squash (#42111)

parent 4036d86a
No related branches found
No related tags found
No related merge requests found
......@@ -9,7 +9,8 @@ import { PLUGIN_CONTENT_VERIFICATION } from "metabase/plugins";
import { Box, Flex, Group, Icon, Stack, Title } from "metabase/ui";
import type { ModelResult, SearchRequest } from "metabase-types/api";
import { filterModels, type ActualModelFilters } from "../utils";
import type { ActualModelFilters } from "../utils";
import { filterModels } from "../utils";
import {
BrowseContainer,
......@@ -72,7 +73,6 @@ export const BrowseModelsBody = ({
model_ancestors: true,
filter_items_in_personal_collection: "exclude",
};
const { data, error, isLoading } = useSearchQuery(query);
const models = useMemo(() => {
......
......@@ -13,7 +13,7 @@ import { createMockSetupState } from "metabase-types/store/mocks";
import { BrowseModels } from "./BrowseModels";
const renderBrowseModels = (modelCount: number) => {
const setup = (modelCount: number) => {
const models = mockModels.slice(0, modelCount);
setupSearchEndpoints(models);
setupSettingsEndpoints([]);
......@@ -264,20 +264,23 @@ const mockModels: SearchResult[] = [
describe("BrowseModels", () => {
it("displays a 'no models' message in the Models tab when no models exist", async () => {
renderBrowseModels(0);
setup(0);
expect(await screen.findByText("No models here yet")).toBeInTheDocument();
});
it("displays the Our Analytics collection if it has a model", async () => {
renderBrowseModels(25);
await screen.findAllByText("Our analytics");
setup(25);
expect(await screen.findByRole("table")).toBeInTheDocument();
expect(
await screen.findAllByTestId("path-for-collection: Our analytics"),
).toHaveLength(2);
expect(await screen.findByText("Model 20")).toBeInTheDocument();
expect(await screen.findByText("Model 21")).toBeInTheDocument();
expect(await screen.findByText("Model 22")).toBeInTheDocument();
});
it("displays collection breadcrumbs", async () => {
renderBrowseModels(25);
setup(25);
expect(await screen.findByText("Model 1")).toBeInTheDocument();
expect(
await screen.findAllByTestId("breadcrumbs-for-collection: Alpha"),
......
......@@ -4,7 +4,7 @@ import type { AnchorHTMLAttributes } from "react";
import { ResponsiveChild } from "metabase/components/ResponsiveContainer/ResponsiveContainer";
import { color } from "metabase/lib/colors";
import type { AnchorProps } from "metabase/ui";
import { Anchor } from "metabase/ui";
import { Anchor, FixedSizeIcon, Group } from "metabase/ui";
import type { RefProp } from "./types";
......@@ -54,3 +54,11 @@ export const CollectionBreadcrumbsWrapper = styled(ResponsiveChild)`
`;
}}
`;
export const BreadcrumbGroup = styled(Group)`
flex-flow: row nowrap;
`;
export const CollectionsIcon = styled(FixedSizeIcon)`
margin-inline-end: 0.5rem;
`;
......@@ -7,14 +7,16 @@ import { useAreAnyTruncated } from "metabase/hooks/use-is-truncated";
import resizeObserver from "metabase/lib/resize-observer";
import * as Urls from "metabase/lib/urls";
import type { FlexProps } from "metabase/ui";
import { FixedSizeIcon, Flex, Group, Text, Tooltip } from "metabase/ui";
import { Flex, Text, Tooltip } from "metabase/ui";
import type { CollectionEssentials } from "metabase-types/api";
import { getCollectionName } from "../utils";
import {
Breadcrumb,
BreadcrumbGroup,
CollectionBreadcrumbsWrapper,
CollectionsIcon,
} from "./CollectionBreadcrumbsWithTooltip.styled";
import { pathSeparatorChar } from "./constants";
import type { RefProp } from "./types";
......@@ -83,11 +85,20 @@ export const CollectionBreadcrumbsWithTooltip = ({
w="auto"
>
<Flex align="center" w="100%" lh="1" style={{ flexFlow: "row nowrap" }}>
<FixedSizeIcon name="folder" style={{ marginInlineEnd: ".5rem" }} />
<CollectionsIcon
name="folder"
// Stopping propagation so that the parent <tr>'s onclick won't fire
onClick={(e: React.MouseEvent) => e.stopPropagation()}
/>
{shownCollections.map((collection, index) => {
const key = `collection${collection.id}`;
return (
<Group spacing={0} style={{ flexFlow: "row nowrap" }} key={key}>
<BreadcrumbGroup
spacing={0}
key={key}
// Stopping propagation so that the parent <tr>'s onclick won't fire
onClick={(e: React.MouseEvent) => e.stopPropagation()}
>
{index > 0 && <PathSeparator />}
<CollectionBreadcrumbsWrapper
containerName={containerName}
......@@ -115,7 +126,7 @@ export const CollectionBreadcrumbsWithTooltip = ({
{getCollectionName(collection)}
</Breadcrumb>
</CollectionBreadcrumbsWrapper>
</Group>
</BreadcrumbGroup>
);
})}
</Flex>
......
import styled from "@emotion/styled";
import { color } from "metabase/lib/colors";
export const ModelTableRow = styled.tr`
cursor: pointer;
:outline {
outline: 2px solid ${color("brand")};
}
`;
import { useState } from "react";
import { push } from "react-router-redux";
import { t } from "ttag";
import EntityItem from "metabase/components/EntityItem";
......@@ -7,7 +8,6 @@ import {
type SortingOptions,
} from "metabase/components/ItemsTable/BaseItemsTable";
import {
ColumnHeader,
ItemCell,
ItemLink,
ItemNameCell,
......@@ -18,7 +18,7 @@ import {
import { Columns, SortDirection } from "metabase/components/ItemsTable/Columns";
import type { ResponsiveProps } from "metabase/components/ItemsTable/utils";
import { color } from "metabase/lib/colors";
import { useSelector } from "metabase/lib/redux";
import { useDispatch, useSelector } from "metabase/lib/redux";
import * as Urls from "metabase/lib/urls";
import { getLocale } from "metabase/setup/selectors";
import { Icon, type IconProps } from "metabase/ui";
......@@ -29,6 +29,7 @@ import { getCollectionName, getIcon } from "../utils";
import { CollectionBreadcrumbsWithTooltip } from "./CollectionBreadcrumbsWithTooltip";
import { EllipsifiedWithMarkdown } from "./EllipsifiedWithMarkdown";
import { ModelTableRow } from "./ModelsTable.styled";
import { getModelDescription, sortModels } from "./utils";
export interface ModelsTableProps {
......@@ -76,7 +77,9 @@ export const ModelsTable = ({ models }: ModelsTableProps) => {
sortingOptions={sortingOptions}
onSortingOptionsChange={setSortingOptions}
/>
<ColumnHeader {...descriptionProps}>{t`Description`}</ColumnHeader>
<SortableColumnHeader name="description" {...descriptionProps}>
{t`Description`}
</SortableColumnHeader>
<SortableColumnHeader
name="collection"
sortingOptions={sortingOptions}
......@@ -100,9 +103,22 @@ export const ModelsTable = ({ models }: ModelsTableProps) => {
const TBodyRow = ({ model }: { model: ModelResult }) => {
const icon = getIcon(model);
const containerName = `collections-path-for-${model.id}`;
const dispatch = useDispatch();
const { id, name } = model;
return (
<tr>
<ModelTableRow
onClick={(e: React.MouseEvent) => {
const url = Urls.model({ id, name });
if ((e.ctrlKey || e.metaKey) && e.button === 0) {
window.open(url, "_blank");
} else {
dispatch(push(url));
}
}}
tabIndex={0}
key={model.id}
>
{/* Name */}
<NameCell
model={model}
......@@ -138,7 +154,7 @@ const TBodyRow = ({ model }: { model: ModelResult }) => {
{/* Adds a border-radius to the table */}
<Columns.RightEdge.Cell />
</tr>
</ModelTableRow>
);
};
......
......@@ -43,8 +43,7 @@ export const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon(
return tooltip ? <Tooltip label={tooltip}>{icon}</Tooltip> : icon;
});
/** An icon that does not shrink when the viewport gets narrower **/
export const FixedSizeIcon = styled(Icon)<{ size?: number }>`
min-width: ${({ size }) => size ?? 16}px;
min-height: ${({ size }) => size ?? 16}px;
/** An icon that does not shrink when its container is too narrow **/
export const FixedSizeIcon = styled(Icon)`
flex-shrink: 0;
`;
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