feat: add search title only filter for search options (#4587)
* feat: search title only filter * fix: page reload will keep settings * fix: working with additional filters * style changes
This commit is contained in:
@@ -21,6 +21,7 @@ import Flex from "~/components/Flex";
|
|||||||
import LoadingIndicator from "~/components/LoadingIndicator";
|
import LoadingIndicator from "~/components/LoadingIndicator";
|
||||||
import RegisterKeyDown from "~/components/RegisterKeyDown";
|
import RegisterKeyDown from "~/components/RegisterKeyDown";
|
||||||
import Scene from "~/components/Scene";
|
import Scene from "~/components/Scene";
|
||||||
|
import Switch from "~/components/Switch";
|
||||||
import Text from "~/components/Text";
|
import Text from "~/components/Text";
|
||||||
import withStores from "~/components/withStores";
|
import withStores from "~/components/withStores";
|
||||||
import Logger from "~/utils/Logger";
|
import Logger from "~/utils/Logger";
|
||||||
@@ -159,6 +160,7 @@ class Search extends React.Component<Props> {
|
|||||||
userId?: string | undefined;
|
userId?: string | undefined;
|
||||||
dateFilter?: TDateFilter;
|
dateFilter?: TDateFilter;
|
||||||
includeArchived?: boolean | undefined;
|
includeArchived?: boolean | undefined;
|
||||||
|
titleFilter?: boolean | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
this.props.history.replace({
|
this.props.history.replace({
|
||||||
pathname: this.props.location.pathname,
|
pathname: this.props.location.pathname,
|
||||||
@@ -171,6 +173,10 @@ class Search extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleTitleFilterChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
this.handleFilterChange({ titleFilter: ev.target.checked });
|
||||||
|
};
|
||||||
|
|
||||||
get includeArchived() {
|
get includeArchived() {
|
||||||
return this.params.get("includeArchived") === "true";
|
return this.params.get("includeArchived") === "true";
|
||||||
}
|
}
|
||||||
@@ -190,12 +196,17 @@ class Search extends React.Component<Props> {
|
|||||||
return id ? (id as TDateFilter) : undefined;
|
return id ? (id as TDateFilter) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get titleFilter() {
|
||||||
|
return this.params.get("titleFilter") === "true";
|
||||||
|
}
|
||||||
|
|
||||||
get isFiltered() {
|
get isFiltered() {
|
||||||
return (
|
return (
|
||||||
this.dateFilter ||
|
this.dateFilter ||
|
||||||
this.userId ||
|
this.userId ||
|
||||||
this.collectionId ||
|
this.collectionId ||
|
||||||
this.includeArchived
|
this.includeArchived ||
|
||||||
|
this.titleFilter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +241,7 @@ class Search extends React.Component<Props> {
|
|||||||
includeDrafts: true,
|
includeDrafts: true,
|
||||||
collectionId: this.collectionId,
|
collectionId: this.collectionId,
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
|
titleFilter: this.titleFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
// we just requested this thing – no need to try again
|
// we just requested this thing – no need to try again
|
||||||
@@ -243,7 +255,9 @@ class Search extends React.Component<Props> {
|
|||||||
this.lastParams = params;
|
this.lastParams = params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const results = await this.props.documents.search(this.query, params);
|
const results = this.titleFilter
|
||||||
|
? await this.props.documents.searchTitles(this.query, params)
|
||||||
|
: await this.props.documents.search(this.query, params);
|
||||||
|
|
||||||
// Add to the searches store so this search can immediately appear in
|
// Add to the searches store so this search can immediately appear in
|
||||||
// the recent searches list without a flash of load
|
// the recent searches list without a flash of load
|
||||||
@@ -348,6 +362,13 @@ class Search extends React.Component<Props> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<SearchTitleOnlyFilter
|
||||||
|
width={26}
|
||||||
|
height={14}
|
||||||
|
label={t("Search titles only")}
|
||||||
|
onChange={this.handleTitleFilterChange}
|
||||||
|
checked={this.titleFilter}
|
||||||
|
/>
|
||||||
</Filters>
|
</Filters>
|
||||||
) : (
|
) : (
|
||||||
<RecentSearches />
|
<RecentSearches />
|
||||||
@@ -437,4 +458,11 @@ const Filters = styled(Flex)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const SearchTitleOnlyFilter = styled(Switch)`
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
||||||
|
|
||||||
export default withTranslation()(withStores(withRouter(Search)));
|
export default withTranslation()(withStores(withRouter(Search)));
|
||||||
|
|||||||
@@ -385,14 +385,35 @@ export default class DocumentsStore extends BaseStore<Document> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@action
|
@action
|
||||||
searchTitles = async (query: string) => {
|
searchTitles = async (query: string, options?: SearchParams) => {
|
||||||
|
const compactedOptions = omitBy(options, (o) => !o);
|
||||||
const res = await client.post("/documents.search_titles", {
|
const res = await client.post("/documents.search_titles", {
|
||||||
|
...compactedOptions,
|
||||||
query,
|
query,
|
||||||
});
|
});
|
||||||
invariant(res?.data, "Search response should be available");
|
invariant(res?.data, "Search response should be available");
|
||||||
|
|
||||||
// add the documents and associated policies to the store
|
// add the documents and associated policies to the store
|
||||||
res.data.forEach(this.add);
|
res.data.forEach(this.add);
|
||||||
this.addPolicies(res.policies);
|
this.addPolicies(res.policies);
|
||||||
|
|
||||||
|
// store a reference to the document model in the search cache instead
|
||||||
|
// of the original result from the API.
|
||||||
|
const results: SearchResult[] = compact(
|
||||||
|
res.data.map((result: SearchResult) => {
|
||||||
|
const document = this.data.get(result.id);
|
||||||
|
if (!document) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
document,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const existing = this.searchCache.get(query) || [];
|
||||||
|
// splice modifies any existing results, taking into account pagination
|
||||||
|
existing.splice(0, existing.length, ...results);
|
||||||
|
this.searchCache.set(query, existing);
|
||||||
return res.data;
|
return res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -622,6 +622,7 @@
|
|||||||
"Any author": "Any author",
|
"Any author": "Any author",
|
||||||
"Author": "Author",
|
"Author": "Author",
|
||||||
"We were unable to find the page you’re looking for.": "We were unable to find the page you’re looking for.",
|
"We were unable to find the page you’re looking for.": "We were unable to find the page you’re looking for.",
|
||||||
|
"Search titles only": "Search titles only",
|
||||||
"No documents found for your search filters.": "No documents found for your search filters.",
|
"No documents found for your search filters.": "No documents found for your search filters.",
|
||||||
"Search Results": "Search Results",
|
"Search Results": "Search Results",
|
||||||
"Allowed domains": "Allowed domains",
|
"Allowed domains": "Allowed domains",
|
||||||
|
|||||||
Reference in New Issue
Block a user