From: Wouter Admiraal Date: Wed, 17 May 2023 08:57:49 +0000 (+0200) Subject: SONAR-19236 Move security hotspot activity to its own tab X-Git-Tag: 10.1.0.73491~226 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=76f1bb2ffe4c49b0098d12c9057f8dbc89891714;p=sonarqube.git SONAR-19236 Move security hotspot activity to its own tab --- diff --git a/server/sonar-web/design-system/src/components/HtmlFormatter.tsx b/server/sonar-web/design-system/src/components/HtmlFormatter.tsx index 2142e789a9e..fd44093c0e6 100644 --- a/server/sonar-web/design-system/src/components/HtmlFormatter.tsx +++ b/server/sonar-web/design-system/src/components/HtmlFormatter.tsx @@ -22,7 +22,6 @@ import tw from 'twin.macro'; import { themeBorder, themeColor } from '../helpers'; export const HtmlFormatter = styled.div` - ${tw`sw-my-6`} ${tw`sw-body-sm`} a { diff --git a/server/sonar-web/design-system/src/components/Text.tsx b/server/sonar-web/design-system/src/components/Text.tsx index aff69978ad3..fb6664fc038 100644 --- a/server/sonar-web/design-system/src/components/Text.tsx +++ b/server/sonar-web/design-system/src/components/Text.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import styled from '@emotion/styled'; +import { ElementType } from 'react'; import tw from 'twin.macro'; import { themeColor, themeContrast } from '../helpers/theme'; @@ -50,9 +51,17 @@ export function TextMuted({ text, className }: { className?: string; text: strin ); } -export function PageTitle({ text, className }: { className?: string; text: string }) { +export function PageTitle({ + text, + className, + as = 'h1', +}: { + as?: ElementType; + className?: string; + text: string; +}) { return ( - + {text} ); @@ -86,6 +95,7 @@ const StyledMutedText = styled(StyledText)` `; export const StyledPageTitle = styled(StyledText)` + ${tw`sw-block`}; ${tw`sw-text-base`} color: ${themeColor('facetHeader')}; `; diff --git a/server/sonar-web/design-system/src/components/icons/TrashIcon.tsx b/server/sonar-web/design-system/src/components/icons/TrashIcon.tsx new file mode 100644 index 00000000000..f4865e6536c --- /dev/null +++ b/server/sonar-web/design-system/src/components/icons/TrashIcon.tsx @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { TrashIcon as BaseTrashIcon } from '@primer/octicons-react'; +import { OcticonHoc } from './Icon'; + +export const TrashIcon = OcticonHoc(BaseTrashIcon); diff --git a/server/sonar-web/design-system/src/components/icons/index.ts b/server/sonar-web/design-system/src/components/icons/index.ts index 301e4c08af8..27e7dc2d9f6 100644 --- a/server/sonar-web/design-system/src/components/icons/index.ts +++ b/server/sonar-web/design-system/src/components/icons/index.ts @@ -66,6 +66,7 @@ export { StatusConfirmedIcon } from './StatusConfirmedIcon'; export { StatusOpenIcon } from './StatusOpenIcon'; export { StatusReopenedIcon } from './StatusReopenedIcon'; export { StatusResolvedIcon } from './StatusResolvedIcon'; +export { TrashIcon } from './TrashIcon'; export { TriangleDownIcon } from './TriangleDownIcon'; export { TriangleLeftIcon } from './TriangleLeftIcon'; export { TriangleRightIcon } from './TriangleRightIcon'; diff --git a/server/sonar-web/src/main/js/app/styles/style.css b/server/sonar-web/src/main/js/app/styles/style.css index 3ec343d5ad3..17c90e4e825 100644 --- a/server/sonar-web/src/main/js/app/styles/style.css +++ b/server/sonar-web/src/main/js/app/styles/style.css @@ -55,11 +55,6 @@ margin: 0 1px 0 0; } -.markdown-tips { - font-size: var(--smallFontSize); - color: var(--secondFontColor); -} - .rule-desc, .markdown { line-height: 1.5; diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-it.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-it.tsx index 1f3c205ebcc..ed641478c1e 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-it.tsx @@ -79,6 +79,8 @@ const ui = { fixTab: byRole('tab', { name: 'hotspots.tabs.fix_recommendations' }), fixContent: byText('This is how to fix'), showAllHotspotLink: byRole('link', { name: 'hotspot.filters.show_all' }), + activityTab: byRole('tab', { name: 'hotspots.tabs.activity' }), + addCommentButton: byRole('button', { name: 'hotspots.status.add_comment' }), }; const hotspotsHandler = new SecurityHotspotServiceMock(); @@ -153,7 +155,9 @@ describe('CRUD', () => { await user.click(await ui.activeAssignee.find()); await user.click(ui.inputAssignee.get()); - await user.keyboard('User'); + await act(async () => { + await user.keyboard('User'); + }); expect(searchUsers).toHaveBeenLastCalledWith({ q: 'User' }); await user.keyboard('{Enter}'); @@ -171,13 +175,14 @@ describe('CRUD', () => { await user.click(ui.reviewButton.get()); await user.click(ui.toReviewStatus.get()); - await user.click(screen.getByRole('textbox', { name: 'hotspots.status.add_comment' })); + await user.click(screen.getByRole('textbox', { name: 'hotspots.status.add_comment_optional' })); await user.keyboard(comment); await act(async () => { await user.click(ui.changeStatus.get()); }); + await user.click(ui.activityTab.get()); expect(setSecurityHotspotStatus).toHaveBeenLastCalledWith('test-1', { comment: 'COMMENT-TEXT', resolution: undefined, @@ -195,14 +200,17 @@ describe('CRUD', () => { it('should be able to add, edit and remove own comments', async () => { const uiComment = { - saveButton: byRole('button', { name: 'save' }), + saveButton: byRole('button', { name: 'hotspots.comment.submit' }), deleteButton: byRole('button', { name: 'delete' }), }; const user = userEvent.setup(); const comment = 'This is a comment from john doe'; renderSecurityHotspotsApp(); - const commentSection = await ui.hotspotCommentBox.find(); + await user.click(await ui.activityTab.find()); + await user.click(ui.addCommentButton.get()); + + const commentSection = ui.hotspotCommentBox.get(); const submitButton = ui.commentSubmitButton.get(); // Add a new comment diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentModal.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentModal.tsx new file mode 100644 index 00000000000..d8f0b5d9261 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentModal.tsx @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { ButtonPrimary, FormField, InputTextArea, Modal } from 'design-system'; +import * as React from 'react'; +import FormattingTips from '../../../components/common/FormattingTips'; +import { translate } from '../../../helpers/l10n'; + +export interface HotspotCommentPopupProps { + value?: string; + onSubmit: (comment: string) => void; + onCancel: () => void; +} + +export default function HotspotCommentModal(props: HotspotCommentPopupProps) { + const [comment, setComment] = React.useState(props.value ?? ''); + + return ( + + setComment(event.target.value)} + rows={3} + value={comment} + /> + + + } + primaryButton={ + props.onSubmit(comment)} disabled={!comment}> + {translate('hotspots.comment.submit')} + + } + secondaryButtonLabel={translate('cancel')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentPopup.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentPopup.tsx deleted file mode 100644 index 2ec060acef6..00000000000 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotCommentPopup.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2023 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import * as React from 'react'; -import FormattingTips from '../../../components/common/FormattingTips'; -import { Button, ResetButtonLink } from '../../../components/controls/buttons'; -import { translate } from '../../../helpers/l10n'; - -export interface HotspotCommentPopupProps { - markdownComment: string; - onCommentEditSubmit: (comment: string) => void; - onCancelEdit: () => void; -} - -export default function HotspotCommentPopup(props: HotspotCommentPopupProps) { - const [comment, setComment] = React.useState(props.markdownComment); - - return ( -
-
-