-
Notifications
You must be signed in to change notification settings - Fork 12
/
MixedOwnersAutocomplete.jsx
113 lines (108 loc) · 3.94 KB
/
MixedOwnersAutocomplete.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import React from 'react';
import {Person as PersonIcon, AccountBalance as HomeIcon} from '@mui/icons-material';
import { TextField, CircularProgress } from '@mui/material';
import Autocomplete from '@mui/material/Autocomplete';
import { get, debounce, map, orderBy, isEmpty } from 'lodash'
import APIService from '../../services/APIService';
import { ORANGE } from '../../common/constants';
const MixedOwnersAutocomplete = ({onChange, label, id, required, minCharactersForSearch}) => {
const minLength = minCharactersForSearch || 2;
const [input, setInput] = React.useState('')
const [open, setOpen] = React.useState(false)
const [fetched, setFetched] = React.useState(false)
const [owners, setOwners] = React.useState([])
const [selected, setSelected] = React.useState(undefined)
const isSearchable = input && input.length >= minLength;
const loading = Boolean(open && !fetched && isSearchable && isEmpty(owners))
const handleInputChange = debounce((event, value) => {
setInput(value || '')
setFetched(false)
if(value && value.length >= minLength)
fetchOwners(value)
}, 500)
const handleChange = (id, item) => {
setSelected(item)
onChange(id, item)
}
const fetchOwners = searchStr => {
const searchQuery = searchStr ? searchStr.replace(' (org)', '').replace(' (user)', '') : searchStr;
const query = {limit: 1000, q: searchQuery}
APIService.orgs().get(null, null, query).then(response => {
const orgs = orderBy(
map(response.data, org => ({...org, ownerType: 'org', name: org.id})),
['name']
)
APIService.users().get(null, null, query).then(response => {
const users = orderBy(
map(response.data, user => ({...user, ownerType: 'user', name: user.username})),
'name'
)
setOwners(() => [...orgs, ...users])
setFetched(true)
})
})
}
return (
<Autocomplete
openOnFocus
blurOnSelect
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
isOptionEqualToValue={(option, value) => option.id === get(value, 'id')}
value={selected}
id={id || 'owner'}
options={owners}
loading={loading}
loadingText={loading ? 'Loading...' : `Type atleast ${minLength} characters to search`}
noOptionsText={(isSearchable && !loading) ? "No results" : 'Start typing...'}
getOptionLabel={option => option ? `${option.name} (${option.ownerType})` : ''}
fullWidth
required={required}
onInputChange={handleInputChange}
onChange={(event, item) => handleChange(id || 'owner', item)}
renderInput={
params => (
<TextField
{...params}
value={input}
required
label={label || "Organization/User"}
variant="outlined"
fullWidth
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)
}
renderOption={
(props, option) => (
<li {...props} key={`${option.ownerType}-${option.name}`}>
<span className='flex-vertical-center'>
<span style={{marginRight: '5px'}}>
{
option.ownerType === 'org' ?
<HomeIcon fontSize='small' style={{marginTop: '5px', color: ORANGE, fontSize: '1rem'}} />:
<PersonIcon fontSize='small' style={{marginTop: '5px', color: ORANGE, fontSize: '1rem'}} />
}
</span>
{option.name}
</span>
</li>
)
}
/>
);
}
export default MixedOwnersAutocomplete;