mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-18 01:36:08 +08:00
ui: autocomplete: rewrite in typescript
This commit is contained in:
1 parent
370fc07914
commit
8f4a63006a
11 files changed
+332
-293
No files matched your search
@@ -1,89 +1,43 @@
|
||||
import React, {
|
||||
forwardRef, useImperativeHandle, useRef, useEffect,
|
||||
} from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import React, { forwardRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import api, { gql } from 'vj/utils/api';
|
||||
import AutoComplete from './AutoComplete';
|
||||
import type { AutoCompleteOptions } from '..';
|
||||
import type { Udoc } from 'hydrooj/src/interface';
|
||||
import AutoComplete, { AutoCompleteHandle, AutoCompleteProps } from './AutoComplete';
|
||||
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
const UserSelectAutoComplete = forwardRef(function UserSelectAutoComplete(
|
||||
props: AutoCompleteOptions, ref: React.ForwardedRef<AutoComplete>,
|
||||
) {
|
||||
const multi = props.multi ?? false;
|
||||
const rawDefaultItems = props.defaultItems ?? '';
|
||||
const defaultItems = multi ? rawDefaultItems
|
||||
.split(',')
|
||||
.map((i) => +i.trim())
|
||||
.filter((i) => i) : rawDefaultItems;
|
||||
|
||||
const comRef = useRef<AutoComplete>();
|
||||
const itemsBox = useRef([]);
|
||||
const { isLoading } = useQuery(['default_user', defaultItems], async () => {
|
||||
if (!multi || defaultItems.length === 0) return;
|
||||
const items = await api(gql`
|
||||
users(ids: ${defaultItems}) {
|
||||
const UserSelectAutoComplete = forwardRef<AutoCompleteHandle<Udoc>, AutoCompleteProps<Udoc>>((props, ref) => (
|
||||
<AutoComplete<Udoc>
|
||||
ref={ref as any}
|
||||
cacheKey="user"
|
||||
{...props}
|
||||
queryItems={(query) => api(gql`
|
||||
users(search: ${query}) {
|
||||
_id
|
||||
uname
|
||||
avatarUrl
|
||||
}
|
||||
`, ['data', 'users'])}
|
||||
fetchItems={(ids) => api(gql`
|
||||
users(ids: ${ids.map((i) => +i)}) {
|
||||
_id
|
||||
uname
|
||||
}
|
||||
`, ['data', 'users']);
|
||||
itemsBox.current = items;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (multi && defaultItems.length > 0) {
|
||||
comRef.current.setSelectedItems(itemsBox.current);
|
||||
}
|
||||
}, [itemsBox.current]);
|
||||
|
||||
useImperativeHandle(ref, () => new Proxy(comRef, {
|
||||
get(target, propKey) {
|
||||
if (typeof target.current?.[propKey] === 'function') {
|
||||
return (...args: any[]) => target.current[propKey](...args);
|
||||
}
|
||||
return target.current?.[propKey];
|
||||
},
|
||||
}));
|
||||
|
||||
const itemsFn = (query) => api(gql`
|
||||
users(search: ${query}) {
|
||||
_id
|
||||
uname
|
||||
avatarUrl
|
||||
}
|
||||
`, ['data', 'users']);
|
||||
|
||||
const itemText = (user) => user.uname || user;
|
||||
|
||||
const itemKey = (user) => user._id;
|
||||
|
||||
const renderItem = (user) => (
|
||||
<div className="media">
|
||||
<div className="media__left medium">
|
||||
<img className="small user-profile-avatar" alt="" src={user.avatarUrl} width="30" height="30" />
|
||||
`, ['data', 'users'])}
|
||||
itemText={(user) => user.uname}
|
||||
itemKey={(user) => (props.multi ? user._id.toString() : user.uname)}
|
||||
renderItem={(user) => (
|
||||
<div className="media">
|
||||
<div className="media__left medium">
|
||||
<img className="small user-profile-avatar" alt="" src={user.avatarUrl} width="30" height="30" />
|
||||
</div>
|
||||
<div className="media__body medium">
|
||||
<div className="user-select__uname">{user.uname}</div>
|
||||
<div className="user-select__uid">UID = {user._id}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="media__body medium">
|
||||
<div className="user-select__uname">{user.uname}</div>
|
||||
<div className="user-select__uid">UID = {user._id}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<AutoComplete
|
||||
ref={comRef}
|
||||
{...props}
|
||||
disabled={isLoading}
|
||||
disabledHint="Loading..."
|
||||
itemsFn={itemsFn}
|
||||
itemText={itemText}
|
||||
itemKey={multi ? itemKey : itemText}
|
||||
renderItem={renderItem}
|
||||
defaultItems={multi ? [] : rawDefaultItems}
|
||||
/>
|
||||
);
|
||||
});
|
||||
)}
|
||||
/>
|
||||
));
|
||||
|
||||
UserSelectAutoComplete.propTypes = {
|
||||
width: PropTypes.string,
|
||||
@@ -91,7 +45,7 @@ UserSelectAutoComplete.propTypes = {
|
||||
listStyle: PropTypes.object,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
multi: PropTypes.bool,
|
||||
defaultItems: PropTypes.string,
|
||||
selectedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||
allowEmptyQuery: PropTypes.bool,
|
||||
freeSolo: PropTypes.bool,
|
||||
freeSoloConverter: PropTypes.func,
|
||||
@@ -102,7 +56,7 @@ UserSelectAutoComplete.defaultProps = {
|
||||
height: 'auto',
|
||||
listStyle: {},
|
||||
multi: false,
|
||||
defaultItems: '',
|
||||
selectedKeys: [],
|
||||
allowEmptyQuery: false,
|
||||
freeSolo: false,
|
||||
freeSoloConverter: (input) => input,
|
||||
|
||||
Reference in new issue
Block a user