]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-15275 Disable issues bulk change form if no change configured
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Fri, 13 Aug 2021 08:52:47 +0000 (10:52 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 13 Aug 2021 20:03:54 +0000 (20:03 +0000)
server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
server/sonar-web/src/main/js/apps/issues/components/__tests__/BulkChangeModal-test.tsx
server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/BulkChangeModal-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a98face63c475e1e8aede4a57c73e907a4d1d501..5baaba4ab743c7e1fa2cf6df62af8cbee246f125 100644 (file)
@@ -27,6 +27,7 @@ import Modal from 'sonar-ui-common/components/controls/Modal';
 import Radio from 'sonar-ui-common/components/controls/Radio';
 import SearchSelect from 'sonar-ui-common/components/controls/SearchSelect';
 import Select from 'sonar-ui-common/components/controls/Select';
+import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
 import IssueTypeIcon from 'sonar-ui-common/components/icons/IssueTypeIcon';
 import { Alert } from 'sonar-ui-common/components/ui/Alert';
 import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
@@ -255,6 +256,19 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
     }));
   }
 
+  canSubmit = () => {
+    const { addTags, assignee, removeTags, severity, transition, type } = this.state;
+
+    return Boolean(
+      (addTags && addTags.length > 0) ||
+        (removeTags && removeTags.length > 0) ||
+        assignee ||
+        severity ||
+        transition ||
+        type
+    );
+  };
+
   renderLoading = () => (
     <div>
       <div className="modal-head">
@@ -487,6 +501,7 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
     const { issues, paging, submitting } = this.state;
 
     const limitReached = paging && paging.total > MAX_PAGE_SIZE;
+    const canSubmit = this.canSubmit();
 
     return (
       <form id="bulk-change-form" onSubmit={this.handleSubmit}>
@@ -520,9 +535,13 @@ export default class BulkChangeModal extends React.PureComponent<Props, State> {
 
         <div className="modal-foot">
           {submitting && <i className="spinner spacer-right" />}
-          <SubmitButton disabled={submitting || issues.length === 0} id="bulk-change-submit">
-            {translate('apply')}
-          </SubmitButton>
+          <Tooltip overlay={!canSubmit ? translate('issue_bulk_change.no_change_selected') : null}>
+            <SubmitButton
+              disabled={!canSubmit || submitting || issues.length === 0}
+              id="bulk-change-submit">
+              {translate('apply')}
+            </SubmitButton>
+          </Tooltip>
           <ResetButtonLink onClick={this.props.onClose}>{translate('cancel')}</ResetButtonLink>
         </div>
       </form>
index 9bc940e960cd91658b5b175b4f3f7d6ededa2c26..ec7b73572db1dd5c657237a3ce797a83cfc51ddd 100644 (file)
@@ -19,7 +19,9 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
+import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
+import Select from 'sonar-ui-common/components/controls/Select';
+import { change, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
 import { searchIssueTags } from '../../../../api/issues';
 import { mockIssue } from '../../../../helpers/testMocks';
 import BulkChangeModal, { MAX_PAGE_SIZE } from '../BulkChangeModal';
@@ -99,6 +101,32 @@ it('should properly handle the search for tags', async () => {
   expect(searchIssueTags).toBeCalled();
 });
 
+it('should disable the submit button unless some change is configured', async () => {
+  const wrapper = getWrapper([mockIssue(false, { actions: ['set_severity', 'comment'] })]);
+  await waitAndUpdate(wrapper);
+
+  return new Promise<void>((resolve, reject) => {
+    expect(wrapper.find(SubmitButton).props().disabled).toBe(true);
+
+    // Setting a comment is not sufficient; some other change must occur.
+    change(wrapper.find('#comment'), 'Some comment');
+    expect(wrapper.find(SubmitButton).props().disabled).toBe(true);
+
+    const { onChange } = wrapper
+      .find(Select)
+      .at(0)
+      .props();
+    if (!onChange) {
+      reject();
+      return;
+    }
+
+    onChange({ value: 'foo' });
+    expect(wrapper.find(SubmitButton).props().disabled).toBe(false);
+    resolve();
+  });
+});
+
 const getWrapper = (issues: T.Issue[]) => {
   return shallow<BulkChangeModal>(
     <BulkChangeModal
index e8fb769f86266a2189ba657abe7f81007d0162bc..88ef96d3cebc69f3dced0150ae007e99b3d64131 100644 (file)
@@ -29,12 +29,16 @@ exports[`should display error message when no issues available 1`] = `
     <div
       className="modal-foot"
     >
-      <SubmitButton
-        disabled={true}
-        id="bulk-change-submit"
+      <Tooltip
+        overlay="issue_bulk_change.no_change_selected"
       >
-        apply
-      </SubmitButton>
+        <SubmitButton
+          disabled={true}
+          id="bulk-change-submit"
+        >
+          apply
+        </SubmitButton>
+      </Tooltip>
       <ResetButtonLink
         onClick={[Function]}
       >
@@ -83,12 +87,16 @@ exports[`should display form when issues are present 1`] = `
     <div
       className="modal-foot"
     >
-      <SubmitButton
-        disabled={false}
-        id="bulk-change-submit"
+      <Tooltip
+        overlay="issue_bulk_change.no_change_selected"
       >
-        apply
-      </SubmitButton>
+        <SubmitButton
+          disabled={true}
+          id="bulk-change-submit"
+        >
+          apply
+        </SubmitButton>
+      </Tooltip>
       <ResetButtonLink
         onClick={[Function]}
       >
index ec14f5372d2a5798a139d16910c4df0017dcc3e7..e0d6b6463e1ecda5f70f40961acd6a4192666eb0 100644 (file)
@@ -975,6 +975,7 @@ issue_bulk_change.comment.help=This comment will be applied only to issues that
 issue_bulk_change.max_issues_reached=There are more issues available than can be treated by a single bulk action. Your changes will only be applied to the first {max} issues.
 issue_bulk_change.x_issues={0} issues
 issue_bulk_change.no_match=There is no issue matching your filter selection
+issue_bulk_change.no_change_selected=Make at least 1 change (e.g.: change assignee) in order to update the selected issues.
 
 
 #------------------------------------------------------------------------------