Create CreateGroupDialog's form
[arvados-workbench2.git] / src / views-components / sharing-dialog / people-select.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { Autocomplete } from '~/components/autocomplete/autocomplete';
7 import { UserResource } from '~/models/user';
8 import { connect, DispatchProp } from 'react-redux';
9 import { ServiceRepository } from '~/services/services';
10 import { FilterBuilder } from '../../services/api/filter-builder';
11 import { debounce } from 'debounce';
12 import { ListItemText, Typography } from '@material-ui/core';
13 import { noop } from 'lodash/fp';
14
15 export interface Person {
16     name: string;
17     email: string;
18     uuid: string;
19 }
20 export interface PeopleSelectProps {
21
22     items: Person[];
23     label?: string;
24
25     onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
26     onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
27     onCreate?: (person: Person) => void;
28     onDelete?: (index: number) => void;
29     onSelect?: (person: Person) => void;
30
31 }
32
33 export interface PeopleSelectState {
34     value: string;
35     suggestions: UserResource[];
36 }
37
38 export const PeopleSelect = connect()(
39     class PeopleSelect extends React.Component<PeopleSelectProps & DispatchProp, PeopleSelectState> {
40
41         state: PeopleSelectState = {
42             value: '',
43             suggestions: []
44         };
45
46         render() {
47
48             const { label = 'Invite people' } = this.props;
49
50             return (
51                 <Autocomplete
52                     label={label}
53                     value={this.state.value}
54                     items={this.props.items}
55                     suggestions={this.state.suggestions}
56                     onChange={this.handleChange}
57                     onCreate={this.handleCreate}
58                     onSelect={this.handleSelect}
59                     onDelete={this.handleDelete}
60                     onFocus={this.props.onFocus}
61                     onBlur={this.props.onBlur}
62                     renderChipValue={this.renderChipValue}
63                     renderSuggestion={this.renderSuggestion} />
64             );
65         }
66
67         renderChipValue({ name, uuid }: Person) {
68             return name ? name : uuid;
69         }
70
71         renderSuggestion({ firstName, lastName, email }: UserResource) {
72             return (
73                 <ListItemText>
74                     <Typography noWrap>{`${firstName} ${lastName} <<${email}>>`}</Typography>
75                 </ListItemText>
76             );
77         }
78
79         handleDelete = (_: Person, index: number) => {
80             const { onDelete = noop } = this.props;
81             onDelete(index);
82         }
83
84         handleCreate = () => {
85             const { onCreate } = this.props;
86             if (onCreate) {
87                 this.setState({ value: '', suggestions: [] });
88                 onCreate({
89                     email: '',
90                     name: '',
91                     uuid: this.state.value,
92                 });
93             }
94         }
95
96         handleSelect = ({ email, firstName, lastName, uuid }: UserResource) => {
97             const { onSelect = noop } = this.props;
98             this.setState({ value: '', suggestions: [] });
99             onSelect({
100                 email,
101                 name: `${firstName} ${lastName}`,
102                 uuid,
103             });
104         }
105
106         handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
107             this.setState({ value: event.target.value }, this.getSuggestions);
108         }
109
110         getSuggestions = debounce(() => this.props.dispatch<any>(this.requestSuggestions), 500);
111
112         requestSuggestions = async (_: void, __: void, { userService }: ServiceRepository) => {
113             const { value } = this.state;
114             const filters = new FilterBuilder()
115                 .addILike('email', value)
116                 .getFilters();
117             const { items } = await userService.list({ filters, limit: 5 });
118             this.setState({ suggestions: items });
119         }
120
121     });