diff options
author | Pascal Mugnier <pascal.mugnier@sonarsource.com> | 2018-03-16 16:21:29 +0100 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-03-22 12:37:48 +0100 |
commit | af09abd297eee6694b088437f7f33bea210b82f0 (patch) | |
tree | 6aba521089c4228b464154873ca250042560cfe7 /server/sonar-web/src/main/js/apps/groups | |
parent | 8335168f11c4b8b6bd905e3a883c001352ab234d (diff) | |
download | sonarqube-af09abd297eee6694b088437f7f33bea210b82f0.tar.gz sonarqube-af09abd297eee6694b088437f7f33bea210b82f0.zip |
Rewrite SelectList component in React on Quality Page (#3152)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/groups')
-rw-r--r-- | server/sonar-web/src/main/js/apps/groups/components/EditMembers.tsx | 95 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/apps/groups/components/__tests__/__snapshots__/EditMembers-test.tsx.snap | 9 |
2 files changed, 70 insertions, 34 deletions
diff --git a/server/sonar-web/src/main/js/apps/groups/components/EditMembers.tsx b/server/sonar-web/src/main/js/apps/groups/components/EditMembers.tsx index 9b62320e86b..ee0fc20aacc 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/EditMembers.tsx +++ b/server/sonar-web/src/main/js/apps/groups/components/EditMembers.tsx @@ -18,14 +18,19 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import * as escapeHtml from 'escape-html'; +import { find, without } from 'lodash'; import { Group } from '../../../app/types'; import Modal from '../../../components/controls/Modal'; import BulletListIcon from '../../../components/icons-components/BulletListIcon'; -import SelectList from '../../../components/SelectList'; +import SelectList, { Filter } from '../../../components/SelectList/SelectList'; import { ButtonIcon, ResetButtonLink } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { + getUsersInGroup, + addUserToGroup, + removeUserFromGroup, + GroupUser +} from '../../../api/user_groups'; interface Props { group: Group; @@ -35,14 +40,17 @@ interface Props { interface State { modal: boolean; + users: GroupUser[]; + selectedUsers: string[]; } export default class EditMembers extends React.PureComponent<Props, State> { container?: HTMLElement | null; mounted = false; - state: State = { modal: false }; + state: State = { modal: false, users: [], selectedUsers: [] }; componentDidMount() { + this.handleSearch('', Filter.Selected); this.mounted = true; } @@ -50,13 +58,49 @@ export default class EditMembers extends React.PureComponent<Props, State> { this.mounted = false; } - handleMembersClick = () => { - this.setState({ modal: true }, () => { - // defer rendering of the SelectList to make sure we have `ref` assigned - setTimeout(this.renderSelectList, 0); + handleSearch = (query: string, selected: Filter) => { + return getUsersInGroup({ + id: this.props.group.id, + organization: this.props.organization, + ps: 100, + q: query !== '' ? query : undefined, + selected + }).then(data => { + this.setState({ + users: data.users, + selectedUsers: data.users.filter(user => user.selected).map(user => user.login) + }); + }); + }; + + handleSelect = (login: string) => { + return addUserToGroup({ + name: this.props.group.name, + login, + organization: this.props.organization + }).then(() => { + this.setState((state: State) => ({ + selectedUsers: [...state.selectedUsers, login] + })); + }); + }; + + handleUnselect = (login: string) => { + return removeUserFromGroup({ + name: this.props.group.name, + login, + organization: this.props.organization + }).then(() => { + this.setState((state: State) => ({ + selectedUsers: without(state.selectedUsers, login) + })); }); }; + handleMembersClick = () => { + this.setState({ modal: true }); + }; + handleModalClose = () => { if (this.mounted) { this.setState({ modal: false }); @@ -64,29 +108,9 @@ export default class EditMembers extends React.PureComponent<Props, State> { } }; - renderSelectList = () => { - if (this.container) { - const extra = { name: this.props.group.name, organization: this.props.organization }; - - /* eslint-disable no-new */ - new SelectList({ - el: this.container, - width: '100%', - readOnly: false, - focusSearch: false, - dangerouslyUnescapedHtmlFormat: (item: { login: string; name: string }) => - `${escapeHtml(item.name)}<br><span class="note">${escapeHtml(item.login)}</span>`, - queryParam: 'q', - searchUrl: getBaseUrl() + '/api/user_groups/users?ps=100&id=' + this.props.group.id, - selectUrl: getBaseUrl() + '/api/user_groups/add_user', - deselectUrl: getBaseUrl() + '/api/user_groups/remove_user', - extra, - selectParameter: 'login', - selectParameterValue: 'login', - parse: (r: any) => r.users - }); - /* eslint-enable no-new */ - } + renderElement = (login: string): React.ReactNode => { + const user = find(this.state.users, { login }); + return user === undefined ? login : user.login; }; render() { @@ -104,7 +128,14 @@ export default class EditMembers extends React.PureComponent<Props, State> { </header> <div className="modal-body"> - <div id="groups-users" ref={node => (this.container = node)} /> + <SelectList + elements={this.state.users.map(user => user.login)} + onSearch={this.handleSearch} + onSelect={this.handleSelect} + onUnselect={this.handleUnselect} + renderElement={this.renderElement} + selectedElements={this.state.selectedUsers} + /> </div> <footer className="modal-foot"> diff --git a/server/sonar-web/src/main/js/apps/groups/components/__tests__/__snapshots__/EditMembers-test.tsx.snap b/server/sonar-web/src/main/js/apps/groups/components/__tests__/__snapshots__/EditMembers-test.tsx.snap index 230836640f5..a0b1f679d14 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/__tests__/__snapshots__/EditMembers-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/groups/components/__tests__/__snapshots__/EditMembers-test.tsx.snap @@ -33,8 +33,13 @@ exports[`should edit members 2`] = ` <div className="modal-body" > - <div - id="groups-users" + <SelectList + elements={Array []} + onSearch={[Function]} + onSelect={[Function]} + onUnselect={[Function]} + renderElement={[Function]} + selectedElements={Array []} /> </div> <footer |