Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Trash Usable - Search Filter UI #42402

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading