aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/groups/components
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main/js/apps/groups/components')
-rw-r--r--server/sonar-web/src/main/js/apps/groups/components/EditMembersModal.tsx168
-rw-r--r--server/sonar-web/src/main/js/apps/groups/components/Members.tsx78
2 files changed, 90 insertions, 156 deletions
diff --git a/server/sonar-web/src/main/js/apps/groups/components/EditMembersModal.tsx b/server/sonar-web/src/main/js/apps/groups/components/EditMembersModal.tsx
index 5c27d2f3775..875bade13e3 100644
--- a/server/sonar-web/src/main/js/apps/groups/components/EditMembersModal.tsx
+++ b/server/sonar-web/src/main/js/apps/groups/components/EditMembersModal.tsx
@@ -34,95 +34,56 @@ interface Props {
onClose: () => void;
}
-interface State {
- lastSearchParams?: SelectListSearchParams;
- needToReload: boolean;
- users: UserSelected[];
- usersTotalCount?: number;
- selectedUsers: string[];
-}
-
-export default class EditMembersModal extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
-
- this.state = {
- needToReload: false,
- users: [],
- selectedUsers: [],
- };
- }
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- fetchUsers = (searchParams: SelectListSearchParams) =>
+export default function EditMembersModal(props: Readonly<Props>) {
+ const [needToReload, setNeedToReload] = React.useState(false);
+ const [users, setUsers] = React.useState<UserSelected[]>([]);
+ const [selectedUsers, setSelectedUsers] = React.useState<string[]>([]);
+ const [usersTotalCount, setUsersTotalCount] = React.useState<number | undefined>(undefined);
+ const [lastSearchParams, setLastSearchParams] = React.useState<
+ SelectListSearchParams | undefined
+ >(undefined);
+
+ const { group } = props;
+ const modalHeader = translate('users.update');
+
+ const fetchUsers = (searchParams: SelectListSearchParams) =>
getUsersInGroup({
- name: this.props.group.name,
+ name: props.group.name,
p: searchParams.page,
ps: searchParams.pageSize,
q: searchParams.query !== '' ? searchParams.query : undefined,
selected: searchParams.filter,
}).then((data) => {
- if (this.mounted) {
- this.setState((prevState) => {
- const more = searchParams.page != null && searchParams.page > 1;
-
- const users = more ? [...prevState.users, ...data.users] : data.users;
- const newSelectedUsers = data.users
- .filter((user) => user.selected)
- .map((user) => user.login);
- const selectedUsers = more
- ? [...prevState.selectedUsers, ...newSelectedUsers]
- : newSelectedUsers;
-
- return {
- needToReload: false,
- lastSearchParams: searchParams,
- loading: false,
- users,
- usersTotalCount: data.paging.total,
- selectedUsers,
- };
- });
- }
+ const more = searchParams.page != null && searchParams.page > 1;
+
+ setUsers(more ? [...users, ...data.users] : data.users);
+ const newSelectedUsers = data.users.filter((user) => user.selected).map((user) => user.login);
+ setSelectedUsers(more ? [...selectedUsers, ...newSelectedUsers] : newSelectedUsers);
+ setNeedToReload(false);
+ setLastSearchParams(searchParams);
+ setUsersTotalCount(data.paging.total);
});
- handleSelect = (login: string) =>
+ const handleSelect = (login: string) =>
addUserToGroup({
- name: this.props.group.name,
+ name: group.name,
login,
}).then(() => {
- if (this.mounted) {
- this.setState((state: State) => ({
- needToReload: true,
- selectedUsers: [...state.selectedUsers, login],
- }));
- }
+ setNeedToReload(true);
+ setSelectedUsers([...selectedUsers, login]);
});
- handleUnselect = (login: string) =>
+ const handleUnselect = (login: string) =>
removeUserFromGroup({
- name: this.props.group.name,
+ name: group.name,
login,
}).then(() => {
- if (this.mounted) {
- this.setState((state: State) => ({
- needToReload: true,
- selectedUsers: without(state.selectedUsers, login),
- }));
- }
+ setNeedToReload(true);
+ setSelectedUsers(without(selectedUsers, login));
});
- renderElement = (login: string): React.ReactNode => {
- const user = find(this.state.users, { login });
+ const renderElement = (login: string): React.ReactNode => {
+ const user = find(users, { login });
return (
<div className="select-list-list-item">
{user === undefined ? (
@@ -138,40 +99,35 @@ export default class EditMembersModal extends React.PureComponent<Props, State>
);
};
- render() {
- const modalHeader = translate('users.update');
- return (
- <Modal
- className="group-menbers-modal"
- contentLabel={modalHeader}
- onRequestClose={this.props.onClose}
- >
- <header className="modal-head">
- <h2>{modalHeader}</h2>
- </header>
-
- <div className="modal-body modal-container">
- <SelectList
- elements={this.state.users.map((user) => user.login)}
- elementsTotalCount={this.state.usersTotalCount}
- needToReload={
- this.state.needToReload &&
- this.state.lastSearchParams &&
- this.state.lastSearchParams.filter !== SelectListFilter.All
- }
- onSearch={this.fetchUsers}
- onSelect={this.handleSelect}
- onUnselect={this.handleUnselect}
- renderElement={this.renderElement}
- selectedElements={this.state.selectedUsers}
- withPaging
- />
- </div>
+ 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">
+ <SelectList
+ elements={users.map((user) => user.login)}
+ elementsTotalCount={usersTotalCount}
+ needToReload={
+ needToReload && lastSearchParams && lastSearchParams.filter !== SelectListFilter.All
+ }
+ onSearch={fetchUsers}
+ onSelect={handleSelect}
+ onUnselect={handleUnselect}
+ renderElement={renderElement}
+ selectedElements={selectedUsers}
+ withPaging
+ />
+ </div>
- <footer className="modal-foot">
- <ResetButtonLink onClick={this.props.onClose}>{translate('done')}</ResetButtonLink>
- </footer>
- </Modal>
- );
- }
+ <footer className="modal-foot">
+ <ResetButtonLink onClick={props.onClose}>{translate('done')}</ResetButtonLink>
+ </footer>
+ </Modal>
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/groups/components/Members.tsx b/server/sonar-web/src/main/js/apps/groups/components/Members.tsx
index d1d733f5542..64814df42f7 100644
--- a/server/sonar-web/src/main/js/apps/groups/components/Members.tsx
+++ b/server/sonar-web/src/main/js/apps/groups/components/Members.tsx
@@ -31,58 +31,36 @@ interface Props {
onEdit: () => void;
}
-interface State {
- modal: boolean;
-}
-
-export default class Members extends React.PureComponent<Props, State> {
- mounted = false;
- state: State = { modal: false };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleMembersClick = () => {
- this.setState({ modal: true });
- };
+export default function Members(props: Readonly<Props>) {
+ const [openModal, setOpenModal] = React.useState(false);
+ const { isManaged, group } = props;
- handleModalClose = () => {
- const { isManaged, group } = this.props;
- if (this.mounted) {
- this.setState({ modal: false });
- if (!isManaged && !group.default) {
- this.props.onEdit();
- }
+ const handleModalClose = () => {
+ setOpenModal(false);
+ if (!isManaged && !group.default) {
+ props.onEdit();
}
};
- render() {
- const { isManaged, group } = this.props;
- return (
- <>
- <ButtonIcon
- aria-label={translateWithParameters(
- isManaged || group.default ? 'groups.users.view' : 'groups.users.edit',
- group.name,
- )}
- className="button-small little-spacer-left little-padded"
- onClick={this.handleMembersClick}
- title={translateWithParameters('groups.users.edit', group.name)}
- >
- <BulletListIcon />
- </ButtonIcon>
- {this.state.modal &&
- (isManaged || group.default ? (
- <ViewMembersModal isManaged={isManaged} group={group} onClose={this.handleModalClose} />
- ) : (
- <EditMembersModal group={group} onClose={this.handleModalClose} />
- ))}
- </>
- );
- }
+ return (
+ <>
+ <ButtonIcon
+ aria-label={translateWithParameters(
+ isManaged || group.default ? 'groups.users.view' : 'groups.users.edit',
+ group.name,
+ )}
+ className="button-small little-spacer-left little-padded"
+ onClick={() => setOpenModal(true)}
+ title={translateWithParameters('groups.users.edit', group.name)}
+ >
+ <BulletListIcon />
+ </ButtonIcon>
+ {openModal &&
+ (isManaged || group.default ? (
+ <ViewMembersModal isManaged={isManaged} group={group} onClose={handleModalClose} />
+ ) : (
+ <EditMembersModal group={group} onClose={handleModalClose} />
+ ))}
+ </>
+ );
}