Skip to content

Commit e45921d

Browse files
refactor: extract filter methods to separate file
1 parent 93921dc commit e45921d

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

src/lib/components/composites/paper-components/paper-view/cards/ReferencesAndCitationsCardContent.svelte

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script lang="ts">
22
import NamedList from "$lib/components/composites/list/NamedList.svelte";
33
import SearchBar from "$lib/components/composites/search-bar/SearchBar.svelte";
4-
import { Fzf } from "fzf";
54
import PaperListEntry from "../../PaperListEntry.svelte";
65
import PaperListEntrySkeleton from "../../PaperListEntrySkeleton.svelte";
76
import type { Paper } from "$lib/model/api/paper";
7+
import { filterPapers } from "$lib/filters";
88
99
export interface ReferencesAndCitationsCardContentProps {
1010
backwardReferencedPapers: Promise<Paper[]>;
@@ -19,14 +19,6 @@
1919
let backwardReferencedPapers = $state<Promise<Paper[]>>(allBackwardReferencedPapers);
2020
let forwardReferencedPapers = $state<Promise<Paper[]>>(allForwardReferencedPapers);
2121
22-
function filterPapers(allPapers: Paper[], searchText: string) {
23-
const fzf = new Fzf(allPapers, {
24-
selector: (paper) => `#${paper!.id} ${paper!.title}`,
25-
casing: "case-insensitive",
26-
});
27-
return fzf.find(searchText).map((result) => result.item);
28-
}
29-
3022
function filterBackwardReferencedPapers(searchText: string) {
3123
backwardReferencedPapers = allBackwardReferencedPapers.then((allPapers) =>
3224
filterPapers(allPapers, searchText),

src/lib/components/composites/project-components/CreateProjectDialog.svelte

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
import { cn } from "$lib/utils/shadcn-helper";
99
import ChipsInput from "$lib/components/composites/input/ChipsInput.svelte";
1010
import { onMount } from "svelte";
11-
import { Fzf } from "fzf";
1211
import { goto } from "$app/navigation";
1312
import { getName, getNames } from "$lib/utils/common-helper";
1413
import type { ValidationResult } from "$lib/model/general";
1514
import ErrorAlert from "$lib/components/composites/ErrorAlert.svelte";
1615
import { backendService } from "$lib/grpc-api";
1716
import { Nothing } from "$lib/model/api/base";
1817
import type { User } from "$lib/model/api/user";
18+
import { filterUsers } from "$lib/filters";
1919
2020
// at the beginning the dialog should not be open
2121
let open: boolean = $state(false);
@@ -60,8 +60,9 @@
6060
* @returns list of "name \<email\>" (sorted) representations of users that can be invited
6161
*/
6262
function filterPossibleMembers(input: string): string[] {
63-
const fzf = new Fzf(possibleMembers.map((user) => `${getName(user)} <${user.email}>`));
64-
return fzf.find(input.toLowerCase()).map((result) => result.item);
63+
return filterUsers(possibleMembers, input).map(
64+
(member) => `${getName(member)} <${member.email}>`,
65+
);
6566
}
6667
6768
/**

src/lib/filters.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Fzf, type Selector } from "fzf";
2+
import type { Paper } from "./model/api/paper";
3+
import { getName, getNames } from "./utils/common-helper";
4+
import type { User } from "./model/api/user";
5+
6+
/**
7+
* Generic filter function using Fzf.
8+
*
9+
* @param items - List of items to filter
10+
* @param selector - Function to extract the string to match against
11+
* @param searchText - Search text
12+
* @returns List of items that match the search text
13+
*/
14+
function filter<T>(items: T[], selector: (item: T) => string, searchText: string) {
15+
// Here we case the items to string[] and selector to Selector<string> because we can't just use a selector
16+
// with a generic type. This is weird but it's the only way to make it work.
17+
const fzf = new Fzf(items as string[], {
18+
selector: selector as Selector<string>,
19+
casing: "case-insensitive",
20+
});
21+
return fzf.find(searchText).map((result) => result.item) as T[];
22+
}
23+
24+
/**
25+
* Filters papers based on search text and sorts them by best match.
26+
*
27+
* The search text is matched against the following fields:
28+
* - Paper ID
29+
* - Paper Title
30+
* - Paper Authors
31+
*
32+
* @param allPapers - List of all papers
33+
* @param searchText - Search text
34+
* @returns List of papers that match the search text
35+
*/
36+
function filterPapers(allPapers: Paper[], searchText: string) {
37+
return filter(
38+
allPapers,
39+
(paper) => `#${paper.id} ${paper.title} ${getNames(paper.authors)}`,
40+
searchText,
41+
);
42+
}
43+
44+
/**
45+
* Filter users based on search text and sorts them by best match.
46+
*
47+
* The search text is matched against the following fields:
48+
* - User Name
49+
* - User Email
50+
*
51+
* @param allUsers - List of all users
52+
* @param searchText - Search text
53+
* @returns List of users that match the search text
54+
*/
55+
function filterUsers(allUsers: User[], searchText: string) {
56+
return filter(allUsers, (user) => `${getName(user)} ${user.email}`, searchText);
57+
}
58+
59+
export { filterPapers, filterUsers };

0 commit comments

Comments
 (0)