Skip to content

Commit

Permalink
Make Trash Usable - Search Filter UI (#42402)
Browse files Browse the repository at this point in the history
* adds filtering for archived items on the search page

* fix typing mistake
  • Loading branch information
sloansparger committed May 10, 2024
1 parent 6004264 commit 9a4cb8e
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 11 deletions.
23 changes: 23 additions & 0 deletions e2e/test/scenarios/onboarding/search/search-filters.cy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ADMIN_USER_ID,
NORMAL_USER_ID,
ORDERS_COUNT_QUESTION_ID,
FIRST_COLLECTION_ID,
} from "e2e/support/cypress_sample_instance_data";
import {
createAction,
Expand Down Expand Up @@ -1023,6 +1024,28 @@ describe("scenarios > search", () => {
});
});

describe("trashed items filter", () => {
it("should only show items in the trash", () => {
cy.visit("/search?q=First");
cy.findAllByTestId("search-result-item").should("have.length", 1);
cy.findByTestId("search-result-item")
.findByText("Collection")
.should("exist");

cy.findByTestId("archived-search-filter")
.findByText("Search items in trash")
.click();
cy.findAllByTestId("search-result-item").should("have.length", 0);

cy.archiveCollection(FIRST_COLLECTION_ID);
cy.reload();
cy.findAllByTestId("search-result-item").should("have.length", 1);
cy.findByTestId("search-result-item")
.findByText("Trash")
.should("exist");
});
});

it("should persist filters when the user changes the text query", () => {
cy.visit("/search?q=orders");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const InfoTextEditedInfo = ({

const { prefix, timestamp, userId } = isUpdated
? {
prefix: t`Updated`,
prefix: result.archived ? t`Deleted` : t`Updated`,
timestamp: result.last_edited_at,
userId: result.last_editor_id,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ import styled from "@emotion/styled";
import { color, lighten } from "metabase/lib/colors";
import type { SearchModel } from "metabase-types/api";

function getColorForIconWrapper({
active,
type,
}: {
active: boolean;
type: SearchModel;
}) {
if (!active) {
function getColorForIconWrapper(
active: boolean,
archived: boolean,
type: SearchModel,
) {
if (!active || archived) {
return color("text-medium");
}
if (type === "collection") {
Expand All @@ -21,6 +19,7 @@ function getColorForIconWrapper({

export const IconWrapper = styled.div<{
active: boolean;
archived: boolean;
type: SearchModel;
}>`
border: ${({ theme }) => `1px solid ${theme.fn.themeColor("border")}`};
Expand All @@ -30,7 +29,8 @@ export const IconWrapper = styled.div<{
justify-content: center;
width: 32px;
height: 32px;
color: ${({ active, type }) => getColorForIconWrapper({ active, type })};
color: ${({ active, archived, type }) =>
getColorForIconWrapper(active, archived, type)};
flex-shrink: 0;
background: ${color("white")};
`;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { SearchModel, RecentItem } from "metabase-types/api";
import { CollectionIcon } from "./CollectionIcon";
import { DefaultIcon } from "./DefaultIcon";
import { IconWrapper } from "./ItemIcon.styled";
import { isWrappedResult } from "./utils";

export interface IconComponentProps {
item: WrappedResult | RecentItem;
Expand Down Expand Up @@ -36,8 +37,15 @@ export const ItemIcon = ({
type,
"data-testid": dataTestId,
}: ItemIconProps) => {
const archived = Boolean(isWrappedResult(item) && item.archived);

return (
<IconWrapper type={type} active={active} data-testid={dataTestId}>
<IconWrapper
type={type}
active={active}
archived={archived}
data-testid={dataTestId}
>
<IconComponent item={item} type={type} />
</IconWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { WrappedResult } from "metabase/search/types";

import type { IconComponentProps } from "./ItemIcon";

export const isWrappedResult = (
item: IconComponentProps["item"],
): item is WrappedResult => item && "getIcon" in item;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CreatedByFilter } from "metabase/search/components/filters/CreatedByFil
import { LastEditedAtFilter } from "metabase/search/components/filters/LastEditedAtFilter";
import { LastEditedByFilter } from "metabase/search/components/filters/LastEditedByFilter";
import { NativeQueryFilter } from "metabase/search/components/filters/NativeQueryFilter";
import { SearchTrashedItemsFilter } from "metabase/search/components/filters/SearchTrashedItemsFilter";
import { TypeFilter } from "metabase/search/components/filters/TypeFilter";
import { SearchFilterKeys } from "metabase/search/constants";
import type {
Expand All @@ -32,6 +33,7 @@ export const SearchSidebar = ({ value, onChange }: SearchSidebarProps) => {
[SearchFilterKeys.LastEditedAt]: LastEditedAtFilter,
[SearchFilterKeys.Verified]: PLUGIN_CONTENT_VERIFICATION.VerifiedFilter,
[SearchFilterKeys.NativeQuery]: NativeQueryFilter,
[SearchFilterKeys.SearchTrashedItems]: SearchTrashedItemsFilter,
};

const onOutputChange = (key: FilterTypeKeys, val?: SearchQueryParamValue) => {
Expand Down Expand Up @@ -89,6 +91,7 @@ export const SearchSidebar = ({ value, onChange }: SearchSidebarProps) => {
</Stack>
{getFilter(SearchFilterKeys.Verified)}
{getFilter(SearchFilterKeys.NativeQuery)}
{getFilter(SearchFilterKeys.SearchTrashedItems)}
</Stack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { t } from "ttag";

import type { SearchFilterToggle } from "metabase/search/types";

export const SearchTrashedItemsFilter: SearchFilterToggle = {
label: () => t`Search items in trash`,
type: "toggle",
fromUrl: value => value === "true",
toUrl: (value: boolean) => (value ? "true" : null),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { t } from "ttag";

import type { SearchFilterToggle } from "metabase/search/types";

export const SearchTrashedItemsFilter: SearchFilterToggle = {
label: () => t`Search items in trash`,
type: "toggle",
fromUrl: value => value === "true",
toUrl: (value: boolean) => (value ? "true" : null),
};
1 change: 1 addition & 0 deletions frontend/src/metabase/search/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const SearchFilterKeys = {
LastEditedBy: "last_edited_by",
LastEditedAt: "last_edited_at",
NativeQuery: "search_native_query",
SearchTrashedItems: "archived",
} as const;

export const enabledSearchTypes: EnabledSearchModel[] = [
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/metabase/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type LastEditedByProps = UserId[];
export type LastEditedAtFilterProps = string | null;
export type VerifiedFilterProps = true | null;
export type NativeQueryFilterProps = true | null;
export type SearchTrashedItemsFilterProps = true | undefined;

export type SearchFilterPropTypes = {
[SearchFilterKeys.Type]: TypeFilterProps;
Expand All @@ -36,6 +37,7 @@ export type SearchFilterPropTypes = {
[SearchFilterKeys.LastEditedBy]: LastEditedByProps;
[SearchFilterKeys.LastEditedAt]: LastEditedAtFilterProps;
[SearchFilterKeys.NativeQuery]: NativeQueryFilterProps;
[SearchFilterKeys.SearchTrashedItems]: SearchTrashedItemsFilterProps;
};

export type FilterTypeKeys = keyof SearchFilterPropTypes;
Expand Down

0 comments on commit 9a4cb8e

Please sign in to comment.