Skip to content

Commit

Permalink
Use a Popover and user settings for filters (#41959)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafpaf committed May 3, 2024
1 parent 62e09eb commit 902ef11
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -1,46 +1,81 @@
import { useCallback } from "react";
import { t } from "ttag";
import _ from "underscore";

import type { ModelFilterControlsProps } from "metabase/browse/utils";
import { Switch, Text } from "metabase/ui";
import type {
ActualModelFilters,
ModelFilterControlsProps,
} from "metabase/browse/utils";
import { useUserSetting } from "metabase/common/hooks";
import { Button, Icon, Popover, Switch, Text } from "metabase/ui";

export const ModelFilterControls = ({
actualModelFilters,
handleModelFilterChange,
setActualModelFilters,
}: ModelFilterControlsProps) => {
const [__, setVerifiedFilterStatus] = useUserSetting(
"browse-filter-only-verified-models",
{ shouldRefresh: false },
);
const setVerifiedFilterStatusDebounced = _.debounce(
setVerifiedFilterStatus,
200,
);

const handleModelFilterChange = useCallback(
(modelFilterName: string, active: boolean) => {
// For now, only one filter is supported
setVerifiedFilterStatusDebounced(active);
setActualModelFilters((prev: ActualModelFilters) => {
return { ...prev, [modelFilterName]: active };
});
},
[setActualModelFilters, setVerifiedFilterStatusDebounced],
);

const checked = actualModelFilters.onlyShowVerifiedModels;
return (
<Switch
label={
<Text
align="end"
weight="bold"
lh="1rem"
px=".75rem"
>{t`Only show verified models`}</Text>
}
role="switch"
checked={checked}
aria-checked={checked}
onChange={e => {
handleModelFilterChange("onlyShowVerifiedModels", e.target.checked);
}}
size="sm"
labelPosition="left"
styles={{
root: {
marginInlineStart: "auto",
display: "flex",
alignItems: "center",
},
body: {
alignItems: "center",
// Align with tab labels:
position: "relative",
top: "-.5px",
},
labelWrapper: { justifyContent: "center", padding: 0 },
track: { marginTop: "-1.5px" },
}}
/>
<Popover position="bottom-end">
<Popover.Target>
<Button p="sm" variant="subtle" color="text-dark">
<Icon name="filter" />
</Button>
</Popover.Target>
<Popover.Dropdown p="lg">
<Switch
label={
<Text
align="end"
weight="bold"
lh="1rem"
px=".75rem"
>{t`Only show verified models`}</Text>
}
role="switch"
checked={checked}
aria-checked={checked}
onChange={e => {
handleModelFilterChange("onlyShowVerifiedModels", e.target.checked);
}}
size="sm"
labelPosition="left"
styles={{
root: {
marginInlineStart: "auto",
display: "flex",
alignItems: "center",
},
body: {
alignItems: "center",
// Align with tab labels:
position: "relative",
top: "-.5px",
},
labelWrapper: { justifyContent: "center", padding: 0 },
track: { marginTop: "-1.5px" },
}}
/>
</Popover.Dropdown>
</Popover>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
availableModelFilters,
sortCollectionsByVerification,
sortModelsByVerification,
useModelFilterSettings,
} from "./utils";

if (hasPremiumFeature("content_verification")) {
Expand All @@ -16,5 +17,6 @@ if (hasPremiumFeature("content_verification")) {
availableModelFilters,
sortModelsByVerification,
sortCollectionsByVerification,
useModelFilterSettings,
});
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { AvailableModelFilters } from "metabase/browse/utils";
import { useMemo } from "react";

import type {
ActualModelFilters,
AvailableModelFilters,
} from "metabase/browse/utils";
import { useUserSetting } from "metabase/common/hooks";
import type { CollectionEssentials, SearchResult } from "metabase-types/api";

export const sortCollectionsByVerification = (
Expand Down Expand Up @@ -34,3 +40,16 @@ export const availableModelFilters: AvailableModelFilters = {
activeByDefault: true,
},
};

export const useModelFilterSettings = (): ActualModelFilters => {
const [initialVerifiedFilterStatus, __] = useUserSetting(
"browse-filter-only-verified-models",
{ shouldRefresh: false },
);
return useMemo(
() => ({
onlyShowVerifiedModels: initialVerifiedFilterStatus ?? false,
}),
[initialVerifiedFilterStatus],
);
};
45 changes: 7 additions & 38 deletions frontend/src/metabase/browse/components/BrowseModels.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { t } from "ttag";
import _ from "underscore";

Expand All @@ -23,49 +23,18 @@ import {
import { ModelExplanationBanner } from "./ModelExplanationBanner";
import { ModelsTable } from "./ModelsTable";

const { availableModelFilters } = PLUGIN_CONTENT_VERIFICATION;
const { availableModelFilters, useModelFilterSettings } =
PLUGIN_CONTENT_VERIFICATION;

export const BrowseModels = () => {
const getInitialModelFilters = useCallback(() => {
return _.reduce(
availableModelFilters,
(acc, filter, filterName) => {
const storedFilterStatus = localStorage.getItem(
`browseFilters.${filterName}`,
);
const shouldFilterBeActive =
storedFilterStatus === null
? filter.activeByDefault
: storedFilterStatus === "on";
return {
...acc,
[filterName]: shouldFilterBeActive,
};
},
{},
);
}, []);
const initialModelFilters = useModelFilterSettings();

const [actualModelFilters, setActualModelFilters] =
useState<ActualModelFilters>({});
useState<ActualModelFilters>(initialModelFilters);

useEffect(() => {
const initialModelFilters = getInitialModelFilters();
setActualModelFilters(initialModelFilters);
}, [getInitialModelFilters, setActualModelFilters]);

const handleModelFilterChange = useCallback(
(modelFilterName: string, active: boolean) => {
localStorage.setItem(
`browseFilters.${modelFilterName}`,
active ? "on" : "off",
);
setActualModelFilters((prev: ActualModelFilters) => {
return { ...prev, [modelFilterName]: active };
});
},
[setActualModelFilters],
);
}, [initialModelFilters, setActualModelFilters]);

return (
<BrowseContainer>
Expand All @@ -80,7 +49,7 @@ export const BrowseModels = () => {
</Title>
<PLUGIN_CONTENT_VERIFICATION.ModelFilterControls
actualModelFilters={actualModelFilters}
handleModelFilterChange={handleModelFilterChange}
setActualModelFilters={setActualModelFilters}
/>
</Flex>
</BrowseSection>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/metabase/browse/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Dispatch, SetStateAction } from "react";
import { t } from "ttag";
import _ from "underscore";

Expand Down Expand Up @@ -95,7 +96,7 @@ export type AvailableModelFilters = Record<

export type ModelFilterControlsProps = {
actualModelFilters: ActualModelFilters;
handleModelFilterChange: (filterName: string, active: boolean) => void;
setActualModelFilters: Dispatch<SetStateAction<ActualModelFilters>>;
};

export const sortModels = (
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/metabase/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "metabase/admin/permissions/types";
import type { ADMIN_SETTINGS_SECTIONS } from "metabase/admin/settings/selectors";
import type {
ActualModelFilters,
AvailableModelFilters,
ModelFilterControlsProps,
} from "metabase/browse/utils";
Expand Down Expand Up @@ -426,6 +427,7 @@ export const PLUGIN_CONTENT_VERIFICATION = {
_a: CollectionEssentials,
_b: CollectionEssentials,
) => 0,
useModelFilterSettings: () => ({} as ActualModelFilters),
};

export const PLUGIN_DASHBOARD_HEADER = {
Expand Down
8 changes: 8 additions & 0 deletions src/metabase/models/user.clj
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,14 @@
:type :boolean
:default true)

(defsetting browse-filter-only-verified-models
(deferred-tru "User preference for whether the 'Browse models' page should be filtered to show only verified models.")
:user-local :only
:export? false
:visibility :authenticated
:type :boolean
:default true)

;;; ## ------------------------------------------ AUDIT LOG ------------------------------------------

(defmethod audit-log/model-details :model/User
Expand Down

0 comments on commit 902ef11

Please sign in to comment.