]> source.dussan.org Git - sonarqube.git/blob
6ff3a5a40e5a2422fcd0cdd790aa94ebf69b4bcd
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2021 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 import * as classNames from 'classnames';
21 import * as React from 'react';
22 import { DropdownOverlay } from 'sonar-ui-common/components/controls/Dropdown';
23 import SearchBox from 'sonar-ui-common/components/controls/SearchBox';
24 import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
25 import { PopupPlacement } from 'sonar-ui-common/components/ui/popups';
26 import { translate } from 'sonar-ui-common/helpers/l10n';
27 import Avatar from '../../../../components/ui/Avatar';
28 import './AssigneeSelection.css';
29
30 export interface HotspotAssigneeSelectRendererProps {
31   highlighted?: T.UserActive;
32   loading: boolean;
33   onKeyDown: (event: React.KeyboardEvent) => void;
34   onSearch: (query: string) => void;
35   onSelect: (user: T.UserActive) => void;
36   open: boolean;
37   query?: string;
38   suggestedUsers?: T.UserActive[];
39 }
40
41 export default function AssigneeSelectionRenderer(props: HotspotAssigneeSelectRendererProps) {
42   const { highlighted, loading, open, query, suggestedUsers } = props;
43   return (
44     <>
45       <div className="display-flex-center">
46         <SearchBox
47           autoFocus={true}
48           onChange={props.onSearch}
49           onKeyDown={props.onKeyDown}
50           placeholder={translate('hotspots.assignee.select_user')}
51           value={query}
52         />
53
54         {loading && <DeferredSpinner className="spacer-left" />}
55       </div>
56
57       {!loading && open && (
58         <div className="position-relative">
59           <DropdownOverlay noPadding={true} placement={PopupPlacement.BottomLeft}>
60             {suggestedUsers && suggestedUsers.length > 0 ? (
61               <ul className="hotspot-assignee-search-results">
62                 {suggestedUsers.map(suggestion => (
63                   <li
64                     className={classNames('padded', {
65                       active: highlighted && highlighted.login === suggestion.login
66                     })}
67                     key={suggestion.login}
68                     onClick={() => props.onSelect(suggestion)}>
69                     <Avatar
70                       className="spacer-right"
71                       hash={suggestion.avatar}
72                       name={suggestion.name}
73                       size={16}
74                     />
75                     {suggestion.name}
76                   </li>
77                 ))}
78               </ul>
79             ) : (
80               <div className="padded">{translate('no_results')}</div>
81             )}
82           </DropdownOverlay>
83         </div>
84       )}
85     </>
86   );
87 }