UserPicker.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // Libraries
  2. import React, { Component } from 'react';
  3. import _ from 'lodash';
  4. // Components
  5. import { AsyncSelect } from '@grafana/ui';
  6. // Utils & Services
  7. import { debounce } from 'lodash';
  8. import { getBackendSrv } from 'app/core/services/backend_srv';
  9. // Types
  10. import { User } from 'app/types';
  11. export interface Props {
  12. onSelected: (user: User) => void;
  13. className?: string;
  14. }
  15. export interface State {
  16. isLoading: boolean;
  17. }
  18. export class UserPicker extends Component<Props, State> {
  19. debouncedSearch: any;
  20. constructor(props) {
  21. super(props);
  22. this.state = { isLoading: false };
  23. this.search = this.search.bind(this);
  24. this.debouncedSearch = debounce(this.search, 300, {
  25. leading: true,
  26. trailing: true,
  27. });
  28. }
  29. search(query?: string) {
  30. const backendSrv = getBackendSrv();
  31. this.setState({ isLoading: true });
  32. if (_.isNil(query)) {
  33. query = '';
  34. }
  35. return backendSrv
  36. .get(`/api/org/users?query=${query}&limit=10`)
  37. .then(result => {
  38. return result.map(user => ({
  39. id: user.userId,
  40. value: user.userId,
  41. label: user.login === user.email ? user.login : `${user.login} - ${user.email}`,
  42. imgUrl: user.avatarUrl,
  43. login: user.login,
  44. }));
  45. })
  46. .finally(() => {
  47. this.setState({ isLoading: false });
  48. });
  49. }
  50. render() {
  51. const { className, onSelected } = this.props;
  52. const { isLoading } = this.state;
  53. return (
  54. <div className="user-picker">
  55. <AsyncSelect
  56. className={className}
  57. isLoading={isLoading}
  58. defaultOptions={true}
  59. loadOptions={this.debouncedSearch}
  60. onChange={onSelected}
  61. placeholder="Select user"
  62. noOptionsMessage={() => 'No users found'}
  63. />
  64. </div>
  65. );
  66. }
  67. }