]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9806 Add the quality gate metric back for Views and Subviews
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 11 Aug 2017 14:05:21 +0000 (16:05 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Mon, 14 Aug 2017 09:44:44 +0000 (11:44 +0200)
server/sonar-web/src/main/js/apps/component-measures/components/AppContainer.js
server/sonar-web/src/main/js/apps/component-measures/components/MeasureContent.js
server/sonar-web/src/main/js/apps/component-measures/components/MeasureViewSelect.js
server/sonar-web/src/main/js/apps/component-measures/config/domains.js
server/sonar-web/src/main/js/apps/component-measures/sidebar/DomainFacet.js
server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.js
server/sonar-web/src/main/js/apps/component-measures/utils.js

index bcf1739c38ccd7483557e00dd60d6a15421346fd..38672597858c2dbcfd7136dfd869a325e51b8524 100644 (file)
@@ -43,7 +43,10 @@ const mapStateToProps = (state, ownProps) => ({
 });
 
 const banQualityGate = (component: Component): Array<Measure> => {
-  const bannedMetrics = ['alert_status'];
+  const bannedMetrics = [];
+  if (!['VW', 'SVW'].includes(component.qualifier)) {
+    bannedMetrics.push('alert_status');
+  }
   if (component.qualifier === 'APP') {
     bannedMetrics.push('releasability_rating', 'releasability_effort');
   }
index 0a403474482f5bc8dd918e150764377ed891c506..3b5552955bbd227d7bddfc33f84dddfeeee7ba8a 100644 (file)
@@ -196,7 +196,7 @@ export default class MeasureContent extends React.PureComponent {
       const component = this.state.components.find(
         component => component.refKey === componentKey || component.key === componentKey
       );
-      if (component && component.qualifier === 'TRK') {
+      if (component && component.refKey != null) {
         if (this.props.view === 'treemap') {
           this.props.router.push(getProjectUrl(componentKey));
         }
@@ -315,7 +315,8 @@ export default class MeasureContent extends React.PureComponent {
             </div>
           </div>
         </div>
-        {metric == null && <MetricNotFound className="layout-page-main-inner measure-details-content" />}
+        {metric == null &&
+          <MetricNotFound className="layout-page-main-inner measure-details-content" />}
         {metric != null &&
           measure != null &&
           <div className="layout-page-main-inner measure-details-content">
index ec33171709a8059ab3211fa3f3e8983b9cc6bccc..e17f12a85895aae718f52a57db3aa40382db54c4 100644 (file)
@@ -23,7 +23,7 @@ import Select from 'react-select';
 import ListIcon from '../../../components/icons-components/ListIcon';
 import TreeIcon from '../../../components/icons-components/TreeIcon';
 import TreemapIcon from '../../../components/icons-components/TreemapIcon';
-import { hasTreemap } from '../utils';
+import { hasList, hasTree, hasTreemap } from '../utils';
 import { translate } from '../../../helpers/l10n';
 import type { Metric } from '../../../store/metrics/actions';
 
@@ -40,27 +40,31 @@ export default class MeasureViewSelect extends React.PureComponent {
   getOptions = () => {
     const { metric } = this.props;
     const options = [];
-    options.push({
-      value: 'list',
-      label: (
-        <div>
-          <ListIcon className="little-spacer-right" />
-          {translate('component_measures.tab.list')}
-        </div>
-      ),
-      icon: <ListIcon />
-    });
-    options.push({
-      value: 'tree',
-      label: (
-        <div>
-          <TreeIcon className="little-spacer-right" />
-          {translate('component_measures.tab.tree')}
-        </div>
-      ),
-      icon: <TreeIcon />
-    });
-    if (hasTreemap(metric.type)) {
+    if (hasList(metric.key)) {
+      options.push({
+        value: 'list',
+        label: (
+          <div>
+            <ListIcon className="little-spacer-right" />
+            {translate('component_measures.tab.list')}
+          </div>
+        ),
+        icon: <ListIcon />
+      });
+    }
+    if (hasTree(metric.key)) {
+      options.push({
+        value: 'tree',
+        label: (
+          <div>
+            <TreeIcon className="little-spacer-right" />
+            {translate('component_measures.tab.tree')}
+          </div>
+        ),
+        icon: <TreeIcon />
+      });
+    }
+    if (hasTreemap(metric.key, metric.type)) {
       options.push({
         value: 'treemap',
         label: (
index 9f10d6f7b281a8cf4b7a7f5113bfe10a2bb669cc..274f09a5e864bb5af2e211285cb12259c6429095 100644 (file)
@@ -116,7 +116,7 @@ export const domains = {
   },
 
   Releasability: {
-    order: ['alert_status']
+    order: ['releasability_rating', 'releasability_effort', 'alert_status']
   },
 
   Issues: {
index 0efc611f94eadf6cd0060fb55a64ddfdd83462c6..7bdea166fd947d258fbe4e37692e9778bb3f9fad 100644 (file)
@@ -27,7 +27,7 @@ import FacetItemsList from '../../../components/facet/FacetItemsList';
 import FacetMeasureValue from './FacetMeasureValue';
 import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
 import Tooltip from '../../../components/controls/Tooltip';
-import { filterMeasures, hasBubbleChart, sortMeasures } from '../utils';
+import { filterMeasures, hasBubbleChart, hasFacetStat, sortMeasures } from '../utils';
 import {
   getLocalizedMetricDomain,
   getLocalizedMetricName,
@@ -119,7 +119,9 @@ export default class DomainFacet extends React.PureComponent {
                   </Tooltip>
                 }
                 onClick={this.props.onChange}
-                stat={<FacetMeasureValue measure={measure} />}
+                stat={
+                  hasFacetStat(measure.metric.key) ? <FacetMeasureValue measure={measure} /> : null
+                }
                 value={measure.metric.key}
               />
             )}
index f74f751656ded4d0d04d259a71c967bd9a7651be..465439125afb2585e8ef715f2a54d6107f4e5ebd 100644 (file)
@@ -21,7 +21,7 @@
 import React from 'react';
 import ProjectOverviewFacet from './ProjectOverviewFacet';
 import DomainFacet from './DomainFacet';
-import { groupByDomains, KNOWN_DOMAINS, PROJECT_OVERVEW } from '../utils';
+import { getDefaultView, groupByDomains, KNOWN_DOMAINS, PROJECT_OVERVEW } from '../utils';
 import type { MeasureEnhanced } from '../../../components/measure/types';
 import type { Query } from '../types';
 
@@ -67,9 +67,10 @@ export default class Sidebar extends React.PureComponent {
     }));
   };
 
-  resetSelection = () => ({ selected: null, view: 'list' });
+  resetSelection = (metric: string) => ({ selected: null, view: getDefaultView(metric) });
 
-  changeMetric = (metric: string) => this.props.updateQuery({ metric, ...this.resetSelection() });
+  changeMetric = (metric: string) =>
+    this.props.updateQuery({ metric, ...this.resetSelection(metric) });
 
   render() {
     return (
index a1cd1d3c2ac9082b68f40251fbc82e5ef12b56e2..0ae0a1dfa15ec903d02142735d2676a4ac5817c3 100644 (file)
@@ -112,11 +112,25 @@ export const groupByDomains = memoize((measures: Array<MeasureEnhanced>): Array<
   ]);
 });
 
-export const hasTreemap = (metricType: string): boolean =>
-  ['PERCENT', 'RATING', 'LEVEL'].includes(metricType);
+export const getDefaultView = (metric: string): string => {
+  if (!hasList(metric)) {
+    return 'tree';
+  }
+  return DEFAULT_VIEW;
+};
+
+export const hasList = (metric: string): boolean =>
+  !['releasability_rating', 'releasability_effort'].includes(metric);
+
+export const hasTree = (metric: string): boolean => metric !== 'alert_status';
+
+export const hasTreemap = (metric: string, type: string): boolean =>
+  ['PERCENT', 'RATING', 'LEVEL'].includes(type) && hasTree(metric);
 
 export const hasBubbleChart = (domainName: string): boolean => bubbles[domainName] != null;
 
+export const hasFacetStat = (metric: string): boolean => metric !== 'alert_status';
+
 export const getBubbleMetrics = (domain: string, metrics: { [string]: Metric }) => {
   const conf = bubbles[domain];
   return {
@@ -129,11 +143,24 @@ export const getBubbleMetrics = (domain: string, metrics: { [string]: Metric })
 
 export const isProjectOverview = (metric: string) => metric === PROJECT_OVERVEW;
 
-export const parseQuery = memoize((urlQuery: RawQuery): Query => ({
-  metric: parseAsString(urlQuery['metric']) || DEFAULT_METRIC,
-  selected: parseAsString(urlQuery['selected']),
-  view: parseAsString(urlQuery['view']) || DEFAULT_VIEW
-}));
+const parseView = memoize((rawView?: string, metric: string) => {
+  const view = parseAsString(rawView) || DEFAULT_VIEW;
+  if (!hasTree(metric)) {
+    return 'list';
+  } else if (view === 'list' && !hasList(metric)) {
+    return 'tree';
+  }
+  return view;
+});
+
+export const parseQuery = memoize((urlQuery: RawQuery): Query => {
+  const metric = parseAsString(urlQuery['metric']) || DEFAULT_METRIC;
+  return {
+    metric,
+    selected: parseAsString(urlQuery['selected']),
+    view: parseView(urlQuery['view'], metric)
+  };
+});
 
 export const serializeQuery = memoize((query: Query): RawQuery => {
   return cleanQuery({