Revert "Search term filter tag on scene list (#5991)" (#6003)

This reverts commit 21ee88b149.
This commit is contained in:
WithoutPants 2025-07-08 13:12:46 +10:00 committed by GitHub
parent 21ee88b149
commit 14be3c24ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 37 additions and 103 deletions

View file

@ -9,37 +9,31 @@ import { Badge, BadgeProps, Button, Overlay, Popover } from "react-bootstrap";
import { Criterion } from "src/models/list-filter/criteria/criterion"; import { Criterion } from "src/models/list-filter/criteria/criterion";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import { Icon } from "../Shared/Icon"; import { Icon } from "../Shared/Icon";
import { faMagnifyingGlass, faTimes } from "@fortawesome/free-solid-svg-icons"; import { faTimes } from "@fortawesome/free-solid-svg-icons";
import { BsPrefixProps, ReplaceProps } from "react-bootstrap/esm/helpers"; import { BsPrefixProps, ReplaceProps } from "react-bootstrap/esm/helpers";
import { CustomFieldsCriterion } from "src/models/list-filter/criteria/custom-fields"; import { CustomFieldsCriterion } from "src/models/list-filter/criteria/custom-fields";
import { useDebounce } from "src/hooks/debounce"; import { useDebounce } from "src/hooks/debounce";
import cx from "classnames";
type TagItemProps = PropsWithChildren< type TagItemProps = PropsWithChildren<
ReplaceProps<"span", BsPrefixProps<"span"> & BadgeProps> ReplaceProps<"span", BsPrefixProps<"span"> & BadgeProps>
>; >;
export const TagItem: React.FC<TagItemProps> = (props) => { export const TagItem: React.FC<TagItemProps> = (props) => {
const { className, children, ...others } = props; const { children } = props;
return ( return (
<Badge <Badge className="tag-item" variant="secondary" {...props}>
className={cx("tag-item", className)}
variant="secondary"
{...others}
>
{children} {children}
</Badge> </Badge>
); );
}; };
export const FilterTag: React.FC<{ export const FilterTag: React.FC<{
className?: string;
label: React.ReactNode; label: React.ReactNode;
onClick: React.MouseEventHandler<HTMLSpanElement>; onClick: React.MouseEventHandler<HTMLSpanElement>;
onRemove: React.MouseEventHandler<HTMLElement>; onRemove: React.MouseEventHandler<HTMLElement>;
}> = ({ className, label, onClick, onRemove }) => { }> = ({ label, onClick, onRemove }) => {
return ( return (
<TagItem className={className} onClick={onClick}> <TagItem onClick={onClick}>
{label} {label}
<Button <Button
variant="secondary" variant="secondary"
@ -102,24 +96,18 @@ const MoreFilterTags: React.FC<{
}; };
interface IFilterTagsProps { interface IFilterTagsProps {
searchTerm?: string;
criteria: Criterion[]; criteria: Criterion[];
onEditSearchTerm?: () => void;
onEditCriterion: (c: Criterion) => void; onEditCriterion: (c: Criterion) => void;
onRemoveCriterion: (c: Criterion, valueIndex?: number) => void; onRemoveCriterion: (c: Criterion, valueIndex?: number) => void;
onRemoveAll: () => void; onRemoveAll: () => void;
onRemoveSearchTerm?: () => void;
truncateOnOverflow?: boolean; truncateOnOverflow?: boolean;
} }
export const FilterTags: React.FC<IFilterTagsProps> = ({ export const FilterTags: React.FC<IFilterTagsProps> = ({
searchTerm,
criteria, criteria,
onEditCriterion, onEditCriterion,
onRemoveCriterion, onRemoveCriterion,
onRemoveAll, onRemoveAll,
onEditSearchTerm,
onRemoveSearchTerm,
truncateOnOverflow = false, truncateOnOverflow = false,
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
@ -277,7 +265,7 @@ export const FilterTags: React.FC<IFilterTagsProps> = ({
); );
} }
if (criteria.length === 0 && !searchTerm) { if (criteria.length === 0) {
return null; return null;
} }
@ -285,31 +273,31 @@ export const FilterTags: React.FC<IFilterTagsProps> = ({
const filterTags = criteria.map((c) => getFilterTags(c)).flat(); const filterTags = criteria.map((c) => getFilterTags(c)).flat();
if (searchTerm && searchTerm.length > 0) { if (cutoff && filterTags.length > cutoff) {
filterTags.unshift( const visibleCriteria = filterTags.slice(0, cutoff);
<FilterTag const hiddenCriteria = filterTags.slice(cutoff);
key="search-term"
className="search-term-filter-tag"
label={
<span className="search-term">
<Icon icon={faMagnifyingGlass} />
{searchTerm}
</span>
}
onClick={() => onEditSearchTerm?.()}
onRemove={() => onRemoveSearchTerm?.()}
/>
);
}
const visibleCriteria = cutoff ? filterTags.slice(0, cutoff) : filterTags;
const hiddenCriteria = cutoff ? filterTags.slice(cutoff) : [];
return ( return (
<div className={className} ref={ref}> <div className={className} ref={ref}>
{visibleCriteria} {visibleCriteria}
<MoreFilterTags tags={hiddenCriteria} /> <MoreFilterTags tags={hiddenCriteria} />
{filterTags.length >= 3 && ( {criteria.length >= 3 && (
<Button
variant="minimal"
className="clear-all-button"
onClick={() => onRemoveAll()}
>
<FormattedMessage id="actions.clear" />
</Button>
)}
</div>
);
}
return (
<div className={className} ref={ref}>
{filterTags}
{criteria.length >= 3 && (
<Button <Button
variant="minimal" variant="minimal"
className="clear-all-button" className="clear-all-button"

View file

@ -16,17 +16,8 @@ export const FilteredSidebarHeader: React.FC<{
filter: ListFilterModel; filter: ListFilterModel;
setFilter: (filter: ListFilterModel) => void; setFilter: (filter: ListFilterModel) => void;
view?: View; view?: View;
focus?: ReturnType<typeof useFocus>; }> = ({ sidebarOpen, showEditFilter, filter, setFilter, view }) => {
}> = ({ const focus = useFocus();
sidebarOpen,
showEditFilter,
filter,
setFilter,
view,
focus: providedFocus,
}) => {
const localFocus = useFocus();
const focus = providedFocus ?? localFocus;
const [, setFocus] = focus; const [, setFocus] = focus;
// Set the focus on the input field when the sidebar is opened // Set the focus on the input field when the sidebar is opened

View file

@ -196,12 +196,9 @@ export function useFilterOperations(props: {
[setFilter] [setFilter]
); );
const clearAllCriteria = useCallback( const clearAllCriteria = useCallback(() => {
(includeSearchTerm = false) => { setFilter((cv) => cv.clearCriteria());
setFilter((cv) => cv.clearCriteria(includeSearchTerm)); }, [setFilter]);
},
[setFilter]
);
return { return {
setPage, setPage,

View file

@ -63,7 +63,6 @@ import { Icon } from "../Shared/Icon";
import { ListViewOptions } from "../List/ListViewOptions"; import { ListViewOptions } from "../List/ListViewOptions";
import { PageSizeSelector, SortBySelect } from "../List/ListFilter"; import { PageSizeSelector, SortBySelect } from "../List/ListFilter";
import { Criterion } from "src/models/list-filter/criteria/criterion"; import { Criterion } from "src/models/list-filter/criteria/criterion";
import useFocus from "src/utils/focus";
function renderMetadataByline(result: GQL.FindScenesQueryResult) { function renderMetadataByline(result: GQL.FindScenesQueryResult) {
const duration = result?.data?.findScenes?.duration; const duration = result?.data?.findScenes?.duration;
@ -242,7 +241,6 @@ const SidebarContent: React.FC<{
onClose?: () => void; onClose?: () => void;
showEditFilter: (editingCriterion?: string) => void; showEditFilter: (editingCriterion?: string) => void;
count?: number; count?: number;
focus?: ReturnType<typeof useFocus>;
}> = ({ }> = ({
filter, filter,
setFilter, setFilter,
@ -252,7 +250,6 @@ const SidebarContent: React.FC<{
sidebarOpen, sidebarOpen,
onClose, onClose,
count, count,
focus,
}) => { }) => {
const showResultsId = const showResultsId =
count !== undefined ? "actions.show_count_results" : "actions.show_results"; count !== undefined ? "actions.show_count_results" : "actions.show_results";
@ -267,7 +264,6 @@ const SidebarContent: React.FC<{
filter={filter} filter={filter}
setFilter={setFilter} setFilter={setFilter}
view={view} view={view}
focus={focus}
/> />
<ScenesFilterSidebarSections> <ScenesFilterSidebarSections>
@ -330,7 +326,6 @@ interface IOperations {
} }
const ListToolbarContent: React.FC<{ const ListToolbarContent: React.FC<{
searchTerm: string;
criteria: Criterion[]; criteria: Criterion[];
items: GQL.SlimSceneDataFragment[]; items: GQL.SlimSceneDataFragment[];
selectedIds: Set<string>; selectedIds: Set<string>;
@ -339,8 +334,6 @@ const ListToolbarContent: React.FC<{
onEditCriterion: (c: Criterion) => void; onEditCriterion: (c: Criterion) => void;
onRemoveCriterion: (criterion: Criterion, valueIndex?: number) => void; onRemoveCriterion: (criterion: Criterion, valueIndex?: number) => void;
onRemoveAllCriterion: () => void; onRemoveAllCriterion: () => void;
onEditSearchTerm: () => void;
onRemoveSearchTerm: () => void;
onSelectAll: () => void; onSelectAll: () => void;
onSelectNone: () => void; onSelectNone: () => void;
onEdit: () => void; onEdit: () => void;
@ -348,7 +341,6 @@ const ListToolbarContent: React.FC<{
onPlay: () => void; onPlay: () => void;
onCreateNew: () => void; onCreateNew: () => void;
}> = ({ }> = ({
searchTerm,
criteria, criteria,
items, items,
selectedIds, selectedIds,
@ -357,8 +349,6 @@ const ListToolbarContent: React.FC<{
onEditCriterion, onEditCriterion,
onRemoveCriterion, onRemoveCriterion,
onRemoveAllCriterion, onRemoveAllCriterion,
onEditSearchTerm,
onRemoveSearchTerm,
onSelectAll, onSelectAll,
onSelectNone, onSelectNone,
onEdit, onEdit,
@ -380,13 +370,10 @@ const ListToolbarContent: React.FC<{
title={intl.formatMessage({ id: "actions.sidebar.toggle" })} title={intl.formatMessage({ id: "actions.sidebar.toggle" })}
/> />
<FilterTags <FilterTags
searchTerm={searchTerm}
criteria={criteria} criteria={criteria}
onEditCriterion={onEditCriterion} onEditCriterion={onEditCriterion}
onRemoveCriterion={onRemoveCriterion} onRemoveCriterion={onRemoveCriterion}
onRemoveAll={onRemoveAllCriterion} onRemoveAll={onRemoveAllCriterion}
onEditSearchTerm={onEditSearchTerm}
onRemoveSearchTerm={onRemoveSearchTerm}
truncateOnOverflow truncateOnOverflow
/> />
</div> </div>
@ -533,9 +520,6 @@ export const FilteredSceneList = (props: IFilteredScenes) => {
const intl = useIntl(); const intl = useIntl();
const history = useHistory(); const history = useHistory();
const searchFocus = useFocus();
const [, setSearchFocus] = searchFocus;
const { filterHook, defaultSort, view, alterQuery, fromGroupId } = props; const { filterHook, defaultSort, view, alterQuery, fromGroupId } = props;
// States // States
@ -790,7 +774,6 @@ export const FilteredSceneList = (props: IFilteredScenes) => {
sidebarOpen={showSidebar} sidebarOpen={showSidebar}
onClose={() => setShowSidebar(false)} onClose={() => setShowSidebar(false)}
count={cachedResult.loading ? undefined : totalCount} count={cachedResult.loading ? undefined : totalCount}
focus={searchFocus}
/> />
</Sidebar> </Sidebar>
<div> <div>
@ -800,7 +783,6 @@ export const FilteredSceneList = (props: IFilteredScenes) => {
})} })}
> >
<ListToolbarContent <ListToolbarContent
searchTerm={filter.searchTerm}
criteria={filter.criteria} criteria={filter.criteria}
items={items} items={items}
selectedIds={selectedIds} selectedIds={selectedIds}
@ -808,12 +790,7 @@ export const FilteredSceneList = (props: IFilteredScenes) => {
onToggleSidebar={() => setShowSidebar(!showSidebar)} onToggleSidebar={() => setShowSidebar(!showSidebar)}
onEditCriterion={(c) => showEditFilter(c.criterionOption.type)} onEditCriterion={(c) => showEditFilter(c.criterionOption.type)}
onRemoveCriterion={removeCriterion} onRemoveCriterion={removeCriterion}
onRemoveAllCriterion={() => clearAllCriteria(true)} onRemoveAllCriterion={() => clearAllCriteria()}
onEditSearchTerm={() => {
setShowSidebar(true);
setSearchFocus(true);
}}
onRemoveSearchTerm={() => setFilter(filter.clearSearchTerm())}
onSelectAll={() => onSelectAll()} onSelectAll={() => onSelectAll()}
onSelectNone={() => onSelectNone()} onSelectNone={() => onSelectNone()}
onEdit={onEdit} onEdit={onEdit}

View file

@ -698,10 +698,8 @@ div.dropdown-menu {
} }
.tag-item { .tag-item {
align-items: center;
background-color: $muted-gray; background-color: $muted-gray;
color: $dark-text; color: $dark-text;
display: flex;
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
line-height: 16px; line-height: 16px;
@ -712,20 +710,17 @@ div.dropdown-menu {
cursor: pointer; cursor: pointer;
} }
.search-term svg {
margin-left: 0;
}
.btn { .btn {
background: none; background: none;
border: none; border: none;
bottom: 2px; bottom: 2px;
color: $dark-text; color: $dark-text;
font-size: 12px; font-size: 12px;
line-height: 16px; line-height: 1rem;
margin-right: -0.5rem; margin-right: -0.5rem;
opacity: 0.5; opacity: 0.5;
padding: 0 0.5rem; padding: 0 0.5rem;
position: relative;
&:active, &:active,
&:hover { &:hover {

View file

@ -476,23 +476,13 @@ export class ListFilterModel {
return this.setCriteria(criteria); return this.setCriteria(criteria);
} }
public clearCriteria(clearSearchTerm = false) { public clearCriteria() {
const ret = this.clone(); const ret = this.clone();
if (clearSearchTerm) {
ret.searchTerm = "";
}
ret.criteria = []; ret.criteria = [];
ret.currentPage = 1; ret.currentPage = 1;
return ret; return ret;
} }
public clearSearchTerm() {
const ret = this.clone();
ret.searchTerm = "";
ret.currentPage = 1; // reset to first page
return ret;
}
public setCriteria(criteria: Criterion[]) { public setCriteria(criteria: Criterion[]) {
const ret = this.clone(); const ret = this.clone();
ret.criteria = criteria; ret.criteria = criteria;

View file

@ -2,15 +2,11 @@ import { useRef, useEffect, useCallback } from "react";
const useFocus = () => { const useFocus = () => {
const htmlElRef = useRef<HTMLInputElement | null>(null); const htmlElRef = useRef<HTMLInputElement | null>(null);
const setFocus = useCallback((selectAll?: boolean) => { const setFocus = useCallback(() => {
const currentEl = htmlElRef.current; const currentEl = htmlElRef.current;
if (currentEl) { if (currentEl) {
if (selectAll) {
currentEl.select();
} else {
currentEl.focus(); currentEl.focus();
} }
}
}, []); }, []);
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef