1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { Autocomplete } from '~/components/autocomplete/autocomplete';
7 import { connect, DispatchProp } from 'react-redux';
8 import { ServiceRepository } from '~/services/services';
9 import { FilterBuilder } from '../../services/api/filter-builder';
10 import { debounce } from 'debounce';
11 import { ListItemText, Typography } from '@material-ui/core';
12 import { noop } from 'lodash/fp';
13 import { GroupClass } from '~/models/group';
15 export interface Person {
21 export interface PeopleSelectProps {
28 onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
29 onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
30 onCreate?: (person: Person) => void;
31 onDelete?: (index: number) => void;
32 onSelect?: (person: Person) => void;
36 export interface PeopleSelectState {
41 export const PeopleSelect = connect()(
42 class PeopleSelect extends React.Component<PeopleSelectProps & DispatchProp, PeopleSelectState> {
44 state: PeopleSelectState = {
50 const { label = 'Share' } = this.props;
55 value={this.state.value}
56 items={this.props.items}
57 suggestions={this.state.suggestions}
58 autofocus={this.props.autofocus}
59 onChange={this.handleChange}
60 onCreate={this.handleCreate}
61 onSelect={this.handleSelect}
62 onDelete={this.handleDelete}
63 onFocus={this.props.onFocus}
64 onBlur={this.props.onBlur}
65 renderChipValue={this.renderChipValue}
66 renderSuggestion={this.renderSuggestion} />
70 renderChipValue({ name, uuid }: Person) {
71 return name ? name : uuid;
74 renderSuggestion({ firstName, lastName, email, name }: any) {
78 <Typography noWrap>{name}</Typography> :
79 <Typography noWrap>{`${firstName} ${lastName} <<${email}>>`}</Typography>}
84 handleDelete = (_: Person, index: number) => {
85 const { onDelete = noop } = this.props;
89 handleCreate = () => {
90 const { onCreate } = this.props;
92 this.setState({ value: '', suggestions: [] });
96 uuid: this.state.value,
101 handleSelect = ({ email, firstName, lastName, uuid, name }: any) => {
102 const { onSelect = noop } = this.props;
103 this.setState({ value: '', suggestions: [] });
106 name: `${name ? name : `${firstName} ${lastName}`}`,
111 handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
112 this.setState({ value: event.target.value }, this.getSuggestions);
115 getSuggestions = debounce(() => this.props.dispatch<any>(this.requestSuggestions), 500);
117 requestSuggestions = async (_: void, __: void, { userService, groupsService }: ServiceRepository) => {
118 const { value } = this.state;
119 const filterGroups = new FilterBuilder()
120 .addNotIn('groupClass', [GroupClass.PROJECT])
121 .addILike('name', value)
123 const groupItems = await groupsService.list({ filters: filterGroups, limit: 5 });
124 const filterUsers = new FilterBuilder()
125 .addILike('email', value)
127 const userItems: any = await userService.list({ filters: filterUsers, limit: 5 });
128 const items = groupItems.items.concat(userItems.items);
129 this.setState({ suggestions: this.props.onlyPeople ? userItems.items : items });