]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19581 Styling fixes for issue list and details page
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Wed, 14 Jun 2023 13:20:12 +0000 (15:20 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 15 Jun 2023 09:41:52 +0000 (09:41 +0000)
16 files changed:
server/sonar-web/design-system/src/components/DiscreetSelect.tsx
server/sonar-web/design-system/src/components/InputSelect.tsx
server/sonar-web/design-system/src/components/code-line/LineIssuesIndicatorIcon.tsx
server/sonar-web/design-system/src/components/icons/IssueTypeIcon.tsx
server/sonar-web/design-system/src/types/index.ts
server/sonar-web/design-system/src/types/issues.ts [new file with mode: 0644]
server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx
server/sonar-web/src/main/js/apps/issues/components/IssueHeader.tsx
server/sonar-web/src/main/js/components/icons/StatusIcon.tsx
server/sonar-web/src/main/js/components/issue/Issue.css
server/sonar-web/src/main/js/components/issue/components/IssueActionsBar.tsx
server/sonar-web/src/main/js/components/issue/components/IssueCommentAction.tsx
server/sonar-web/src/main/js/components/issue/components/IssueSeverity.tsx
server/sonar-web/src/main/js/components/issue/components/IssueTransition.tsx
server/sonar-web/src/main/js/components/issue/components/IssueType.tsx
server/sonar-web/src/main/js/components/issue/components/IssueView.tsx

index b78deb33a91e1470a9e8d9202095b6be3acf3bc0..085caf1b12b9cb25fc74a041dd0313910d5bbffb 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import styled from '@emotion/styled';
 import tw from 'twin.macro';
 import { themeBorder, themeColor, themeContrast } from '../helpers/theme';
@@ -25,7 +26,7 @@ import { InputSelect, LabelValueSelectOption } from './InputSelect';
 
 interface Props<V> {
   className?: string;
-  components?: any;
+  components?: Parameters<typeof InputSelect>[0]['components'];
   customValue?: JSX.Element;
   isDisabled?: boolean;
   menuIsOpen?: boolean;
index 906203174dd2d28b3203ca9f143dcd680ac98062..f000f7321367bbe44a1583ba8eb4eeab1200036c 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { useTheme as themeInfo } from '@emotion/react';
 import classNames from 'classnames';
 import { omit } from 'lodash';
@@ -120,11 +121,11 @@ export function InputSelect<
       classNames={{
         container: () => 'sw-relative sw-inline-block sw-align-middle',
         placeholder: () => 'sw-truncate sw-leading-4',
-        menu: () => 'sw-z-dropdown-menu',
+        menu: () => 'sw-z-dropdown-menu sw-ml-1/2 sw-mt-2',
         menuList: () => 'sw-overflow-y-auto sw-py-2 sw-max-h-[12.25rem]',
         control: ({ isDisabled }) =>
           classNames(
-            'sw-absolut sw-box-border sw-rounded-2 sw-overflow-hidden',
+            'sw-box-border sw-rounded-2 sw-overflow-hidden',
             isDisabled && 'sw-pointer-events-none sw-cursor-not-allowed'
           ),
         option: ({ isDisabled }) =>
index a5522960a1532dfc748295000d216a76e6ad7b3e..792722caa5f40c2237311f1b70b8cfa33a34edb7 100644 (file)
 import styled from '@emotion/styled';
 import { memo } from 'react';
 import tw from 'twin.macro';
+import { IssueType } from '../../types';
 import { IssueTypeIcon } from '../icons/IssueTypeIcon';
 
-export type IssueType = 'BUG' | 'VULNERABILITY' | 'CODE_SMELL' | 'SECURITY_HOTSPOT';
-
 interface Props {
   issuesCount: number;
   mostImportantIssueType: IssueType;
index 134788f96188676f16bc293549b64591dcc925eb..94047ec41c7d1e9757eb39991a8816bbef1e5508 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { useTheme } from '@emotion/react';
 import styled from '@emotion/styled';
 import tw from 'twin.macro';
 import { themeColor, themeContrast } from '../../helpers/theme';
+import { IssueType } from '../../types';
 import { BugIcon } from './BugIcon';
 import { CodeSmellIcon } from './CodeSmellIcon';
 import { IconProps } from './Icon';
 import { SecurityFindingIcon } from './SecurityFindingIcon';
 import { VulnerabilityIcon } from './VulnerabilityIcon';
 
-export type IssueType = 'BUG' | 'VULNERABILITY' | 'CODE_SMELL' | 'SECURITY_HOTSPOT';
 export interface Props extends IconProps {
   // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
   type: string | IssueType;
index 60861305544f7e295d05ecd0b6dea88fcc4971bd..7a5670450c2bcf9d619dad73b852014cefbeb887 100644 (file)
@@ -19,5 +19,6 @@
  */
 
 export * from './charts';
+export * from './issues';
 export * from './measures';
 export * from './theme';
diff --git a/server/sonar-web/design-system/src/types/issues.ts b/server/sonar-web/design-system/src/types/issues.ts
new file mode 100644 (file)
index 0000000..8f2c801
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+export type IssueType = 'BUG' | 'VULNERABILITY' | 'CODE_SMELL' | 'SECURITY_HOTSPOT';
index c6beaa5f4d14dfaecfe44de06b9f45f404cd5631..777284552d041121def9faa2c99659269ca79f6c 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import styled from '@emotion/styled';
 import { Badge, themeBorder, themeColor, themeContrast } from 'design-system';
 import * as React from 'react';
@@ -63,6 +64,7 @@ export default function ComponentBreadcrumbs({
       {displayProject && (
         <span title={projectName}>
           {limitComponentName(issue.projectName)}
+
           {displayBranchInformation && (
             <>
               {' - '}
@@ -76,18 +78,20 @@ export default function ComponentBreadcrumbs({
               )}
             </>
           )}
+
           <SlashSeparator className="sw-mx-1" />
         </span>
       )}
 
-      <span title={componentName}>{collapsePath(componentName || '')}</span>
+      <span title={componentName}>{collapsePath(componentName ?? '')}</span>
     </DivStyled>
   );
 }
 
 const DivStyled = styled.div`
-  color: ${themeContrast('subnavigation')};
   background-color: ${themeColor('subnavigation')};
+  color: ${themeContrast('breadcrumb')};
+
   &:not(:last-child) {
     border-bottom: ${themeBorder('default')};
   }
index 4715c45f80778650a0752ef71ce48f11607de5a2..5f2e86919c0c5b51da987cb96517ccafbc91964e 100644 (file)
@@ -168,7 +168,6 @@ export default class IssueHeader extends React.PureComponent<Props, State> {
           />
         </div>
         <IssueActionsBar
-          className="issue-header-actions"
           currentPopup={issuePopupName}
           issue={issue}
           onAssign={this.handleAssignement}
index c198c651980839a563f079324773f345c534fbdc..936daa5b482f95888da32a73ba88446251fcfb41 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
+import {
+  StatusConfirmedIcon,
+  StatusOpenIcon,
+  StatusReopenedIcon,
+  StatusResolvedIcon,
+} from 'design-system';
 import * as React from 'react';
-import { colors } from '../../app/theme';
 import { Dict } from '../../types/types';
-import Icon, { IconProps } from './Icon';
+import { IconProps } from './Icon';
 
 interface Props extends IconProps {
   status: string;
 }
 
 const statusIcons: Dict<(props: IconProps) => React.ReactElement> = {
-  open: OpenStatusIcon,
-  confirmed: ConfirmedStatusIcon,
-  reopened: ReopenedStatusIcon,
-  resolved: ResolvedStatusIcon,
-  closed: ClosedStatusIcon,
-  to_review: OpenStatusIcon,
-  in_review: ConfirmedStatusIcon,
-  reviewed: ResolvedStatusIcon,
+  closed: StatusResolvedIcon,
+  confirm: StatusConfirmedIcon,
+  confirmed: StatusConfirmedIcon,
+  falsepositive: StatusResolvedIcon,
+  in_review: StatusConfirmedIcon,
+  open: StatusOpenIcon,
+  reopened: StatusReopenedIcon,
+  resolve: StatusResolvedIcon,
+  resolved: StatusResolvedIcon,
+  reviewed: StatusResolvedIcon,
+  to_review: StatusOpenIcon,
+  wontfix: StatusResolvedIcon,
 };
 
 export default function StatusIcon({ status, ...iconProps }: Props) {
   const DesiredStatusIcon = statusIcons[status.toLowerCase()];
-  return DesiredStatusIcon ? <DesiredStatusIcon {...iconProps} /> : null;
-}
-
-function OpenStatusIcon(iconProps: IconProps) {
-  return (
-    <Icon {...iconProps}>
-      <path
-        d="M8 3.75c-.77 0-1.482.19-2.133.57A4.25 4.25 0 0 0 4.32 5.867c-.38.65-.57 1.362-.57 2.133 0 .77.19 1.482.57 2.133.38.65.896 1.167 1.547 1.547.65.38 1.362.57 2.133.57.77 0 1.482-.19 2.133-.57a4.242 4.242 0 0 0 1.547-1.547c.38-.65.57-1.362.57-2.133 0-.77-.19-1.482-.57-2.133a4.25 4.25 0 0 0-1.547-1.547A4.153 4.153 0 0 0 8 3.75zM14 8c0 1.09-.268 2.092-.805 3.012a5.96 5.96 0 0 1-2.183 2.183A5.863 5.863 0 0 1 8 14a5.863 5.863 0 0 1-3.012-.805 5.96 5.96 0 0 1-2.183-2.183A5.863 5.863 0 0 1 2 8c0-1.09.268-2.092.805-3.012a5.96 5.96 0 0 1 2.183-2.183A5.863 5.863 0 0 1 8 2c1.09 0 2.092.268 3.012.805a5.96 5.96 0 0 1 2.183 2.183C13.732 5.908 14 6.91 14 8z"
-        style={{ fill: colors.blue }}
-      />
-    </Icon>
-  );
-}
-
-function ConfirmedStatusIcon(iconProps: IconProps) {
-  return (
-    <Icon {...iconProps}>
-      <path
-        d="M10 8c0 .552-.195 1.023-.586 1.414-.39.39-.862.586-1.414.586a1.926 1.926 0 0 1-1.414-.586A1.928 1.928 0 0 1 6 8c0-.552.195-1.023.586-1.414C6.976 6.196 7.448 6 8 6c.552 0 1.023.195 1.414.586.39.39.586.862.586 1.414zM8 3.75c-.77 0-1.482.19-2.133.57A4.25 4.25 0 0 0 4.32 5.867c-.38.65-.57 1.362-.57 2.133 0 .77.19 1.482.57 2.133.38.65.896 1.167 1.547 1.547.65.38 1.362.57 2.133.57.77 0 1.482-.19 2.133-.57a4.242 4.242 0 0 0 1.547-1.547c.38-.65.57-1.362.57-2.133 0-.77-.19-1.482-.57-2.133a4.25 4.25 0 0 0-1.547-1.547A4.153 4.153 0 0 0 8 3.75zM14 8c0 1.09-.268 2.092-.805 3.012a5.96 5.96 0 0 1-2.183 2.183A5.863 5.863 0 0 1 8 14a5.863 5.863 0 0 1-3.012-.805 5.96 5.96 0 0 1-2.183-2.183A5.863 5.863 0 0 1 2 8c0-1.09.268-2.092.805-3.012a5.96 5.96 0 0 1 2.183-2.183A5.863 5.863 0 0 1 8 2c1.09 0 2.092.268 3.012.805a5.96 5.96 0 0 1 2.183 2.183C13.732 5.908 14 6.91 14 8z"
-        style={{ fill: colors.blue }}
-      />
-    </Icon>
-  );
-}
-
-function ReopenedStatusIcon(iconProps: IconProps) {
-  return (
-    <Icon {...iconProps}>
-      <path
-        d="M8 12.25v-8.5c-.77 0-1.482.19-2.133.57A4.25 4.25 0 0 0 4.32 5.867c-.38.65-.57 1.362-.57 2.133 0 .77.19 1.482.57 2.133.38.65.896 1.167 1.547 1.547.65.38 1.362.57 2.133.57zM14 8c0 1.09-.268 2.092-.805 3.012a5.96 5.96 0 0 1-2.183 2.183A5.863 5.863 0 0 1 8 14a5.863 5.863 0 0 1-3.012-.805 5.96 5.96 0 0 1-2.183-2.183A5.863 5.863 0 0 1 2 8c0-1.09.268-2.092.805-3.012a5.96 5.96 0 0 1 2.183-2.183A5.863 5.863 0 0 1 8 2c1.09 0 2.092.268 3.012.805a5.96 5.96 0 0 1 2.183 2.183C13.732 5.908 14 6.91 14 8z"
-        style={{ fill: colors.blue }}
-      />
-    </Icon>
-  );
-}
 
-function ResolvedStatusIcon(iconProps: IconProps) {
-  return (
-    <Icon {...iconProps}>
-      <path
-        d="M12.03 6.734a.49.49 0 0 0-.14-.36l-.71-.702a.48.48 0 0 0-.352-.15.474.474 0 0 0-.35.15l-3.19 3.18-1.765-1.766a.479.479 0 0 0-.35-.15.479.479 0 0 0-.353.15l-.71.703a.482.482 0 0 0-.14.358c0 .14.046.258.14.352l2.828 2.828c.098.1.216.15.35.15.142 0 .26-.05.36-.15l4.243-4.242a.475.475 0 0 0 .14-.352l-.001.001zM14 8c0 1.09-.268 2.092-.805 3.012a5.96 5.96 0 0 1-2.183 2.183A5.863 5.863 0 0 1 8 14a5.863 5.863 0 0 1-3.012-.805 5.96 5.96 0 0 1-2.183-2.183A5.863 5.863 0 0 1 2 8c0-1.09.268-2.092.805-3.012a5.96 5.96 0 0 1 2.183-2.183A5.863 5.863 0 0 1 8 2c1.09 0 2.092.268 3.012.805a5.96 5.96 0 0 1 2.183 2.183C13.732 5.908 14 6.91 14 8z"
-        style={{ fill: colors.baseFontColor }}
-      />
-    </Icon>
-  );
-}
-
-function ClosedStatusIcon(iconProps: IconProps) {
-  return (
-    <Icon {...iconProps}>
-      <path
-        d="M14 8c0 1.09-.268 2.092-.805 3.012a5.96 5.96 0 0 1-2.183 2.183A5.863 5.863 0 0 1 8 14a5.863 5.863 0 0 1-3.012-.805 5.96 5.96 0 0 1-2.183-2.183A5.863 5.863 0 0 1 2 8c0-1.09.268-2.092.805-3.012a5.96 5.96 0 0 1 2.183-2.183A5.863 5.863 0 0 1 8 2c1.09 0 2.092.268 3.012.805a5.96 5.96 0 0 1 2.183 2.183C13.732 5.908 14 6.91 14 8z"
-        style={{ fill: colors.baseFontColor }}
-      />
-    </Icon>
-  );
+  return DesiredStatusIcon ? <DesiredStatusIcon {...iconProps} /> : null;
 }
index 5be5920c71f4c237cc86295bc2e94e9a801447f5..4a0abde9f6669b0b6520fef0c12522ec72a46ea8 100644 (file)
   margin-left: var(--gridSize);
 }
 
-.issue-header-actions .issue-meta + .issue-meta {
-  margin-left: calc(var(--gridSize) * 2);
-}
-
 .issue-meta-label {
   display: inline-block;
   vertical-align: top;
index 76fa0f8523143d1fffeb71880d98a875fc364ded..e0008c255b5252639bc2c7ee8d3ecabed5e8bc7a 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import styled from '@emotion/styled';
 import classNames from 'classnames';
 import { Badge, CommentIcon, SeparatorCircleIcon, themeColor } from 'design-system';
@@ -71,6 +72,7 @@ export default function IssueActionsBar(props: Props) {
     showCommentsInPopup,
     showLine,
   } = props;
+
   const [commentState, setCommentState] = React.useState<State>({
     commentAutoTriggered: false,
     commentPlaceholder: '',
@@ -86,19 +88,22 @@ export default function IssueActionsBar(props: Props) {
       const newIssue = { ...issue, [property]: value };
       updateIssue(onChange, apiCall({ issue: issue.key, [property]: value }), issue, newIssue);
     }
+
     togglePopup(popup, false);
   };
 
-  const toggleComment = (open: boolean | undefined, placeholder = '', autoTriggered = false) => {
+  const toggleComment = (open: boolean, placeholder = '', autoTriggered = false) => {
     setCommentState({
       commentPlaceholder: placeholder,
       commentAutoTriggered: autoTriggered,
     });
+
     togglePopup('comment', open);
   };
 
   const handleTransition = (issue: Issue) => {
     onChange(issue);
+
     if (
       issue.resolution === IssueResolution.FalsePositive ||
       (issue.resolution === IssueResolution.WontFix && issue.type !== IssueTypeEnum.SecurityHotspot)
@@ -108,15 +113,18 @@ export default function IssueActionsBar(props: Props) {
   };
 
   const { externalRulesRepoNames } = React.useContext(WorkspaceContext);
+
   const ruleEngine =
     (issue.externalRuleEngine && externalRulesRepoNames[issue.externalRuleEngine]) ||
     issue.externalRuleEngine;
+
   const canAssign = issue.actions.includes(IssueActions.Assign);
   const canComment = issue.actions.includes(IssueActions.Comment);
   const canSetSeverity = issue.actions.includes(IssueActions.SetSeverity);
   const canSetType = issue.actions.includes(IssueActions.SetType);
   const hasTransitions = issue.transitions.length > 0;
   const hasComments = !!issue.comments?.length;
+
   const issueMetaListItemClassNames = classNames(
     className,
     'sw-body-sm sw-overflow-hidden sw-whitespace-nowrap sw-max-w-abs-150'
@@ -130,6 +138,7 @@ export default function IssueActionsBar(props: Props) {
         <li>
           <IssueType canSetType={canSetType} issue={issue} setIssueProperty={setIssueProperty} />
         </li>
+
         <li>
           <IssueSeverity
             isOpen={currentPopup === 'set-severity'}
@@ -139,6 +148,7 @@ export default function IssueActionsBar(props: Props) {
             setIssueProperty={setIssueProperty}
           />
         </li>
+
         <li>
           <IssueTransition
             isOpen={currentPopup === 'transition'}
@@ -148,6 +158,7 @@ export default function IssueActionsBar(props: Props) {
             onChange={handleTransition}
           />
         </li>
+
         <li>
           <IssueAssign
             isOpen={currentPopup === 'assign'}
@@ -158,6 +169,7 @@ export default function IssueActionsBar(props: Props) {
           />
         </li>
       </ul>
+
       {(canComment || showCommentsInPopup) && (
         <IssueCommentAction
           commentAutoTriggered={commentState.commentAutoTriggered}
@@ -211,9 +223,11 @@ export default function IssueActionsBar(props: Props) {
               <CommentIcon aria-label={translate('issue.comment.formlink')} />
               {issue.comments?.length}
             </IssueMetaListItem>
+
             <SeparatorCircleIcon aria-hidden as="li" />
           </>
         )}
+
         {showLine && isDefined(issue.textRange) && (
           <>
             <Tooltip overlay={translate('line_number')}>
@@ -221,17 +235,21 @@ export default function IssueActionsBar(props: Props) {
                 {translateWithParameters('issue.ncloc_x.short', issue.textRange.endLine)}
               </IssueMetaListItem>
             </Tooltip>
+
             <SeparatorCircleIcon aria-hidden as="li" />
           </>
         )}
+
         {issue.effort && (
           <>
             <IssueMetaListItem className={issueMetaListItemClassNames}>
               {translateWithParameters('issue.x_effort', issue.effort)}
             </IssueMetaListItem>
+
             <SeparatorCircleIcon aria-hidden as="li" />
           </>
         )}
+
         <IssueMetaListItem className={issueMetaListItemClassNames}>
           <DateFromNow date={issue.creationDate} />
         </IssueMetaListItem>
index 17ccba55a76f4d3717c2316d2f32a833baf26757..54fc8d609f7ca61925094b27e1d8600a27e90584 100644 (file)
@@ -32,7 +32,7 @@ interface Props {
   currentPopup?: boolean;
   issueKey: string;
   onChange: (issue: Issue) => void;
-  toggleComment: (open?: boolean, placeholder?: string, autoTriggered?: boolean) => void;
+  toggleComment: (open: boolean, placeholder?: string, autoTriggered?: boolean) => void;
   comments?: IssueComment[];
   showCommentsInPopup?: boolean;
 }
@@ -54,10 +54,6 @@ export default class IssueCommentAction extends React.PureComponent<Props> {
     updateIssue(this.props.onChange, deleteIssueComment({ comment }));
   };
 
-  handleCommentClick = () => {
-    this.props.toggleComment();
-  };
-
   handleClose = () => {
     this.props.toggleComment(false);
   };
index 7d3b33a823045cd158161e2d38cec9e22afb5e86..1c80407309b9093856059ee08a3840cd0e92afe2 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { DiscreetSelect } from 'design-system';
 import * as React from 'react';
 import { setIssueSeverity } from '../../../api/issues';
+import { SEVERITIES } from '../../../helpers/constants';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { IssueResponse } from '../../../types/issues';
+import { IssueResponse, IssueSeverity as IssueSeverityType } from '../../../types/issues';
 import { Issue, RawQuery } from '../../../types/types';
-import SeverityIcon from '../../icons/SeverityIcon';
+import IssueSeverityIcon from '../../icon-mappers/IssueSeverityIcon';
 
 interface Props {
   canSetSeverity: boolean;
@@ -44,7 +46,7 @@ export default class IssueSeverity extends React.PureComponent<Props> {
     this.toggleSetSeverity(false);
   };
 
-  toggleSetSeverity = (open?: boolean) => {
+  toggleSetSeverity = (open: boolean) => {
     this.props.togglePopup('set-severity', open);
   };
 
@@ -54,11 +56,11 @@ export default class IssueSeverity extends React.PureComponent<Props> {
 
   render() {
     const { issue } = this.props;
-    const SEVERITY = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'];
-    const typesOptions = SEVERITY.map((severity) => ({
+
+    const typesOptions = SEVERITIES.map((severity) => ({
       label: translate('severity', severity),
       value: severity,
-      Icon: <SeverityIcon severity={severity} aria-hidden />,
+      Icon: <IssueSeverityIcon severity={severity} aria-hidden />,
     }));
 
     if (this.props.canSetSeverity) {
@@ -81,7 +83,8 @@ export default class IssueSeverity extends React.PureComponent<Props> {
 
     return (
       <span className="sw-flex sw-items-center sw-gap-1">
-        <SeverityIcon className="little-spacer-right" severity={issue.severity} aria-hidden />
+        <IssueSeverityIcon severity={issue.severity as IssueSeverityType} aria-hidden />
+
         {translate('severity', issue.severity)}
       </span>
     );
index a6b505c716dd0c42c7ecd8268e6edadb27974a17..338b5a6c344238ecaf0cb8f7868f0ad43e73de87 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { DiscreetSelect } from 'design-system';
 import * as React from 'react';
 import { GroupBase, OptionProps, components } from 'react-select';
@@ -36,16 +37,36 @@ interface Props {
   togglePopup: (popup: string, show?: boolean) => void;
 }
 
+function SingleValueFactory(issue: Props['issue']) {
+  return function SingleValue<
+    V,
+    Option extends LabelValueSelectOption<V>,
+    IsMulti extends boolean = false,
+    Group extends GroupBase<Option> = GroupBase<Option>
+  >(props: OptionProps<Option, IsMulti, Group>) {
+    return (
+      <components.SingleValue {...props}>
+        <StatusHelper
+          className="sw-flex sw-items-center"
+          resolution={issue.resolution}
+          status={issue.status}
+        />
+      </components.SingleValue>
+    );
+  };
+}
+
 export default class IssueTransition extends React.PureComponent<Props> {
   setTransition = ({ value }: { value: string }) => {
     updateIssue(
       this.props.onChange,
       setIssueTransition({ issue: this.props.issue.key, transition: value })
     );
+
     this.toggleSetTransition(false);
   };
 
-  toggleSetTransition = (open?: boolean) => {
+  toggleSetTransition = (open: boolean) => {
     this.props.togglePopup('transition', open);
   };
 
@@ -71,26 +92,7 @@ export default class IssueTransition extends React.PureComponent<Props> {
           )}
           size="medium"
           className="it__issue-transition"
-          components={{
-            SingleValue: <
-              V,
-              Option extends LabelValueSelectOption<V>,
-              IsMulti extends boolean = false,
-              Group extends GroupBase<Option> = GroupBase<Option>
-            >(
-              props: OptionProps<Option, IsMulti, Group>
-            ) => {
-              return (
-                <components.SingleValue {...props}>
-                  <StatusHelper
-                    className="sw-flex sw-items-center"
-                    resolution={issue.resolution}
-                    status={issue.status}
-                  />
-                </components.SingleValue>
-              );
-            },
-          }}
+          components={{ SingleValue: SingleValueFactory(issue) }}
           menuIsOpen={this.props.isOpen && this.props.hasTransitions}
           options={transitions}
           setValue={this.setTransition}
@@ -103,10 +105,13 @@ export default class IssueTransition extends React.PureComponent<Props> {
     }
 
     const resolution = issue.resolution && ` (${translate('issue.resolution', issue.resolution)})`;
+
     return (
       <span className="sw-flex sw-items-center sw-gap-1">
         <StatusIcon status={issue.status} />
+
         {translate('issue.status', issue.status)}
+
         {resolution}
       </span>
     );
index 2607dad09fc167ebf75a26cc99137f0f95da907e..a0be2494e77426b827a348a82fc79b6566b96d51 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { DiscreetSelect } from 'design-system';
 import * as React from 'react';
 import { setIssueType } from '../../../api/issues';
-import IssueTypeIcon from '../../../components/icons/IssueTypeIcon';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { IssueResponse } from '../../../types/issues';
 import { Issue, RawQuery } from '../../../types/types';
+import IssueTypeIcon from '../../icon-mappers/IssueTypeIcon';
 
 interface Props {
   canSetType: boolean;
@@ -44,11 +45,13 @@ export default class IssueType extends React.PureComponent<Props> {
   render() {
     const { issue } = this.props;
     const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
+
     const typesOptions = TYPES.map((type) => ({
       label: translate('issue.type', type),
       value: type,
-      Icon: <IssueTypeIcon query={type} />,
+      Icon: <IssueTypeIcon type={type} />,
     }));
+
     if (this.props.canSetType) {
       return (
         <DiscreetSelect
@@ -66,7 +69,7 @@ export default class IssueType extends React.PureComponent<Props> {
 
     return (
       <span className="sw-flex sw-items-center sw-gap-1">
-        <IssueTypeIcon query={issue.type} />
+        <IssueTypeIcon type={issue.type} />
         {translate('issue.type', issue.type)}
       </span>
     );
index 23a6fd2750979c16099336b4f7689021ac2ec7d5..e04d48f276227d11eb762572dacf08dd09ab272c 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import styled from '@emotion/styled';
 import classNames from 'classnames';
 import { Checkbox, themeBorder, themeColor } from 'design-system';
@@ -98,13 +99,16 @@ export default class IssueView extends React.PureComponent<Props> {
       >
         <div className="sw-flex sw-w-full sw-px-2 sw-gap-4">
           {hasCheckbox && (
-            <Checkbox
-              checked={checked ?? false}
-              onCheck={this.handleCheck}
-              label={translateWithParameters('issues.action_select.label', issue.message)}
-              title={translate('issues.action_select')}
-            />
+            <span className="sw-mt-1/2 sw-self-start">
+              <Checkbox
+                checked={checked ?? false}
+                onCheck={this.handleCheck}
+                label={translateWithParameters('issues.action_select.label', issue.message)}
+                title={translate('issues.action_select')}
+              />
+            </span>
           )}
+
           <div className="sw-flex sw-flex-col sw-grow sw-gap-2">
             <IssueTitleBar
               currentPopup={currentPopup}
@@ -114,6 +118,7 @@ export default class IssueView extends React.PureComponent<Props> {
               onChange={this.props.onChange}
               togglePopup={this.props.togglePopup}
             />
+
             <IssueActionsBar
               currentPopup={currentPopup}
               issue={issue}