diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2018-02-26 16:49:40 +0100 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2018-02-27 14:44:23 +0100 |
commit | 2bc87f33684239adbfa746db78ca73290688adaa (patch) | |
tree | e4f04535c3733d28f00da796abfe9e6143a59805 /server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js | |
parent | 2947082abde85a0e16ce65da155e1e9d9d7cb78d (diff) | |
download | sonarqube-2bc87f33684239adbfa746db78ca73290688adaa.tar.gz sonarqube-2bc87f33684239adbfa746db78ca73290688adaa.zip |
SONAR-10047 Use SearchSelect for tags in Bulk Issue Change
Diffstat (limited to 'server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js')
-rw-r--r-- | server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js | 102 |
1 files changed, 56 insertions, 46 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js index b9f7ef9014f..e8f9b22fd0c 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js +++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.js @@ -23,7 +23,7 @@ import { pickBy, sortBy } from 'lodash'; import SearchSelect from '../../../components/controls/SearchSelect'; import Checkbox from '../../../components/controls/Checkbox'; import Modal from '../../../components/controls/Modal'; -import Select, { Creatable } from '../../../components/controls/Select'; +import Select from '../../../components/controls/Select'; import Tooltip from '../../../components/controls/Tooltip'; import MarkdownTips from '../../../components/common/MarkdownTips'; import SeverityHelper from '../../../components/shared/SeverityHelper'; @@ -49,21 +49,21 @@ type Props = {| /*:: type State = {| + initialTags: Array<{ label:string, value: string }>, issues: Array<Issue>, // used for initial loading of issues loading: boolean, paging?: Paging, // used when submitting a form submitting: boolean, - tags?: Array<string>, // form fields - addTags?: Array<string>, - assignee?: string, + addTags?: Array<{ label: string, value: string }>, + assignee?: { avatar?: string, label: string, value: string }, comment?: string, notifications?: boolean, organization?: string, - removeTags?: Array<string>, + removeTags?: Array<{ label: string, value: string }>, severity?: string, transition?: string, type?: string @@ -84,7 +84,7 @@ export default class BulkChangeModal extends React.PureComponent { if (props.organization && !organization) { organization = props.organization.key; } - this.state = { issues: [], loading: true, submitting: false, organization }; + this.state = { initialTags: [], issues: [], loading: true, submitting: false, organization }; } componentDidMount() { @@ -93,16 +93,19 @@ export default class BulkChangeModal extends React.PureComponent { Promise.all([ this.loadIssues(), searchIssueTags({ organization: this.state.organization }) - ]).then(([issues, tags]) => { - if (this.mounted) { - this.setState({ - issues: issues.issues, - loading: false, - paging: issues.paging, - tags - }); - } - }); + ]).then( + ([issues, tags]) => { + if (this.mounted) { + this.setState({ + initialTags: tags.map(tag => ({ label: tag, value: tag })), + issues: issues.issues, + loading: false, + paging: issues.paging + }); + } + }, + () => {} + ); } componentWillUnmount() { @@ -142,12 +145,26 @@ export default class BulkChangeModal extends React.PureComponent { this.props.onClose(); }; - handleAssigneeSearch = (query /*: string */) => searchAssignees(query, this.state.organization); + handleAssigneeSearch = (query /*: string */) => { + return searchAssignees(query, this.state.organization); + }; - handleAssigneeSelect = (assignee /*: string */) => { + handleAssigneeSelect = (assignee /*: { avatar?: string, label: string, value: string } */) => { this.setState({ assignee }); }; + handleTagsSearch = (query /*: string */) => { + return searchIssueTags({ organization: this.state.organization, q: query }).then(tags => + tags.map(tag => ({ label: tag, value: tag })) + ); + }; + + handleTagsSelect = (field /*: string */) => ( + options /*: Array<{ label: string, value: string }> */ + ) => { + this.setState({ [field]: options }); + }; + handleFieldCheck = (field /*: string */) => (checked /*: boolean */) => { if (!checked) { this.setState({ [field]: undefined }); @@ -164,28 +181,24 @@ export default class BulkChangeModal extends React.PureComponent { this.setState({ [field]: value }); }; - handleMultiSelectFieldChange = (field /*: string */) => ( - options /*: Array<{ value: string }> */ - ) => { - this.setState({ [field]: options.map(option => option.value) }); - }; - handleSubmit = (e /*: Event */) => { e.preventDefault(); + /* eslint-disable camelcase */ const query = pickBy( { - assign: this.state.assignee, - set_type: this.state.type, - set_severity: this.state.severity, - add_tags: this.state.addTags && this.state.addTags.join(), - remove_tags: this.state.removeTags && this.state.removeTags.join(), - do_transition: this.state.transition, + add_tags: this.state.addTags && this.state.addTags.map(t => t.value).join(), + assign: this.state.assignee && this.state.assignee.value, comment: this.state.comment, - sendNotifications: this.state.notifications + do_transition: this.state.transition, + remove_tags: this.state.removeTags && this.state.removeTags.map(t => t.value).join(), + sendNotifications: this.state.notifications, + set_severity: this.state.severity, + set_type: this.state.type }, // remove null, but keep empty string x => x != null ); + /* eslint-enable camelcase */ const issueKeys = this.state.issues.map(issue => issue.key); this.setState({ submitting: true }); @@ -320,8 +333,8 @@ export default class BulkChangeModal extends React.PureComponent { clearable={false} id="type" onChange={this.handleSelectFieldChange('type')} - options={options} optionRenderer={optionRenderer} + options={options} searchable={false} value={this.state.type} valueRenderer={optionRenderer} @@ -349,8 +362,8 @@ export default class BulkChangeModal extends React.PureComponent { clearable={false} id="severity" onChange={this.handleSelectFieldChange('severity')} - options={options} optionRenderer={option => <SeverityHelper severity={option.value} />} + options={options} searchable={false} value={this.state.severity} valueRenderer={option => <SeverityHelper severity={option.value} />} @@ -361,28 +374,25 @@ export default class BulkChangeModal extends React.PureComponent { }; renderTagsField = (field /*: string */, label /*: string */, allowCreate /*: boolean */) => { + const { initialTags } = this.state; const affected /*: number */ = this.state.issues.filter(hasAction('set_tags')).length; - if (this.state.tags == null || affected === 0) { + if (initialTags == null || affected === 0) { return null; } - const Component = allowCreate ? Creatable : Select; - - const options = [...this.state.tags, ...(this.state[field] || [])].map(tag => ({ - label: tag, - value: tag - })); - const input = ( - <Component - clearable={false} + <SearchSelect + canCreate={allowCreate} + defaultOptions={this.state.initialTags} id={field} + minimumQueryLength={0} multi={true} - onChange={this.handleMultiSelectFieldChange(field)} - options={options} + onMultiSelect={this.handleTagsSelect(field)} + onSearch={this.handleTagsSearch} promptTextCreator={promptCreateTag} - searchable={true} + renderOption={this.renderAssigneeOption} + resetOnBlur={false} value={this.state[field]} /> ); |