]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7897 Update measures on the Projects page (#1237)
authorStas Vilchik <vilchiks@gmail.com>
Tue, 13 Sep 2016 09:49:17 +0000 (11:49 +0200)
committerGitHub <noreply@github.com>
Tue, 13 Sep 2016 09:49:17 +0000 (11:49 +0200)
server/sonar-web/src/main/js/apps/code/actions/index.js
server/sonar-web/src/main/js/apps/code/components/Code.js
server/sonar-web/src/main/js/apps/code/components/Component.js
server/sonar-web/src/main/js/apps/code/components/ComponentMeasure.js
server/sonar-web/src/main/js/apps/code/components/ComponentsHeader.js
server/sonar-web/tests/apps/code/components-test.js
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 2422d9933624d45b31be167da439eee85b4cd006..c765e9ed755e879f659ea77e2b7ea16dbac3c3fc 100644 (file)
@@ -24,6 +24,15 @@ import { getChildren, getComponent, getTree, getBreadcrumbs } from '../../../api
 import { translate } from '../../../helpers/l10n';
 import { getComponentUrl } from '../../../helpers/urls';
 
+const VIEW_METRICS = [
+  'releasability_rating',
+  'alert_status',
+  'reliability_rating',
+  'security_rating',
+  'sqale_rating',
+  'ncloc'
+];
+
 const METRICS = [
   'ncloc',
   'code_smells',
@@ -120,16 +129,18 @@ function getPath (componentKey) {
   return '/' + encodeURIComponent(componentKey);
 }
 
-function expandRootDir ({ children, total, ...other }) {
-  const rootDir = children.find(component => component.qualifier === 'DIR' && component.name === '/');
-  if (rootDir) {
-    return getChildren(rootDir.key, METRICS_WITH_COVERAGE).then(r => {
-      const nextChildren = _.without([...children, ...r.components], rootDir);
-      const nextTotal = total + r.components.length - /* root dir */ 1;
-      return { children: nextChildren, total: nextTotal, ...other };
-    });
-  } else {
-    return { children, total, ...other };
+function expandRootDir (metrics) {
+  return function ({ children, total, ...other }) {
+    const rootDir = children.find(component => component.qualifier === 'DIR' && component.name === '/');
+    if (rootDir) {
+      return getChildren(rootDir.key, metrics).then(r => {
+        const nextChildren = _.without([...children, ...r.components], rootDir);
+        const nextTotal = total + r.components.length - /* root dir */ 1;
+        return { children: nextChildren, total: nextTotal, ...other };
+      });
+    } else {
+      return { children, total, ...other };
+    }
   }
 }
 
@@ -143,16 +154,16 @@ function skipRootDir (breadcrumbs) {
   });
 }
 
-function retrieveComponentBase (componentKey, candidate) {
+function retrieveComponentBase (componentKey, candidate, metrics) {
   return candidate ?
       Promise.resolve(candidate) :
-      getComponent(componentKey, METRICS_WITH_COVERAGE);
+      getComponent(componentKey, metrics);
 }
 
-function retrieveComponentChildren (componentKey, candidate) {
+function retrieveComponentChildren (componentKey, candidate, metrics) {
   return candidate && candidate.children ?
       Promise.resolve({ children: candidate.children, total: candidate.total }) :
-      getChildren(componentKey, METRICS_WITH_COVERAGE, { ps: PAGE_SIZE }).then(prepareChildren).then(expandRootDir);
+      getChildren(componentKey, metrics, { ps: PAGE_SIZE }).then(prepareChildren).then(expandRootDir(metrics));
 }
 
 function retrieveComponentBreadcrumbs (componentKey, candidate) {
@@ -161,11 +172,12 @@ function retrieveComponentBreadcrumbs (componentKey, candidate) {
       getBreadcrumbs({ key: componentKey }).then(skipRootDir);
 }
 
-function retrieveComponent (componentKey, bucket) {
+function retrieveComponent (componentKey, bucket, isView) {
   const candidate = _.findWhere(bucket, { key: componentKey });
+  const metrics = isView ? VIEW_METRICS : METRICS_WITH_COVERAGE;
   return Promise.all([
-    retrieveComponentBase(componentKey, candidate),
-    retrieveComponentChildren(componentKey, candidate),
+    retrieveComponentBase(componentKey, candidate, metrics),
+    retrieveComponentChildren(componentKey, candidate, metrics),
     retrieveComponentBreadcrumbs(componentKey, candidate)
   ]);
 }
@@ -193,10 +205,13 @@ async function getErrorMessage (response) {
   }
 }
 
-export function initComponent (componentKey, breadcrumbs) {
+export function initComponent (component, breadcrumbs) {
   return dispatch => {
+    const componentKey = component.key;
+    const isView = component.qualifier === 'VW' || component.qualifier === 'SVW';
+    const metrics = isView ? VIEW_METRICS : METRICS_WITH_COVERAGE;
     dispatch(startFetching());
-    return getComponent(componentKey, METRICS_WITH_COVERAGE)
+    return getComponent(componentKey, metrics)
         .then(component => dispatch(initComponentAction(component, breadcrumbs)))
         .then(() => dispatch(replacePath(getPath(componentKey))))
         .then(() => dispatch(stopFetching()));
@@ -205,9 +220,9 @@ export function initComponent (componentKey, breadcrumbs) {
 
 export function browse (componentKey) {
   return (dispatch, getState) => {
-    const { bucket } = getState();
+    const { bucket, current } = getState();
     dispatch(startFetching());
-    return retrieveComponent(componentKey, bucket)
+    return retrieveComponent(componentKey, bucket, current.isView)
         .then(([component, children, breadcrumbs]) => {
           if (component.refKey) {
             window.location = getComponentUrl(component.refKey);
index 16ea3bd17676306ed1231033a01c5d422757a48d..aec9d8e724c752f284b95f1613310551defb247e 100644 (file)
@@ -32,7 +32,7 @@ class Code extends Component {
   componentDidMount () {
     const { dispatch, component, routing } = this.props;
     const selectedKey = (routing.path && decodeURIComponent(routing.path.substr(1))) || component.key;
-    dispatch(initComponent(component.key, component.breadcrumbs))
+    dispatch(initComponent(component, component.breadcrumbs))
         .then(() => dispatch(browse(selectedKey)));
   }
 
index 47efb73c58cc1fe97d9b1ea8dd506c36bc3d608c..ffbab8c9d31cc5c7627856588d34793e2efd34ea 100644 (file)
@@ -76,7 +76,21 @@ class Component extends React.Component {
       }
     }
 
-    /* eslint object-shorthand: 0 */
+    const columns = isView ? [
+      { metric: 'releasability_rating', type: 'RATING' },
+      { metric: 'reliability_rating', type: 'RATING' },
+      { metric: 'security_rating', type: 'RATING' },
+      { metric: 'sqale_rating', type: 'RATING' },
+      { metric: 'ncloc', type: 'SHORT_INT' },
+    ] : [
+      { metric: 'ncloc', type: 'SHORT_INT' },
+      { metric: 'bugs', type: 'SHORT_INT' },
+      { metric: 'vulnerabilities', type: 'SHORT_INT' },
+      { metric: 'code_smells', type: 'SHORT_INT' },
+      { metric: coverageMetric, type: 'PERCENT' },
+      { metric: 'duplicated_lines_density', type: 'PERCENT' }
+    ];
+
     return (
         <tr className={classNames({ selected })}>
           <td className="thin nowrap">
@@ -85,63 +99,22 @@ class Component extends React.Component {
             </span>
           </td>
           <td className="code-name-cell">
-            {isView && (
-                <ComponentQualityGate
-                    component={component}/>
-            )}
             <ComponentName
                 component={component}
                 previous={previous}
                 onBrowse={onBrowse}/>
           </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey="ncloc"
-                  metricType="SHORT_INT"/>
-            </div>
-          </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey="bugs"
-                  metricType="SHORT_INT"/>
-            </div>
-          </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey="vulnerabilities"
-                  metricType="SHORT_INT"/>
-            </div>
-          </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey="code_smells"
-                  metricType="SHORT_INT"/>
-            </div>
-          </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey={coverageMetric}
-                  metricType="PERCENT"/>
-            </div>
-          </td>
-          <td className="thin nowrap text-right">
-            <div className="code-components-cell">
-              <ComponentMeasure
-                  component={component}
-                  metricKey="duplicated_lines_density"
-                  metricType="PERCENT"/>
-            </div>
-          </td>
+
+          {columns.map(column => (
+              <td key={column.metric} className="thin nowrap text-right">
+                <div className="code-components-cell">
+                  <ComponentMeasure
+                      component={component}
+                      metricKey={column.metric}
+                      metricType={column.type}/>
+                </div>
+              </td>
+          ))}
         </tr>
     );
   }
index a4a31655b74098e24949c03b5bc75a34fcbd7fb3..4938464a414654c26e829d147cd2e2cf8ca4c43b 100644 (file)
  */
 import _ from 'underscore';
 import React from 'react';
-
-import { formatMeasure } from '../../../helpers/measures';
+import Measure from '../../component-measures/components/Measure';
 
 const ComponentMeasure = ({ component, metricKey, metricType }) => {
-  const measure = _.findWhere(component.measures, { metric: metricKey });
+  const isProject = component.qualifier === 'TRK';
+  const isReleasability = metricKey === 'releasability_rating';
+
+  const finalMetricKey = (isProject && isReleasability) ? 'alert_status' : metricKey;
+  const finalMetricType = (isProject && isReleasability) ? 'LEVEL' : metricType;
+
+  const measure = _.findWhere(component.measures, { metric: finalMetricKey });
+
+  if (!measure) {
+    return <span/>;
+  }
+
   return (
-      <span>
-        {measure ? formatMeasure(measure.value, metricType) : ''}
-      </span>
+      <Measure measure={measure} metric={{ key: finalMetricKey, type: finalMetricType }}/>
   );
 };
 
index bbe0b097494d776961dbd5f34bc657cc6b1fa28a..8b071f136ff0af0b754a1d19cea3b361b53c24f6 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import React from 'react';
-
+import { connect } from 'react-redux';
 import { translate } from '../../../helpers/l10n';
 
-const ComponentsHeader = ({ baseComponent }) => (
-    <thead>
-      <tr>
-        <th className="thin nowrap">&nbsp;</th>
-        <th>&nbsp;</th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.ncloc.name')}
-        </th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.bugs.name')}
-        </th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.vulnerabilities.name')}
-        </th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.code_smells.name')}
-        </th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.coverage.name')}
-        </th>
-        <th className="thin nowrap text-right code-components-cell">
-          {baseComponent && translate('metric.duplicated_lines_density.short_name')}
-        </th>
-      </tr>
-    </thead>
-);
+const ComponentsHeader = ({ baseComponent, isView }) => {
+  const columns = isView ? [
+    translate('metric_domain.Releasability'),
+    translate('metric_domain.Reliability'),
+    translate('metric_domain.Security'),
+    translate('metric_domain.Maintainability'),
+    translate('metric', 'ncloc', 'name')
+  ] : [
+    translate('metric', 'ncloc', 'name'),
+    translate('metric', 'bugs', 'name'),
+    translate('metric', 'vulnerabilities', 'name'),
+    translate('metric', 'code_smells', 'name'),
+    translate('metric', 'coverage', 'name'),
+    translate('metric', 'duplicated_lines_density', 'short_name')
+  ];
+
+  return (
+      <thead>
+        <tr>
+          <th className="thin nowrap">&nbsp;</th>
+          <th>&nbsp;</th>
+          {columns.map(column => (
+              <th key={column} className="thin nowrap text-right code-components-cell">
+                {baseComponent && column}
+              </th>
+          ))}
+        </tr>
+      </thead>
+  );
+};
+
+function mapStateToProps (state) {
+  return {
+    isView: state.current.isView
+  };
+}
+
+export default connect(mapStateToProps)(ComponentsHeader);
 
-export default ComponentsHeader;
index 9613032c75f01b64b524a35c2dbabd6bb51b0a9a..26192a5b21023d0c6f3bc4562e43fc53b41bba26 100644 (file)
@@ -3,7 +3,6 @@ import sinon from 'sinon';
 import sinonChai from 'sinon-chai';
 import { shallow } from 'enzyme';
 import React from 'react';
-import TestUtils from 'react-addons-test-utils';
 
 import Breadcrumb from '../../../src/main/js/apps/code/components/Breadcrumb';
 import Breadcrumbs from '../../../src/main/js/apps/code/components/Breadcrumbs';
@@ -104,10 +103,12 @@ describe('Code :: Components', () => {
           <ComponentMeasure
               component={exampleComponent}
               metricKey="ncloc"
-              metricType="SHORT_INT"/>);
+              metricType="SHORT_INT"/>
+      ).find('Measure');
 
-      expect(output.text())
-          .to.equal('9.8k');
+      expect(output.length).to.equal(1);
+      expect(output.prop('measure')).to.deep.equal({ metric: 'ncloc', value: 9757 });
+      expect(output.prop('metric')).to.deep.equal({ key: 'ncloc', type: 'SHORT_INT' });
     });
 
     it('should not render measure', () => {
index 4a0d83cf6bf8be299fb3169a8781402a6a7270a7..bfdc872a746ce4a3753d3abef398a9c40a0caac4 100644 (file)
@@ -1276,6 +1276,7 @@ metric_domain.General=General
 metric_domain.Integration Tests=Integration Tests
 metric_domain.Issues=Issues
 metric_domain.Maintainability=Maintainability
+metric_domain.Releasability=Releasability
 metric_domain.Reliability=Reliability
 metric_domain.Rules=Rules
 metric_domain.SCM=SCM