diff options
author | Wouter Admiraal <wouter.admiraal@sonarsource.com> | 2019-08-26 11:51:25 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-09-10 20:21:01 +0200 |
commit | ac2f2bffa26573347670e0391b036d8d2319803c (patch) | |
tree | 5b8bfe177fbe3e6eb581371e3f392bff822f7ede | |
parent | 1addb9c9c04d8bf616a80c03c7f3f06b855fe0fb (diff) | |
download | sonarqube-ac2f2bffa26573347670e0391b036d8d2319803c.tar.gz sonarqube-ac2f2bffa26573347670e0391b036d8d2319803c.zip |
SONAR-12414 Prevent opening an issue if click happens inside a changelog or comment dropdown
4 files changed, 248 insertions, 232 deletions
diff --git a/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.tsx b/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.tsx index 002fbe02777..aacb92f283f 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.tsx +++ b/server/sonar-web/src/main/js/components/issue/popups/ChangelogPopup.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import ClickEventBoundary from 'sonar-ui-common/components/controls/ClickEventBoundary'; import { DropdownOverlay } from 'sonar-ui-common/components/controls/Dropdown'; import { PopupPlacement } from 'sonar-ui-common/components/ui/popups'; import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; @@ -63,44 +64,46 @@ export default class ChangelogPopup extends React.PureComponent<Props, State> { const { author } = issue; return ( <DropdownOverlay placement={PopupPlacement.BottomRight}> - <div className="menu is-container issue-changelog"> - <table className="spaced"> - <tbody> - <tr> - <td className="thin text-left text-top nowrap"> - <DateTimeFormatter date={issue.creationDate} /> - </td> - <td className="text-left text-top"> - {author ? `${translate('created_by')} ${author}` : translate('created')} - </td> - </tr> - - {this.state.changelog.map((item, idx) => ( - <tr key={idx}> + <ClickEventBoundary> + <div className="menu is-container issue-changelog"> + <table className="spaced"> + <tbody> + <tr> <td className="thin text-left text-top nowrap"> - <DateTimeFormatter date={item.creationDate} /> + <DateTimeFormatter date={issue.creationDate} /> </td> <td className="text-left text-top"> - <p> - <Avatar - className="little-spacer-right" - hash={item.avatar} - name={(item.isUserActive && item.userName) || item.user} - size={16} - /> - {item.isUserActive - ? item.userName || item.user - : translateWithParameters('user.x_deleted', item.user)} - </p> - {item.diffs.map(diff => ( - <IssueChangelogDiff diff={diff} key={diff.key} /> - ))} + {author ? `${translate('created_by')} ${author}` : translate('created')} </td> </tr> - ))} - </tbody> - </table> - </div> + + {this.state.changelog.map((item, idx) => ( + <tr key={idx}> + <td className="thin text-left text-top nowrap"> + <DateTimeFormatter date={item.creationDate} /> + </td> + <td className="text-left text-top"> + <p> + <Avatar + className="little-spacer-right" + hash={item.avatar} + name={(item.isUserActive && item.userName) || item.user} + size={16} + /> + {item.isUserActive + ? item.userName || item.user + : translateWithParameters('user.x_deleted', item.user)} + </p> + {item.diffs.map(diff => ( + <IssueChangelogDiff diff={diff} key={diff.key} /> + ))} + </td> + </tr> + ))} + </tbody> + </table> + </div> + </ClickEventBoundary> </DropdownOverlay> ); } diff --git a/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx b/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx index aa5e411aa29..22f5f5f184c 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx +++ b/server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; import { Button, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons'; +import ClickEventBoundary from 'sonar-ui-common/components/controls/ClickEventBoundary'; import { DropdownOverlay } from 'sonar-ui-common/components/controls/Dropdown'; import { PopupPlacement } from 'sonar-ui-common/components/ui/popups'; import { translate } from 'sonar-ui-common/helpers/l10n'; @@ -73,35 +74,39 @@ export default class CommentPopup extends React.PureComponent<Props, State> { const { comment, autoTriggered } = this.props; return ( <DropdownOverlay placement={this.props.placement}> - <div className="issue-comment-bubble-popup"> - <div className="issue-comment-form-text"> - <textarea - autoFocus={true} - onChange={this.handleCommentChange} - onKeyDown={this.handleKeyboard} - placeholder={this.props.placeholder} - rows={2} - value={this.state.textComment} - /> - </div> - <div className="issue-comment-form-footer"> - <div className="issue-comment-form-actions"> - <Button - className="js-issue-comment-submit little-spacer-right" - disabled={this.state.textComment.trim().length < 1} - onClick={this.handleCommentClick}> - {comment && translate('save')} - {!comment && translate('issue.comment.submit')} - </Button> - <ResetButtonLink className="js-issue-comment-cancel" onClick={this.handleCancelClick}> - {autoTriggered ? translate('skip') : translate('cancel')} - </ResetButtonLink> + <ClickEventBoundary> + <div className="issue-comment-bubble-popup"> + <div className="issue-comment-form-text"> + <textarea + autoFocus={true} + onChange={this.handleCommentChange} + onKeyDown={this.handleKeyboard} + placeholder={this.props.placeholder} + rows={2} + value={this.state.textComment} + /> </div> - <div className="issue-comment-form-tips"> - <MarkdownTips /> + <div className="issue-comment-form-footer"> + <div className="issue-comment-form-actions"> + <Button + className="js-issue-comment-submit little-spacer-right" + disabled={this.state.textComment.trim().length < 1} + onClick={this.handleCommentClick}> + {comment && translate('save')} + {!comment && translate('issue.comment.submit')} + </Button> + <ResetButtonLink + className="js-issue-comment-cancel" + onClick={this.handleCancelClick}> + {autoTriggered ? translate('skip') : translate('cancel')} + </ResetButtonLink> + </div> + <div className="issue-comment-form-tips"> + <MarkdownTips /> + </div> </div> </div> - </div> + </ClickEventBoundary> </DropdownOverlay> ); } diff --git a/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/ChangelogPopup-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/ChangelogPopup-test.tsx.snap index 2bf516e280b..fc871b08153 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/ChangelogPopup-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/ChangelogPopup-test.tsx.snap @@ -4,64 +4,66 @@ exports[`should render the changelog popup correctly 1`] = ` <DropdownOverlay placement="bottom-right" > - <div - className="menu is-container issue-changelog" - > - <table - className="spaced" + <ClickEventBoundary> + <div + className="menu is-container issue-changelog" > - <tbody> - <tr> - <td - className="thin text-left text-top nowrap" - > - <DateTimeFormatter - date="2017-03-01T09:36:01+0100" - /> - </td> - <td - className="text-left text-top" - > - created_by john.david.dalton@gmail.com - </td> - </tr> - <tr - key="0" - > - <td - className="thin text-left text-top nowrap" - > - <DateTimeFormatter - date="2017-03-01T09:36:01+0100" - /> - </td> - <td - className="text-left text-top" + <table + className="spaced" + > + <tbody> + <tr> + <td + className="thin text-left text-top nowrap" + > + <DateTimeFormatter + date="2017-03-01T09:36:01+0100" + /> + </td> + <td + className="text-left text-top" + > + created_by john.david.dalton@gmail.com + </td> + </tr> + <tr + key="0" > - <p> - <Connect(Avatar) - className="little-spacer-right" - hash="gravatarhash" - name="John Doe" - size={16} + <td + className="thin text-left text-top nowrap" + > + <DateTimeFormatter + date="2017-03-01T09:36:01+0100" /> - John Doe - </p> - <IssueChangelogDiff - diff={ - Object { - "key": "severity", - "newValue": "MINOR", - "oldValue": "CRITICAL", + </td> + <td + className="text-left text-top" + > + <p> + <Connect(Avatar) + className="little-spacer-right" + hash="gravatarhash" + name="John Doe" + size={16} + /> + John Doe + </p> + <IssueChangelogDiff + diff={ + Object { + "key": "severity", + "newValue": "MINOR", + "oldValue": "CRITICAL", + } } - } - key="severity" - /> - </td> - </tr> - </tbody> - </table> - </div> + key="severity" + /> + </td> + </tr> + </tbody> + </table> + </div> + </ClickEventBoundary> </DropdownOverlay> `; @@ -69,62 +71,64 @@ exports[`should render the changelog popup when we have a deleted user 1`] = ` <DropdownOverlay placement="bottom-right" > - <div - className="menu is-container issue-changelog" - > - <table - className="spaced" + <ClickEventBoundary> + <div + className="menu is-container issue-changelog" > - <tbody> - <tr> - <td - className="thin text-left text-top nowrap" - > - <DateTimeFormatter - date="2017-03-01T09:36:01+0100" - /> - </td> - <td - className="text-left text-top" - > - created_by john.david.dalton@gmail.com - </td> - </tr> - <tr - key="0" - > - <td - className="thin text-left text-top nowrap" - > - <DateTimeFormatter - date="2017-03-01T09:36:01+0100" - /> - </td> - <td - className="text-left text-top" + <table + className="spaced" + > + <tbody> + <tr> + <td + className="thin text-left text-top nowrap" + > + <DateTimeFormatter + date="2017-03-01T09:36:01+0100" + /> + </td> + <td + className="text-left text-top" + > + created_by john.david.dalton@gmail.com + </td> + </tr> + <tr + key="0" > - <p> - <Connect(Avatar) - className="little-spacer-right" - name="john.doe" - size={16} + <td + className="thin text-left text-top nowrap" + > + <DateTimeFormatter + date="2017-03-01T09:36:01+0100" /> - user.x_deleted.john.doe - </p> - <IssueChangelogDiff - diff={ - Object { - "key": "severity", - "newValue": "MINOR", - "oldValue": "CRITICAL", + </td> + <td + className="text-left text-top" + > + <p> + <Connect(Avatar) + className="little-spacer-right" + name="john.doe" + size={16} + /> + user.x_deleted.john.doe + </p> + <IssueChangelogDiff + diff={ + Object { + "key": "severity", + "newValue": "MINOR", + "oldValue": "CRITICAL", + } } - } - key="severity" - /> - </td> - </tr> - </tbody> - </table> - </div> + key="severity" + /> + </td> + </tr> + </tbody> + </table> + </div> + </ClickEventBoundary> </DropdownOverlay> `; diff --git a/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/CommentPopup-test.tsx.snap b/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/CommentPopup-test.tsx.snap index d6ad2e18439..706ea0067bd 100644 --- a/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/CommentPopup-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/issue/popups/__tests__/__snapshots__/CommentPopup-test.tsx.snap @@ -2,94 +2,98 @@ exports[`should render the comment popup correctly when changing a comment 1`] = ` <DropdownOverlay> - <div - className="issue-comment-bubble-popup" - > + <ClickEventBoundary> <div - className="issue-comment-form-text" - > - <textarea - autoFocus={true} - onChange={[Function]} - onKeyDown={[Function]} - placeholder="" - rows={2} - value="*test*" - /> - </div> - <div - className="issue-comment-form-footer" + className="issue-comment-bubble-popup" > <div - className="issue-comment-form-actions" + className="issue-comment-form-text" > - <Button - className="js-issue-comment-submit little-spacer-right" - disabled={false} - onClick={[Function]} - > - save - </Button> - <ResetButtonLink - className="js-issue-comment-cancel" - onClick={[Function]} - > - cancel - </ResetButtonLink> + <textarea + autoFocus={true} + onChange={[Function]} + onKeyDown={[Function]} + placeholder="" + rows={2} + value="*test*" + /> </div> <div - className="issue-comment-form-tips" + className="issue-comment-form-footer" > - <MarkdownTips /> + <div + className="issue-comment-form-actions" + > + <Button + className="js-issue-comment-submit little-spacer-right" + disabled={false} + onClick={[Function]} + > + save + </Button> + <ResetButtonLink + className="js-issue-comment-cancel" + onClick={[Function]} + > + cancel + </ResetButtonLink> + </div> + <div + className="issue-comment-form-tips" + > + <MarkdownTips /> + </div> </div> </div> - </div> + </ClickEventBoundary> </DropdownOverlay> `; exports[`should render the comment popup correctly without existing comment 1`] = ` <DropdownOverlay> - <div - className="issue-comment-bubble-popup" - > + <ClickEventBoundary> <div - className="issue-comment-form-text" - > - <textarea - autoFocus={true} - onChange={[Function]} - onKeyDown={[Function]} - placeholder="placeholder test" - rows={2} - value="" - /> - </div> - <div - className="issue-comment-form-footer" + className="issue-comment-bubble-popup" > <div - className="issue-comment-form-actions" + className="issue-comment-form-text" > - <Button - className="js-issue-comment-submit little-spacer-right" - disabled={true} - onClick={[Function]} - > - issue.comment.submit - </Button> - <ResetButtonLink - className="js-issue-comment-cancel" - onClick={[Function]} - > - cancel - </ResetButtonLink> + <textarea + autoFocus={true} + onChange={[Function]} + onKeyDown={[Function]} + placeholder="placeholder test" + rows={2} + value="" + /> </div> <div - className="issue-comment-form-tips" + className="issue-comment-form-footer" > - <MarkdownTips /> + <div + className="issue-comment-form-actions" + > + <Button + className="js-issue-comment-submit little-spacer-right" + disabled={true} + onClick={[Function]} + > + issue.comment.submit + </Button> + <ResetButtonLink + className="js-issue-comment-cancel" + onClick={[Function]} + > + cancel + </ResetButtonLink> + </div> + <div + className="issue-comment-form-tips" + > + <MarkdownTips /> + </div> </div> </div> - </div> + </ClickEventBoundary> </DropdownOverlay> `; |