From 706a9a0928758d1fe7928719c800df1c11791599 Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 19 Mar 2025 10:13:04 +0800 Subject: [PATCH] core&ui: UserSelectAutoComplete: support pasting username/email --- build/prepare.js | 6 ++++- packages/hydrooj/src/handler/user.ts | 23 +++++++++++++++---- .../autocomplete/components/AutoComplete.tsx | 6 ++--- .../components/UserSelectAutoComplete.tsx | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/build/prepare.js b/build/prepare.js index e03f440a7..11d165a51 100644 --- a/build/prepare.js +++ b/build/prepare.js @@ -135,6 +135,7 @@ const UINextConfig = { outDir: path.join(baseOutDir, 'ui-next'), strict: true, + noImplicitAny: false, useDefineForClassFields: true, lib: ['es2022', 'DOM', 'DOM.Iterable'], @@ -150,7 +151,10 @@ const UINextConfig = { paths: { '@/*': [ - './packages/ui-next/*', + './packages/ui-next/src/*', + ], + 'vj/*': [ + './packages/ui-default/*', ], }, }, diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index d3260f9e9..34e19c29c 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -541,11 +541,24 @@ export async function apply(ctx: Context) { return c.user; }, `Get a user by id, uname, or mail. Returns current user if no argument is provided.`); - api.resolver('Query', 'users(ids: [Int], search: String, limit: Int, exact: Boolean)', '[User]', async (arg, c) => { - if (arg.ids?.length) { - const res = await user.getList(c.args.domainId, arg.ids); - for (const i in res) res[i].avatarUrl = avatar(res[i].avatar); - return Object.keys(res).map((id) => res[+id]); + api.resolver('Query', 'users(ids: [Int], auto: [String], search: String, limit: Int, exact: Boolean)', '[User]', async (arg, c) => { + const auto = arg.ids || arg.auto || []; + if (auto.length) { + const maybeId = auto.filter((i) => !Number.isNaN(+i)); + const result = []; + if (maybeId.length) { + const udocs = await user.getList(c.args.domainId, maybeId.map((i) => +i)); + for (const i in udocs) udocs[i].avatarUrl = avatar(udocs[i].avatar); + result.push(...Object.values(udocs)); + } + const notFound = auto.filter((i) => !result.find((j) => j._id === +i)); + if (notFound.length > 50) return result; // reject if too many + for (const i of notFound) { + // eslint-disable-next-line no-await-in-loop + const udoc = await user.getByUname(c.args.domainId, i) || await user.getByEmail(c.args.domainId, i); + if (udoc) result.push(udoc); + } + return result; } if (!arg.search) return []; const udoc = await user.getById(c.args.domainId, +arg.search) diff --git a/packages/ui-default/components/autocomplete/components/AutoComplete.tsx b/packages/ui-default/components/autocomplete/components/AutoComplete.tsx index e90bef43a..614bf9d4d 100644 --- a/packages/ui-default/components/autocomplete/components/AutoComplete.tsx +++ b/packages/ui-default/components/autocomplete/components/AutoComplete.tsx @@ -307,10 +307,10 @@ const AutoComplete = forwardRef(function Impl(props: AutoCompleteProps, re e.preventDefault(); const ids = text.replace(/,/g, ',').split(',').filter((v) => v?.trim().length && !selectedKeys.includes(v)); if (!ids.length) return; - const fetched = await props.fetchItems(ids.filter((v) => !valueCache[v])); + const fetched = await props.fetchItems(ids); for (const item of fetched) valueCache[itemKey(item)] = item; - setSelected([...selected, ...ids.map((id) => valueCache[id])]); - setSelectedKeys([...selectedKeys, ...ids.map((id) => itemKey(valueCache[id]))]); + setSelected([...selected, ...fetched]); + setSelectedKeys([...selectedKeys, ...fetched.map((val) => itemKey(val))]); }} placeholder={props.placeholder} onBlur={() => setFocused(false)} diff --git a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx index b16d0844f..63dc39dfb 100644 --- a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx +++ b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx @@ -19,7 +19,7 @@ const UserSelectAutoComplete = forwardRef, AutoComplete } `, ['data', 'users'])} fetchItems={(ids) => api(gql` - users(ids: ${ids.map((i) => +i)}) { + users(auto: ${ids}) { _id uname displayName