Skip to content
Snippets Groups Projects
Unverified Commit cd53c8af authored by Ryan Laurie's avatar Ryan Laurie Committed by GitHub
Browse files

entityPicker in technicolor (#43161)

* entityPicker in technicolor

* more precise import

* add unit test
parent bc3ce713
Branches
Tags
No related merge requests found
......@@ -7,7 +7,7 @@ import { LoadingAndErrorWrapper } from "metabase/public/containers/PublicAction/
import { Box, Center, Icon, NavLink } from "metabase/ui";
import type { TypeWithModel } from "../../types";
import { getIcon, isSelectedItem } from "../../utils";
import { getEntityPickerIcon, isSelectedItem } from "../../utils";
import { DelayedLoadingSpinner } from "../LoadingSpinner";
import { PickerColumn } from "./ItemList.styled";
......@@ -73,26 +73,31 @@ export const ItemList = <
return (
<VirtualizedList Wrapper={PickerColumn} scrollTo={activeItemIndex}>
{filteredItems.map((item: Item) => (
<div key={`${item.model}-${item.id}`}>
<NavLink
disabled={shouldDisableItem?.(item)}
rightSection={
isFolder(item) ? <Icon name="chevronright" size={10} /> : null
}
label={item.name}
active={isSelectedItem(item, selectedItem)}
icon={<Icon {...getIcon(item)} />}
onClick={(e: React.MouseEvent) => {
e.preventDefault(); // prevent form submission
e.stopPropagation(); // prevent parent onClick
onClick(item);
}}
variant={isCurrentLevel ? "default" : "mb-light"}
mb="xs"
/>
</div>
))}
{filteredItems.map((item: Item) => {
const isSelected = isSelectedItem(item, selectedItem);
const icon = getEntityPickerIcon(item, isSelected && isCurrentLevel);
return (
<div key={`${item.model}-${item.id}`}>
<NavLink
disabled={shouldDisableItem?.(item)}
rightSection={
isFolder(item) ? <Icon name="chevronright" size={10} /> : null
}
label={item.name}
active={isSelected}
icon={<Icon {...icon} />}
onClick={(e: React.MouseEvent) => {
e.preventDefault(); // prevent form submission
e.stopPropagation(); // prevent parent onClick
onClick(item);
}}
variant={isCurrentLevel ? "default" : "mb-light"}
mb="xs"
/>
</div>
);
})}
</VirtualizedList>
);
};
import { entityForObject } from "metabase/lib/schema";
import { color } from "metabase/lib/colors";
import type { ObjectWithModel } from "metabase/lib/icon";
import { getIcon } from "metabase/lib/icon";
import type { TypeWithModel } from "./types";
export const getIcon = <Id, Model extends string>(
export const getEntityPickerIcon = <Id, Model extends string>(
item: TypeWithModel<Id, Model>,
isSelected?: boolean,
) => {
const entity = entityForObject(item);
return entity?.objectSelectors?.getIcon?.(item) || { name: "table" };
const icon = getIcon(item as ObjectWithModel);
if (["person", "group"].includes(icon.name)) {
// should inherit color
return icon;
}
if (isSelected && !icon.color) {
icon.color = color("white");
}
if (icon.name === "folder" && isSelected) {
icon.name = "folder_filled";
}
return { ...icon, color: color(icon.color ?? "brand") };
};
export const isSelectedItem = <Id, Model extends string>(
......
import { PERSONAL_COLLECTIONS } from "metabase/entities/collections/constants";
import { PLUGIN_COLLECTIONS } from "metabase/plugins";
import type { IconName } from "metabase/ui";
import { getIconForVisualizationType } from "metabase/visualizations";
......@@ -7,20 +8,25 @@ import type {
SearchModel,
} from "metabase-types/api";
type IconModel = SearchModel | "schema";
export type ObjectWithModel = {
model: SearchModel;
model: IconModel;
id?: unknown;
authority_level?: "official" | string | null;
collection_authority_level?: "official" | string | null;
moderated_status?: "verified" | string | null;
display?: CardDisplayType | null;
type?: Collection["type"];
is_personal?: boolean;
};
const modelIconMap: Record<SearchModel, IconName> = {
const modelIconMap: Record<IconModel, IconName> = {
collection: "folder",
database: "database",
table: "table",
dataset: "model",
schema: "folder",
action: "bolt",
"indexed-entity": "index",
dashboard: "dashboard",
......@@ -40,6 +46,14 @@ export const getIconBase = (item: ObjectWithModel): IconData => {
return { name: getIconForVisualizationType(item.display) };
}
if (item.model === "collection" && item.id === PERSONAL_COLLECTIONS.id) {
return { name: "group" };
}
if (item.model === "collection" && item.is_personal) {
return { name: "person" };
}
return { name: modelIconMap?.[item.model] ?? "unknown" };
};
......
......@@ -14,6 +14,9 @@ describe("getIcon", () => {
it("should return the correct icon for a database", () => {
expect(getIcon({ model: "database" })).toEqual({ name: "database" });
});
it("should return the correct icon for a schema", () => {
expect(getIcon({ model: "schema" })).toEqual({ name: "folder" });
});
it("should return the correct icon for a table", () => {
expect(getIcon({ model: "table" })).toEqual({ name: "table" });
});
......
<svg viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M2.18162 3.142L2.18163 3.142C2.45469 2.88916 2.82127 2.75 3.2 2.75H6.09666L7.95362 4.43815L8.09666 4.56818H8.28996H12.8C13.1787 4.56818 13.5453 4.70733 13.8184 4.96019C14.0923 5.2138 14.25 5.56198 14.25 5.92929V11.8889C14.25 12.2562 14.0923 12.6044 13.8184 12.858C13.5453 13.1109 13.1787 13.25 12.8 13.25H3.2C2.82125 13.25 2.45468 13.1109 2.18163 12.858L1.84278 13.224L2.18163 12.858C1.9077 12.6044 1.75 12.2562 1.75 11.8889V4.11111C1.75 3.74381 1.90769 3.39563 2.18162 3.142Z" />
</svg>
......@@ -143,6 +143,8 @@ import filter_component from "./filter.svg?component";
import filter_source from "./filter.svg?source";
import folder_component from "./folder.svg?component";
import folder_source from "./folder.svg?source";
import folder_filled_component from "./folder_filled.svg?component";
import folder_filled_source from "./folder_filled.svg?source";
import formula_component from "./formula.svg?component";
import formula_source from "./formula.svg?source";
import function_component from "./function.svg?component";
......@@ -679,6 +681,10 @@ export const Icons = {
component: folder_component,
source: folder_source,
},
folder_filled: {
component: folder_filled_component,
source: folder_filled_source,
},
gauge: {
component: gauge_component,
source: gauge_source,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment