aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/groups/components/ViewMembersModal.tsx
blob: 76d326fad4950536dd0ef4974e0f49fa799ea3e4 (plain)
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
114
115
116
117
118
119
/*
 * SonarQube
 * Copyright (C) 2009-2023 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
import { DeferredSpinner } from 'design-system/lib';
import * as React from 'react';
import { getUsersInGroup } from '../../../api/user_groups';
import ListFooter from '../../../components/controls/ListFooter';
import Modal from '../../../components/controls/Modal';
import SearchBox from '../../../components/controls/SearchBox';
import { SelectListFilter } from '../../../components/controls/SelectList';
import { ResetButtonLink } from '../../../components/controls/buttons';
import { translate } from '../../../helpers/l10n';
import { Group, UserGroupMember } from '../../../types/types';

interface Props {
  isManaged: boolean;
  group: Group;
  onClose: () => void;
}

export default function ViewMembersModal(props: Props) {
  const { isManaged, group } = props;

  const [loading, setLoading] = React.useState(false);
  const [page, setPage] = React.useState(1);
  const [query, setQuery] = React.useState<string>();
  const [total, setTotal] = React.useState<number>();
  const [users, setUsers] = React.useState<UserGroupMember[]>([]);

  React.useEffect(() => {
    (async () => {
      setLoading(true);
      const data = await getUsersInGroup({
        name: group.name,
        p: page,
        q: query,
        selected: SelectListFilter.Selected,
      });
      if (page > 1) {
        setUsers([...users, ...data.users]);
      } else {
        setUsers(data.users);
      }
      setTotal(data.paging.total);
      setLoading(false);
    })();
  }, [query, page]);

  const modalHeader = translate('users.list');
  return (
    <Modal
      className="group-menbers-modal"
      contentLabel={modalHeader}
      onRequestClose={props.onClose}
    >
      <header className="modal-head">
        <h2>{modalHeader}</h2>
      </header>

      <div className="modal-body modal-container">
        <SearchBox
          className="view-search-box"
          loading={loading}
          onChange={(q) => {
            setQuery(q);
            setPage(1);
          }}
          placeholder={translate('search_verb')}
          value={query}
        />
        <div className="select-list-list-container spacer-top">
          <DeferredSpinner loading={loading}>
            <ul className="menu">
              {users.map((user) => (
                <li key={user.login} className="display-flex-center">
                  <span className="little-spacer-left width-100">
                    <span className="select-list-list-item display-flex-center display-flex-space-between">
                      <span className="spacer-right">
                        {user.name}
                        <br />
                        <span className="note">{user.login}</span>
                      </span>
                      {!user.managed && isManaged && (
                        <span className="badge">{translate('local')}</span>
                      )}
                    </span>
                  </span>
                </li>
              ))}
            </ul>
          </DeferredSpinner>
        </div>
        {total !== undefined && (
          <ListFooter count={users.length} loadMore={() => setPage((p) => p + 1)} total={total} />
        )}
      </div>

      <footer className="modal-foot">
        <ResetButtonLink onClick={props.onClose}>{translate('done')}</ResetButtonLink>
      </footer>
    </Modal>
  );
}