diff options
Diffstat (limited to 'web/source/settings/views/moderation/accounts/search/index.tsx')
-rw-r--r-- | web/source/settings/views/moderation/accounts/search/index.tsx | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/web/source/settings/views/moderation/accounts/search/index.tsx b/web/source/settings/views/moderation/accounts/search/index.tsx index 8ee579e16..58e2d6505 100644 --- a/web/source/settings/views/moderation/accounts/search/index.tsx +++ b/web/source/settings/views/moderation/accounts/search/index.tsx @@ -17,28 +17,53 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import React from "react"; +import React, { ReactNode, useEffect, useMemo } from "react"; import { useLazySearchAccountsQuery } from "../../../../lib/query/admin"; import { useTextInput } from "../../../../lib/form"; -import { AccountList } from "../../../../components/account-list"; -import { SearchAccountParams } from "../../../../lib/types/account"; +import { PageableList } from "../../../../components/pageable-list"; import { Select, TextInput } from "../../../../components/form/inputs"; import MutationButton from "../../../../components/form/mutation-button"; +import { useLocation, useSearch } from "wouter"; +import { AdminAccount } from "../../../../lib/types/account"; +import Username from "../../../../components/username"; export function AccountSearchForm() { + const [ location, setLocation ] = useLocation(); + const search = useSearch(); + const urlQueryParams = useMemo(() => new URLSearchParams(search), [search]); + const [ searchAcct, searchRes ] = useLazySearchAccountsQuery(); + + // Populate search form using values from + // urlQueryParams, to allow paging. const form = { - origin: useTextInput("origin"), - status: useTextInput("status"), - permissions: useTextInput("permissions"), - username: useTextInput("username"), - display_name: useTextInput("display_name"), - by_domain: useTextInput("by_domain"), - email: useTextInput("email"), - ip: useTextInput("ip"), + origin: useTextInput("origin", { defaultValue: urlQueryParams.get("origin") ?? ""}), + status: useTextInput("status", { defaultValue: urlQueryParams.get("status") ?? ""}), + permissions: useTextInput("permissions", { defaultValue: urlQueryParams.get("permissions") ?? ""}), + username: useTextInput("username", { defaultValue: urlQueryParams.get("username") ?? ""}), + display_name: useTextInput("display_name", { defaultValue: urlQueryParams.get("display_name") ?? ""}), + by_domain: useTextInput("by_domain", { defaultValue: urlQueryParams.get("by_domain") ?? ""}), + email: useTextInput("email", { defaultValue: urlQueryParams.get("email") ?? ""}), + ip: useTextInput("ip", { defaultValue: urlQueryParams.get("ip") ?? ""}), + limit: useTextInput("limit", { defaultValue: urlQueryParams.get("limit") ?? "50"}) }; - function submitSearch(e) { + // On mount, if urlQueryParams were provided, + // trigger the search. For example, if page + // was accessed at /search?origin=local&limit=20, + // then run a search with origin=local and + // limit=20 and immediately render the results. + useEffect(() => { + if (urlQueryParams.size > 0) { + searchAcct(Object.fromEntries(urlQueryParams), true); + } + }, [urlQueryParams, searchAcct]); + + // Rather than triggering the search directly, + // the "submit" button changes the location + // based on form field params, and lets the + // useEffect hook above actually do the search. + function submitQuery(e) { e.preventDefault(); // Parse query parameters. @@ -52,16 +77,32 @@ export function AccountSearchForm() { // Remove any nulls. return kv || []; }); - const params: SearchAccountParams = Object.fromEntries(entries); - searchAcct(params); + + const searchParams = new URLSearchParams(entries); + setLocation(location + "?" + searchParams.toString()); } - const [ searchAcct, searchRes ] = useLazySearchAccountsQuery(); + // Location to return to when user clicks "back" on the account detail view. + const backLocation = location + (urlQueryParams ? `?${urlQueryParams}` : ""); + + // Function to map an item to a list entry. + function itemToEntry(account: AdminAccount): ReactNode { + const acc = account.account; + return ( + <Username + key={acc.acct} + account={account} + linkTo={`/${account.id}`} + backLocation={backLocation} + classNames={["entry"]} + /> + ); + } return ( <> <form - onSubmit={submitSearch} + onSubmit={submitQuery} // Prevent password managers trying // to fill in username/email fields. autoComplete="off" @@ -117,13 +158,16 @@ export function AccountSearchForm() { result={searchRes} /> </form> - <AccountList + <PageableList isLoading={searchRes.isLoading} + isFetching={searchRes.isFetching} isSuccess={searchRes.isSuccess} - data={searchRes.data} + items={searchRes.data?.accounts} + itemToEntry={itemToEntry} isError={searchRes.isError} error={searchRes.error} emptyMessage="No accounts found that match your query" + prevNextLinks={searchRes.data?.links} /> </> ); |