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
[Assistants] Filter on names #841
Changes from 6 commits
30796e5
00784d4
3dd82df
c575708
285b6fe
c0387ce
d65f7c1
65b5d89
9365a75
05a8cf2
08e8256
f8bb522
34ed43b
1d0da52
cffcff5
e696796
4cc41c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* A debounce function that works in both browser and Nodejs. | ||
* For pure Nodejs work, prefer the `Debouncer` class. | ||
*/ | ||
export function debounce<T extends unknown[]>( | ||
callback: (...rest: T) => unknown, | ||
limit: number | ||
): (...rest: T) => void { | ||
let timer: ReturnType<typeof setTimeout>; | ||
|
||
return function (...rest) { | ||
clearTimeout(timer); | ||
timer = setTimeout(() => { | ||
callback(...rest); | ||
}, limit); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
import { PUBLIC_APP_ASSETS, PUBLIC_ORIGIN } from "$env/static/public"; | ||
import { isHuggingChat } from "$lib/utils/isHuggingChat"; | ||
|
||
import { tick } from "svelte"; | ||
import { goto } from "$app/navigation"; | ||
import { base } from "$app/paths"; | ||
import { page } from "$app/stores"; | ||
|
@@ -14,22 +15,40 @@ | |
import CarbonArrowUpRight from "~icons/carbon/arrow-up-right"; | ||
import CarbonEarthAmerica from "~icons/carbon/earth-americas-filled"; | ||
import CarbonUserMultiple from "~icons/carbon/user-multiple"; | ||
import CarbonSearch from "~icons/carbon/search"; | ||
import Pagination from "$lib/components/Pagination.svelte"; | ||
import { formatUserCount } from "$lib/utils/formatUserCount"; | ||
import { getHref } from "$lib/utils/getHref"; | ||
import { debounce } from "$lib/utils/debounce"; | ||
|
||
export let data: PageData; | ||
|
||
$: assistantsCreator = $page.url.searchParams.get("user"); | ||
$: createdByMe = data.user?.username && data.user.username === assistantsCreator; | ||
|
||
const SEARCH_DEBOUNCE_DELAY = 400; | ||
let filterInputEl: HTMLInputElement; | ||
let searchDisabled = false; | ||
|
||
const onModelChange = (e: Event) => { | ||
const newUrl = getHref($page.url, { | ||
newKeys: { modelId: (e.target as HTMLSelectElement).value }, | ||
existingKeys: { behaviour: "delete_except", keys: ["user"] }, | ||
}); | ||
goto(newUrl); | ||
}; | ||
|
||
const filterOnName = debounce(async (e: Event) => { | ||
searchDisabled = true; | ||
const value = (e.target as HTMLInputElement).value; | ||
const newUrl = getHref($page.url, { newKeys: { q: value } }); | ||
await goto(newUrl); | ||
setTimeout(async () => { | ||
searchDisabled = false; | ||
await tick(); | ||
filterInputEl.focus(); | ||
}, 0); | ||
}, SEARCH_DEBOUNCE_DELAY); | ||
</script> | ||
|
||
<svelte:head> | ||
|
@@ -96,7 +115,7 @@ | |
{assistantsCreator}'s Assistants | ||
<a | ||
href={getHref($page.url, { | ||
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p"] }, | ||
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] }, | ||
})} | ||
class="group" | ||
><CarbonClose | ||
|
@@ -116,7 +135,7 @@ | |
{:else} | ||
<a | ||
href={getHref($page.url, { | ||
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p"] }, | ||
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] }, | ||
})} | ||
class="flex items-center gap-1.5 rounded-full border px-3 py-1 {!assistantsCreator | ||
? 'border-gray-300 bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-white' | ||
|
@@ -129,16 +148,32 @@ | |
<a | ||
href={getHref($page.url, { | ||
newKeys: { user: data.user.username }, | ||
existingKeys: { behaviour: "delete", keys: ["modelId", "p"] }, | ||
existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q"] }, | ||
})} | ||
class="flex items-center gap-1.5 rounded-full border px-3 py-1 {assistantsCreator && | ||
class="flex items-center gap-1.5 truncate rounded-full border px-3 py-1 {assistantsCreator && | ||
createdByMe | ||
? 'border-gray-300 bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-white' | ||
: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}" | ||
>{data.user.username} | ||
</a> | ||
{/if} | ||
{/if} | ||
<div | ||
class="ml-auto mr-2 flex h-9 w-9 items-center gap-x-2 rounded-full border border-gray-300 px-2 transition-all duration-300 ease-out hover:w-64 md:w-64 dark:border-gray-500" | ||
> | ||
<button class="flex-shrink-0 cursor-default" on:click={() => filterInputEl.focus()} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this |
||
><CarbonSearch class="text-gray-400" /></button | ||
> | ||
<input | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get weird behaviour (undefined is the default value then it's not obvious that there're results) Screen.Recording.2024-02-20.at.14.07.59.movThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
class="h-9 w-full rounded-full bg-transparent focus:outline-none" | ||
placeholder="Filter by name" | ||
value={data.query} | ||
on:input={filterOnName} | ||
bind:this={filterInputEl} | ||
maxlength="150" | ||
disabled={searchDisabled} | ||
/> | ||
</div> | ||
</div> | ||
|
||
<div class="mt-8 grid grid-cols-2 gap-3 sm:gap-5 md:grid-cols-3 lg:grid-cols-4"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
taking advantage of svelte partial hydration without creating explicit API routes for now