Compare commits

...

1 Commits

15 changed files with 98 additions and 111 deletions

View File

@@ -8,6 +8,11 @@ import { push } from "react-router-redux";
import { t } from "ttag";
import { getCollectionName } from "metabase/collections/utils";
import {
CollectionPath,
SimpleCollectionDisplay,
} from "metabase/common/components/CollectionPath/CollectionPath";
import { CollectionsIcon } from "metabase/common/components/CollectionPath/CollectionPath.styled";
import { useLocale } from "metabase/common/hooks/use-locale/use-locale";
import EntityItem from "metabase/components/EntityItem";
import { SortableColumnHeader } from "metabase/components/ItemsTable/BaseItemsTable";
@@ -38,11 +43,6 @@ import { trackModelClick } from "../analytics";
import type { ModelResult } from "../types";
import { getIcon } from "../utils";
import {
CollectionBreadcrumbsWithTooltip,
SimpleCollectionDisplay,
} from "./CollectionBreadcrumbsWithTooltip";
import { CollectionsIcon } from "./CollectionBreadcrumbsWithTooltip.styled";
import { EllipsifiedWithMarkdownTooltip } from "./EllipsifiedWithMarkdownTooltip";
import {
ModelCell,
@@ -243,7 +243,7 @@ const TBodyRow = ({
{simpleDisplay ? (
<SimpleCollectionDisplay collection={model.collection} />
) : (
<CollectionBreadcrumbsWithTooltip
<CollectionPath
containerName={containerName}
collection={model.collection}
/>

View File

@@ -1,36 +1,10 @@
import { t } from "ttag";
import type { CollectionEssentials, SearchResult } from "metabase-types/api";
import { getCollectionPathString } from "metabase/common/components/CollectionPath/utils";
import type { SearchResult } from "metabase-types/api";
import { SortDirection, type SortingOptions } from "metabase-types/api/sorting";
import type { ModelResult } from "../types";
import { getCollectionName } from "../utils";
import { pathSeparatorChar } from "./constants";
export const getBreadcrumbMaxWidths = (
collections: CollectionEssentials["effective_ancestors"],
totalUnitsOfWidthAvailable: number,
isPathEllipsified: boolean,
) => {
if (!collections || collections.length < 2) {
return [];
}
const lengths = collections.map(
collection => getCollectionName(collection).length,
);
const ratio = lengths[0] / (lengths[0] + lengths[1]);
const firstWidth = Math.max(
Math.round(ratio * totalUnitsOfWidthAvailable),
25,
);
const secondWidth = totalUnitsOfWidthAvailable - firstWidth;
const padding = isPathEllipsified ? "2rem" : "1rem";
return [
`calc(${firstWidth}cqw - ${padding})`,
`calc(${secondWidth}cqw - ${padding})`,
];
};
export const isModel = (item: SearchResult) => item.model === "dataset";
@@ -42,16 +16,6 @@ export const getModelDescription = (item: SearchResult) => {
}
};
export const getCollectionPathString = (collection: CollectionEssentials) => {
const ancestors: CollectionEssentials[] =
collection.effective_ancestors || [];
const collections = ancestors.concat(collection);
const pathString = collections
.map(coll => getCollectionName(coll))
.join(` ${pathSeparatorChar} `);
return pathString;
};
const getValueForSorting = (
model: ModelResult,
sort_column: keyof ModelResult,

View File

@@ -4,37 +4,7 @@ import { SortDirection } from "metabase-types/api/sorting";
import { createMockModelResult } from "../test-utils";
import type { ModelResult } from "../types";
import {
getCollectionPathString,
sortModels,
getMaxRecentModelCount,
} from "./utils";
describe("getCollectionPathString", () => {
it("should return path for collection without ancestors", () => {
const collection = createMockCollection({
id: 0,
name: "Documents",
effective_ancestors: [],
});
const pathString = getCollectionPathString(collection);
expect(pathString).toBe("Documents");
});
it("should return path for collection with multiple ancestors", () => {
const ancestors = [
createMockCollection({ name: "Home" }),
createMockCollection({ name: "User" }),
createMockCollection({ name: "Files" }),
];
const collection = createMockCollection({
name: "Documents",
effective_ancestors: ancestors,
});
const pathString = getCollectionPathString(collection);
expect(pathString).toBe("Home / User / Files / Documents");
});
});
import { sortModels, getMaxRecentModelCount } from "./utils";
describe("sortModels", () => {
let id = 0;

View File

@@ -1,15 +1,9 @@
import type { MutableRefObject } from "react";
import type {
RecentCollectionItem,
RecentItem,
SearchResult,
} from "metabase-types/api";
export type RefProp<RefValue> = {
ref: MutableRefObject<RefValue> | ((value: RefValue) => void);
};
/** Model retrieved through the search endpoint */
export type ModelResult = SearchResult<number, "dataset">;

View File

@@ -1,31 +1,11 @@
import type { Dispatch, SetStateAction } from "react";
import { t } from "ttag";
import _ from "underscore";
import {
canonicalCollectionId,
coerceCollectionId,
isRootCollection,
} from "metabase/collections/utils";
import { entityForObject } from "metabase/lib/schema";
import type { IconName } from "metabase/ui";
import type { CollectionEssentials } from "metabase-types/api";
import type { FilterableModel } from "./types";
export const getCollectionName = (collection: CollectionEssentials) => {
if (isRootCollection(collection)) {
return t`Our analytics`;
}
return collection?.name || t`Untitled collection`;
};
/** The root collection's id might be null or 'root' in different contexts.
* Use 'root' instead of null, for the sake of sorting */
export const getCollectionIdForSorting = (collection: CollectionEssentials) => {
return coerceCollectionId(canonicalCollectionId(collection.id));
};
export type AvailableModelFilters = Record<
string,
{

View File

@@ -16,16 +16,17 @@ import {
CollectionLink,
CollectionsIcon,
InitialEllipsis,
} from "./CollectionBreadcrumbsWithTooltip.styled";
} from "./CollectionPath.styled";
import { Ellipsis } from "./Ellipsis";
import { PathSeparator } from "./PathSeparator";
import { getBreadcrumbMaxWidths, getCollectionPathString } from "./utils";
export const CollectionBreadcrumbsWithTooltip = ({
export const CollectionPath = ({
collection,
containerName,
}: {
collection: CollectionEssentials;
/** Must be a valid css identifier. "a_b" is a valid value, but "a.b" is not */
containerName: string;
}) => {
const collections = (

View File

@@ -2,14 +2,11 @@ import { renderWithProviders, screen } from "__support__/ui";
import type { Collection } from "metabase-types/api";
import { createMockCollection } from "metabase-types/api/mocks";
import { CollectionBreadcrumbsWithTooltip } from "./CollectionBreadcrumbsWithTooltip";
import { CollectionPath } from "./CollectionPath";
const setup = (collection: Collection) => {
return renderWithProviders(
<CollectionBreadcrumbsWithTooltip
collection={collection}
containerName="Container"
/>,
<CollectionPath collection={collection} containerName="Container" />,
);
};
const collectionAlpha = createMockCollection({ id: 99, name: "Alpha" });
@@ -24,7 +21,7 @@ const collectionCharlie = createMockCollection({
effective_ancestors: [collectionAlpha, collectionBeta],
});
describe("CollectionBreadcrumbsWithTooltip", () => {
describe("CollectionPath", () => {
it("should show a single collection", () => {
setup(collectionAlpha);
expect(screen.getByLabelText("Alpha")).toBeInTheDocument();

View File

@@ -6,7 +6,7 @@ import { Text } from "metabase/ui";
import type { RefProp } from "../types";
import { EllipsisAndSeparator } from "./CollectionBreadcrumbsWithTooltip.styled";
import { EllipsisAndSeparator } from "./CollectionPath.styled";
import { PathSeparator } from "./PathSeparator";
type EllipsisProps = {
includeSep?: boolean;

View File

@@ -0,0 +1,47 @@
import { t } from "ttag";
import { isRootCollection } from "metabase/collections/utils";
import type { CollectionEssentials } from "metabase-types/api";
import { pathSeparatorChar } from "./constants";
export const getCollectionName = (collection: CollectionEssentials) => {
if (isRootCollection(collection)) {
return t`Our analytics`;
}
return collection?.name || t`Untitled collection`;
};
export const getBreadcrumbMaxWidths = (
collections: CollectionEssentials["effective_ancestors"],
totalUnitsOfWidthAvailable: number,
isPathEllipsified: boolean,
) => {
if (!collections || collections.length < 2) {
return [];
}
const lengths = collections.map(
collection => getCollectionName(collection).length,
);
const ratio = lengths[0] / (lengths[0] + lengths[1]);
const firstWidth = Math.max(
Math.round(ratio * totalUnitsOfWidthAvailable),
25,
);
const secondWidth = totalUnitsOfWidthAvailable - firstWidth;
const padding = isPathEllipsified ? "2rem" : "1rem";
return [
`calc(${firstWidth}cqw - ${padding})`,
`calc(${secondWidth}cqw - ${padding})`,
];
};
export const getCollectionPathString = (collection: CollectionEssentials) => {
const ancestors: CollectionEssentials[] =
collection.effective_ancestors || [];
const collections = ancestors.concat(collection);
const pathString = collections
.map(coll => getCollectionName(coll))
.join(` ${pathSeparatorChar} `);
return pathString;
};

View File

@@ -0,0 +1,29 @@
import { createMockCollection } from "metabase-types/api/mocks";
import { getCollectionPathString } from "./utils";
describe("getCollectionPathString", () => {
it("should return path for collection without ancestors", () => {
const collection = createMockCollection({
id: 0,
name: "Documents",
effective_ancestors: [],
});
const pathString = getCollectionPathString(collection);
expect(pathString).toBe("Documents");
});
it("should return path for collection with multiple ancestors", () => {
const ancestors = [
createMockCollection({ name: "Home" }),
createMockCollection({ name: "User" }),
createMockCollection({ name: "Files" }),
];
const collection = createMockCollection({
name: "Documents",
effective_ancestors: ancestors,
});
const pathString = getCollectionPathString(collection);
expect(pathString).toBe("Home / User / Files / Documents");
});
});

View File

@@ -0,0 +1,5 @@
import type { MutableRefObject } from "react";
export type RefProp<RefValue> = {
ref: MutableRefObject<RefValue> | ((value: RefValue) => void);
};

View File

@@ -1,6 +1,6 @@
import styled from "@emotion/styled";
import type { RefProp } from "metabase/browse/types";
import type { RefProp } from "metabase/common/components/types";
import { doNotForwardProps } from "metabase/common/utils/doNotForwardProps";
import { Box, type BoxProps } from "metabase/ui";