]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10319 Display Analysis Scope on rules detail page (#2995)
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Mon, 29 Jan 2018 16:55:12 +0000 (17:55 +0100)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Wed, 7 Feb 2018 10:32:38 +0000 (11:32 +0100)
* SONAR-10319 Display Analysis Scope on rules detail page

* fix icons alignment

12 files changed:
server/sonar-web/src/main/js/api/quality-profiles.ts
server/sonar-web/src/main/js/app/styles/init/misc.css
server/sonar-web/src/main/js/app/types.ts
server/sonar-web/src/main/js/apps/coding-rules/components/ActivationSeverityFacet.tsx
server/sonar-web/src/main/js/apps/coding-rules/components/RuleDetailsMeta.tsx
server/sonar-web/src/main/js/apps/coding-rules/components/RuleListItem.tsx
server/sonar-web/src/main/js/apps/coding-rules/styles.css
server/sonar-web/src/main/js/components/icons-components/RuleScopeIcon.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tags/TagsList.tsx
server/sonar-web/src/main/js/components/tags/__tests__/__snapshots__/TagsList-test.tsx.snap
server/sonar-web/src/main/js/components/ui/IssueTypeIcon.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 188651ddc31b048aa0f48cdf12a8cbeea56c72d2..736de049edb8d0639b2de06bb1754c384d644a32 100644 (file)
@@ -249,11 +249,11 @@ export interface BulkActivateParameters {
 }
 
 export function bulkActivateRules(data: BulkActivateParameters) {
-  return postJSON('api/qualityprofiles/activate_rules', data);
+  return postJSON('/api/qualityprofiles/activate_rules', data);
 }
 
 export function bulkDeactivateRules(data: BulkActivateParameters) {
-  return postJSON('api/qualityprofiles/deactivate_rules', data);
+  return postJSON('/api/qualityprofiles/deactivate_rules', data);
 }
 
 export function activateRule(data: {
index aa27be830992f568a8e7a4f9397f430229713b71..72cadc3c21b6e37a833fff32d2f81d831e109f90 100644 (file)
@@ -285,6 +285,11 @@ td.big-spacer-top {
   align-items: center;
 }
 
+.display-inline-flex-center {
+  display: inline-flex !important;
+  align-items: center;
+}
+
 .rounded {
   border-radius: 2px;
 }
index f0c37fbe7a386ba9e0fe60de60398e57fee6f25c..0d7fb8b6fec7f82dbbaa58d7f209e054e26c4798 100644 (file)
@@ -156,6 +156,14 @@ export interface CurrentUser {
   showOnboardingTutorial?: boolean;
 }
 
+export interface Group {
+  default?: boolean;
+  description?: string;
+  id: number;
+  membersCount: number;
+  name: string;
+}
+
 export enum HomePageType {
   Project = 'PROJECT',
   Organization = 'ORGANIZATION',
@@ -229,6 +237,7 @@ export interface RuleDetails extends Rule {
   remFnOverloaded?: boolean;
   remFnType?: string;
   repo: string;
+  scope?: RuleScope;
   templateKey?: string;
 }
 
@@ -255,10 +264,8 @@ export enum RuleInheritance {
   Overridden = 'OVERRIDES'
 }
 
-export interface Group {
-  default?: boolean;
-  description?: string;
-  id: number;
-  membersCount: number;
-  name: string;
+export enum RuleScope {
+  Main = 'MAIN',
+  Test = 'TEST',
+  All = 'ALL'
 }
index d9dcbf764ccdc6d8729b30df8a49bf094191f3ad..0faa11ff7486e4633ab1e36fd0b4da18d1bf1782 100644 (file)
@@ -38,6 +38,7 @@ export default class ActivationSeverityFacet extends React.PureComponent<Props>
         {...this.props}
         disabled={this.props.disabled}
         disabledHelper={translate('coding_rules.filters.active_severity.inactive')}
+        halfWidth={true}
         options={SEVERITIES}
         property="activationSeverities"
         renderName={this.renderName}
index 3728d1e8c0e305475851168e73309fa8dea55706..88d81b5facaee5abf3c8249a90ecedc130573138 100644 (file)
 import * as React from 'react';
 import { Link } from 'react-router';
 import { Query } from '../query';
-import { RuleDetails } from '../../../app/types';
+import { RuleDetails, RuleScope } from '../../../app/types';
 import { getRuleUrl } from '../../../helpers/urls';
 import LinkIcon from '../../../components/icons-components/LinkIcon';
+import RuleScopeIcon from '../../../components/icons-components/RuleScopeIcon';
 import SimilarRulesFilter from './SimilarRulesFilter';
 import Tooltip from '../../../components/controls/Tooltip';
 import { translate } from '../../../helpers/l10n';
@@ -72,7 +73,10 @@ export default class RuleDetailsMeta extends React.PureComponent<Props, State> {
   renderSeverity = () => (
     <Tooltip overlay={translate('default_severity')}>
       <li className="coding-rules-detail-property" data-meta="severity">
-        <SeverityHelper severity={this.props.ruleDetails.severity} />
+        <SeverityHelper
+          className="display-inline-flex-center"
+          severity={this.props.ruleDetails.severity}
+        />
       </li>
     </Tooltip>
   );
@@ -200,6 +204,18 @@ export default class RuleDetailsMeta extends React.PureComponent<Props, State> {
     );
   };
 
+  renderScope = () => {
+    const scope = this.props.ruleDetails.scope || RuleScope.Main;
+    return (
+      <Tooltip overlay={translate('coding_rules.scope.title')}>
+        <li className="coding-rules-detail-property">
+          <RuleScopeIcon className="little-spacer-right" />
+          {translate('coding_rules.scope', scope)}
+        </li>
+      </Tooltip>
+    );
+  };
+
   render() {
     const { ruleDetails } = this.props;
     return (
@@ -223,6 +239,7 @@ export default class RuleDetailsMeta extends React.PureComponent<Props, State> {
           {this.renderType()}
           {this.renderSeverity()}
           {this.renderStatus()}
+          {this.renderScope()}
           {this.renderTags()}
           {this.renderCreationDate()}
           {this.renderRepository()}
index e713523ac8f56e54f876faa5e1d4e459bebf86be..20c045ba704ca07b0b26155175d087b0dd208ddf 100644 (file)
@@ -183,7 +183,7 @@ export default class RuleListItem extends React.PureComponent<Props> {
               </td>
 
               <td className="coding-rule-table-meta-cell">
-                <div className="coding-rule-meta">
+                <div className="display-flex-center coding-rule-meta">
                   {rule.status !== 'READY' && (
                     <span className="spacer-left badge badge-normal-size badge-danger-light">
                       {translate('rules.status', rule.status)}
@@ -191,7 +191,7 @@ export default class RuleListItem extends React.PureComponent<Props> {
                   )}
                   <span className="spacer-left note">{rule.langName}</span>
                   <Tooltip overlay={translate('coding_rules.type.tooltip', rule.type)}>
-                    <span className="spacer-left note">
+                    <span className="display-inline-flex-center spacer-left note">
                       <IssueTypeIcon className="little-spacer-right" query={rule.type} />
                       {translate('issue.type', rule.type)}
                     </span>
index ceef209eeeacfb9a51c10cae4d183aeed6ae5fd0..5647de8b17c0b4b39e55c3c283d0d919daeeb4cd 100644 (file)
 }
 
 .coding-rules-detail-properties {
-  margin: 10px 0;
-  font-size: 0;
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  margin-top: var(--gridSize);
 }
 
 .coding-rules-detail-properties + .coding-rules-detail-properties {
 }
 
 .coding-rules-detail-property {
-  display: inline-block;
-  margin-right: 20px;
+  display: flex;
+  align-items: center;
+  margin-right: calc(2 * var(--gridSize));
+  margin-bottom: var(--gridSize);
   font-size: var(--smallFontSize);
 }
 
 }
 
 .coding-rules-detail-quality-profile-severity i {
-  margin-top: 4px;
+  margin-top: 2px;
 }
 
 .coding-rules-detail-quality-profile-parameters,
@@ -265,13 +269,13 @@ textarea.coding-rules-markdown-description {
 }
 
 .coding-rule-title {
-  line-height: 19.5px;
+  line-height: calc(2.5 * var(--gridSize));
   font-size: var(--baseFontSize);
 }
 
 .coding-rule-meta {
+  padding: calc(0.25 * var(--gridSize));
   padding-left: 30px;
-  line-height: 19.5px;
   font-size: var(--smallFontSize);
 }
 
@@ -280,14 +284,6 @@ textarea.coding-rules-markdown-description {
   font-size: var(--smallFontSize);
 }
 
-.coding-rule-meta .js-tag:after {
-  content: ',';
-}
-
-.coding-rule-meta .js-tag:last-child:after {
-  content: '';
-}
-
 .coding-rule-activation {
   width: 40px;
   line-height: 19.5px;
diff --git a/server/sonar-web/src/main/js/components/icons-components/RuleScopeIcon.tsx b/server/sonar-web/src/main/js/components/icons-components/RuleScopeIcon.tsx
new file mode 100644 (file)
index 0000000..27dcdc2
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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 { IconProps } from './types';
+
+export default function RuleScopeIcon({ className, fill = 'currentColor', size = 16 }: IconProps) {
+  return (
+    <svg
+      className={className}
+      width={size}
+      height={size}
+      viewBox="0 0 16 16"
+      version="1.1"
+      xmlnsXlink="http://www.w3.org/1999/xlink"
+      xmlSpace="preserve">
+      <path
+        style={{ fill }}
+        d="M8 3.071c2.724 0 4.929 2.204 4.929 4.929s-2.204 4.929-4.929 4.929c-2.724 0-4.929-2.204-4.929-4.929s2.204-4.929 4.929-4.929zM8 1.357c-3.669 0-6.643 2.974-6.643 6.643s2.974 6.643 6.643 6.643 6.643-2.974 6.643-6.643-2.974-6.643-6.643-6.643zM8 6.286c0.945 0 1.714 0.769 1.714 1.714s-0.769 1.714-1.714 1.714-1.714-0.769-1.714-1.714 0.769-1.714 1.714-1.714zM8 4.571c-1.893 0-3.429 1.535-3.429 3.429s1.535 3.429 3.429 3.429 3.429-1.535 3.429-3.429-1.535-3.429-3.429-3.429z"
+      />
+    </svg>
+  );
+}
index 9b7931c4722c818fded04f9a1870e21d72b3aa29..eaf08bd4fb6e6338988a5c354a37f56a5c5d2622 100644 (file)
@@ -20,6 +20,7 @@
 import * as React from 'react';
 import * as classNames from 'classnames';
 import './TagsList.css';
+import DropdownIcon from '../icons-components/DropdownIcon';
 
 interface Props {
   allowUpdate?: boolean;
@@ -32,7 +33,7 @@ export default function TagsList({ allowUpdate = false, className, tags }: Props
     <span className={classNames('tags-list', className)} title={tags.join(', ')}>
       <i className="icon-tags" />
       <span className="text-ellipsis">{tags.join(', ')}</span>
-      {allowUpdate && <i className="icon-dropdown" />}
+      {allowUpdate && <DropdownIcon />}
     </span>
   );
 }
index d43058542636aa68800cf9b6382c0a1cd08c50f1..3ea92ee6e2020ab722c86701fdccc917d32dc3ea 100644 (file)
@@ -13,9 +13,7 @@ exports[`should render with a caret on the right if update is allowed 1`] = `
   >
     foo, bar
   </span>
-  <i
-    className="icon-dropdown"
-  />
+  <DropdownIcon />
 </span>
 `;
 
index 3836796305825d80bc2751cfbcfe2070d026683a..5cf34fe37e324123513846d3d78a89502ed5794b 100644 (file)
@@ -25,26 +25,27 @@ import CodeSmellIcon from '../icons-components/CodeSmellIcon';
 interface Props {
   className?: string;
   query: string;
+  size?: number;
 }
 
-export default function IssueTypeIcon(props: Props) {
+export default function IssueTypeIcon({ className, query, size }: Props) {
   let icon;
 
-  switch (props.query.toLowerCase()) {
+  switch (query.toLowerCase()) {
     case 'bug':
     case 'bugs':
     case 'new_bugs':
-      icon = <BugIcon />;
+      icon = <BugIcon size={size} />;
       break;
     case 'vulnerability':
     case 'vulnerabilities':
     case 'new_vulnerabilities':
-      icon = <VulnerabilityIcon />;
+      icon = <VulnerabilityIcon size={size} />;
       break;
     case 'code_smell':
     case 'code_smells':
     case 'new_code_smells':
-      icon = <CodeSmellIcon />;
+      icon = <CodeSmellIcon size={size} />;
       break;
   }
 
@@ -52,5 +53,5 @@ export default function IssueTypeIcon(props: Props) {
     return null;
   }
 
-  return props.className ? <span className={props.className}>{icon}</span> : icon;
+  return className ? <span className={className}>{icon}</span> : icon;
 }
index 5a2a3cf89817941c0090c8b9c2fc8773b46d7af2..f4e5b41e0eb9d2b1181672f30c70982000736494 100644 (file)
@@ -1302,6 +1302,11 @@ coding_rules.remediation_function.coeff=Coeff
 coding_rules.remediation_function.offset=Offset
 coding_rules.remediation_function.constant=Constant
 
+coding_rules.scope.title=Analysis Scope
+coding_rules.scope.MAIN=Main sources
+coding_rules.scope.TEST=Test sources
+coding_rules.scope.ALL=Main and Test sources
+
 #------------------------------------------------------------------------------
 #
 # EMAIL CONFIGURATION