-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add admin-only user-search typeahead to AddProjectMember dialog (#692)
* Create user-search typeahead in sandbox Will want to tweak styling later, but this basically works. Now to extract it into a Svelte component and use it (behind an admin-only flag) in the AddProjectMember component. * Better UI for typeahead * Create UserTypeahead component, use it in demo * Use admin-only typeahead in AddProjectMember * Fix lint errors * Improve UI for typeahead results Some excellent UI suggestions from Tim - thanks! * Simplify user typeahead to just return string * Fix overlay-container for modals and remove browser autocomplete * Fix typo during merge resolution * Fix width of typeahead input * Debounce typeahead results * Better formatting for typeahead results * Fix "selectedUser is null" bug * Allow user to ignore typeahead if desired Now if the user ignores the typeahead results and just submits the form, the value in the input field will correctly be used as it was before. * Remove typeahead from sandbox page, fix lint error * Close input overlay on focusout * Default typeahead limit is now 10 items * Remove leftover console log * Rename _typeaheadSearch to _userTypeaheadSearch * Remove now-unused import * No need for limit+1 in typeahead results --------- Co-authored-by: Tim Haasdyk <[email protected]>
- Loading branch information
Showing
8 changed files
with
158 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<script lang="ts"> | ||
import { FormField, PlainInput, randomFormId } from '$lib/forms'; | ||
import { _userTypeaheadSearch, type SingleUserTypeaheadResult } from '$lib/gql/typeahead-queries'; | ||
import { overlay } from '$lib/overlay'; | ||
import { deriveAsync } from '$lib/util/time'; | ||
import { writable } from 'svelte/store'; | ||
export let label: string; | ||
export let error: string | string[] | undefined = undefined; | ||
export let id: string = randomFormId(); | ||
export let autofocus = false; | ||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents | ||
export let value: string; | ||
export let debounceMs = 200; | ||
let input = writable(''); | ||
$: $input = value; | ||
let typeaheadResults = deriveAsync(input, _userTypeaheadSearch, [], debounceMs); | ||
function formatResult(user: SingleUserTypeaheadResult): string { | ||
const extra = user.username && user.email ? ` (${user.username}, ${user.email})` | ||
: user.username ? ` (${user.username})` | ||
: user.email ? ` (${user.email})` | ||
: ''; | ||
return `${user.name}${extra}`; | ||
} | ||
</script> | ||
|
||
<FormField {id} {label} {error} {autofocus} > | ||
<div use:overlay={{ closeClickSelector: '.menu li'}}> | ||
<PlainInput style="w-full" debounce {id} bind:value type="text" autocomplete="off" /> | ||
<div class="overlay-content"> | ||
<ul class="menu p-0"> | ||
{#each $typeaheadResults as user} | ||
<li class="p-0"><button class="whitespace-nowrap" on:click={() => setTimeout(() => $input = value = user.email ?? user.username ?? '')}>{formatResult(user)}</button></li> | ||
{/each} | ||
</ul> | ||
</div> | ||
</div> | ||
</FormField> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import type { LoadAdminUsersTypeaheadQuery, UserFilterInput } from './types'; | ||
|
||
import { getClient } from './gql-client'; | ||
import { graphql } from './generated'; | ||
|
||
export function userFilter(userSearch: string): UserFilterInput { | ||
return { | ||
or: [ | ||
{name: {icontains: userSearch}}, | ||
{email: {icontains: userSearch}}, | ||
{username: {icontains: userSearch}} | ||
] | ||
}; | ||
} | ||
|
||
export type UserTypeaheadResult = NonNullable<NonNullable<LoadAdminUsersTypeaheadQuery['users']>['items']>; | ||
export type SingleUserTypeaheadResult = UserTypeaheadResult[number]; | ||
|
||
export async function _userTypeaheadSearch(userSearch: string, limit = 10): Promise<UserTypeaheadResult> { | ||
if (!userSearch) return Promise.resolve([]); | ||
const client = getClient(); | ||
const result = client.query(graphql(` | ||
query loadAdminUsersTypeahead($filter: UserFilterInput, $take: Int!) { | ||
users( | ||
where: $filter, orderBy: {name: ASC}, take: $take) { | ||
totalCount | ||
items { | ||
id | ||
name | ||
username | ||
} | ||
} | ||
} | ||
`), { filter: userFilter(userSearch), take: limit }); | ||
// NOTE: If more properties are needed, copy from loadAdminDashboardUsers to save time | ||
|
||
const users = result.then(users => { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const count = users.data?.users?.totalCount ?? 0; | ||
if (0 < count && count <= limit) { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
return users.data?.users?.items ?? []; | ||
} else { | ||
return []; | ||
} | ||
}); | ||
|
||
return users; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<script> | ||
import { overlayContainer } from '.'; | ||
</script> | ||
|
||
<div use:overlayContainer class="bg-base-200 shadow rounded-box z-[2] absolute" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters