]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7069 Improve support of views on the overview page
authorStas Vilchik <vilchiks@gmail.com>
Mon, 30 Nov 2015 10:24:50 +0000 (11:24 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 30 Nov 2015 12:32:34 +0000 (13:32 +0100)
server/sonar-web/src/main/js/apps/overview/components/domain-bubble-chart.js
server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js
server/sonar-web/src/main/js/apps/overview/domains/size-domain.js
server/sonar-web/src/main/js/apps/overview/gate/gate.js
server/sonar-web/src/main/js/apps/overview/meta.js
server/sonar-web/src/main/webapp/WEB-INF/app/views/overview/index.html.erb

index f67d5d02873d5944c259e2ce8446d1099853ec89..69c2be4f1ba369d4691325fef4969c400511e68d 100644 (file)
@@ -102,6 +102,10 @@ export class DomainBubbleChart extends React.Component {
   }
 
   render () {
+    if (this.props.component.qualifier === 'DEV' || this.props.component.qualifier === 'VW') {
+      return null;
+    }
+
     return <div className="overview-domain-chart">
       <div className="overview-card-header">
         <h2 className="overview-title">{window.t('overview.chart.files')}</h2>
index d153b98ef1e44580cdd45294904a67b506648768..0014cd54e9fa5e141bc888ce2fb1991a291d7772 100644 (file)
@@ -62,11 +62,21 @@ export class DomainTreemap extends React.Component {
     </div>;
   }
 
+  renderWhenNoData () {
+    return <div className="overview-chart-placeholder" style={{ height: HEIGHT }}>
+      {window.t('no_data')}
+    </div>;
+  }
+
   renderTreemap () {
     if (this.state.loading) {
       return this.renderLoading();
     }
 
+    if (!this.state.components.length) {
+      return this.renderWhenNoData();
+    }
+
     // TODO filter out zero sized components
     let items = this.state.components.map(component => {
       let colorMeasure = this.props.colorMetric ? component.measures[this.props.colorMetric] : null;
index dcdab0821fddd2d9da0ab7281b898a15bb76edc6..18f0f4caddf3a7f0a36e78814c15d4ec9f6ba3b9 100644 (file)
@@ -90,6 +90,43 @@ export const SizeMain = React.createClass({
     return this.renderOtherMeasures('Documentation', []);
   },
 
+  renderLanguageDistribution() {
+    let distribution = this.state.measures['ncloc_language_distribution'];
+    if (distribution == null) {
+      return null;
+    }
+    return <LanguageDistribution lines={this.state.measures['ncloc']} distribution={distribution}/>;
+  },
+
+  renderComplexityDistribution(distribution, props) {
+    if (distribution == null) {
+      return null;
+    }
+    return <ComplexityDistribution distribution={distribution} {...props}/>
+  },
+
+  renderComplexityCard() {
+    if (this.state.measures['complexity'] == null) {
+      return null;
+    }
+
+    return <div className="overview-detailed-layout-column">
+      <div className="overview-detailed-measures-list">
+        <DetailedMeasure {...this.props} {...this.state} metric="complexity" type="INT"/>
+        <DetailedMeasure {...this.props} {...this.state} metric="function_complexity" type="FLOAT">
+          {this.renderComplexityDistribution(this.state.measures['function_complexity_distribution'],
+              { of: 'function' })}
+        </DetailedMeasure>
+        <DetailedMeasure {...this.props} {...this.state} metric="file_complexity" type="FLOAT">
+          {this.renderComplexityDistribution(this.state.measures['file_complexity_distribution'],
+              { of: 'file' })}
+        </DetailedMeasure>
+        <DetailedMeasure {...this.props} {...this.state} metric="class_complexity" type="FLOAT"/>
+        {this.renderOtherComplexityMeasures()}
+      </div>
+    </div>;
+  },
+
   render () {
     if (!this.state.ready) {
       return this.renderLoading();
@@ -105,30 +142,13 @@ export const SizeMain = React.createClass({
           <div className="overview-detailed-layout-column">
             <div className="overview-detailed-measures-list">
               <DetailedMeasure {...this.props} {...this.state} metric="ncloc" type="INT">
-                <LanguageDistribution lines={this.state.measures['ncloc']}
-                                      distribution={this.state.measures['ncloc_language_distribution']}/>
+                {this.renderLanguageDistribution()}
               </DetailedMeasure>
               {this.renderOtherSizeMeasures()}
             </div>
           </div>
 
-          <div className="overview-detailed-layout-column">
-            <div className="overview-detailed-measures-list">
-              <DetailedMeasure {...this.props} {...this.state} metric="complexity" type="INT"/>
-              <DetailedMeasure {...this.props} {...this.state} metric="function_complexity" type="FLOAT">
-                <ComplexityDistribution
-                    distribution={this.state.measures['function_complexity_distribution']}
-                    of="function"/>
-              </DetailedMeasure>
-              <DetailedMeasure {...this.props} {...this.state} metric="file_complexity" type="FLOAT">
-                <ComplexityDistribution
-                    distribution={this.state.measures['file_complexity_distribution']}
-                    of="file"/>
-              </DetailedMeasure>
-              <DetailedMeasure {...this.props} {...this.state} metric="class_complexity" type="FLOAT"/>
-              {this.renderOtherComplexityMeasures()}
-            </div>
-          </div>
+          {this.renderComplexityCard()}
 
           <div className="overview-detailed-layout-column">
             <div className="overview-detailed-measures-list">
index 076cbcd376a100de1945ca3862c0f3717c631929..97592b684559fd4f5ab62e17bdf6921fc0eb1f5f 100644 (file)
@@ -5,6 +5,22 @@ import GateEmpty from './gate-empty';
 
 
 export default React.createClass({
+  renderGateConditions () {
+    return <GateConditions gate={this.props.gate} component={this.props.component}/>;
+  },
+
+  renderGateText () {
+    let text = '';
+    if (this.props.gate.level === 'ERROR') {
+      text = window.t('widget.alerts.errors') + this.props.gate.text + '.';
+    } else if (this.props.gate.level === 'WARN') {
+      text = window.t('widget.alerts.warnings') + this.props.gate.text + '.';
+    } else {
+      text = window.t('widget.alerts.no_alert');
+    }
+    return <div className="overview-card">{text}</div>;
+  },
+
   render() {
     if (!this.props.gate || !this.props.gate.level) {
       return this.props.component.qualifier === 'TRK' ? <GateEmpty/> : null;
@@ -20,7 +36,7 @@ export default React.createClass({
             {window.t('overview.quality_gate')}
             <span className={badgeClassName}>{badgeText}</span>
           </h2>
-          <GateConditions gate={this.props.gate} component={this.props.component}/>
+          {this.props.gate.conditions ? this.renderGateConditions() : this.renderGateText()}
         </div>
     );
   }
index e6a48e71e09193d01424957ce8d13f34fd7ecfee..dea84f078995a927106db368ede0cd249b30f32a 100644 (file)
@@ -4,9 +4,16 @@ import { QualityProfileLink } from './../../components/shared/quality-profile-li
 import { QualityGateLink } from './../../components/shared/quality-gate-link';
 
 export default React.createClass({
+  isView() {
+    return this.props.component.qualifier === 'VW' || this.props.component.qualifier === 'SVW';
+  },
+
+  isDeveloper() {
+    return this.props.component.qualifier === 'DEV';
+  },
+
   render() {
-    let
-        profiles = (this.props.component.profiles || []).map(profile => {
+    let profiles = (this.props.component.profiles || []).map(profile => {
           return (
               <li key={profile.key}>
                 <span className="note spacer-right">({profile.language})</span>
@@ -36,21 +43,23 @@ export default React.createClass({
             </div>
         ) : null,
 
-        profilesCard = _.size(this.props.component.profiles) > 0 ? (
+        profilesCard = !this.isView() && !this.isDeveloper() && _.size(this.props.component.profiles) > 0 ? (
             <div className="overview-meta-card">
               <h4 className="overview-meta-header">{window.t('overview.quality_profiles')}</h4>
               <ul className="overview-meta-list">{profiles}</ul>
             </div>
         ) : null,
 
-        gateCard = this.props.component.gate ? (
+        gateCard = !this.isView() && !this.isDeveloper() && this.props.component.gate ? (
             <div className="overview-meta-card">
               <h4 className="overview-meta-header">{window.t('overview.quality_gate')}</h4>
               <ul className="overview-meta-list">
                 <li>
                   {this.props.component.gate.isDefault ?
                       <span className="note spacer-right">(Default)</span> : null}
-                  <QualityGateLink gate={this.props.component.gate.key}>{this.props.component.gate.name}</QualityGateLink>
+                  <QualityGateLink gate={this.props.component.gate.key}>
+                    {this.props.component.gate.name}
+                  </QualityGateLink>
                 </li>
               </ul>
             </div>
index 450678e7a4ce64b6abc6578a2abe8e7b0feb4d4d..f81ae58beb355ed7b581368182dbd09956dd792d 100644 (file)
 <%
    if @snapshot
      m = @snapshot.measure(Metric::QUALITY_GATE_DETAILS)
+     alert_status = @snapshot.measure(Metric::ALERT_STATUS)
      if m && !m.data.blank?
        details = JSON.parse m.data
        m.alert_status = details['level']
        raw_conditions = details['conditions']
        conditions = []
-       missing_metric = false
        raw_conditions.each do |condition|
-         if metric(condition['metric']).nil?
-           missing_metric = true
-         else
+         if !metric(condition['metric']).nil?
            conditions << condition
          end
        end
-       alert_metric = metric(Metric::ALERT_STATUS)
      end
    end
 %>
         ]
       };
       <% else %>
-      var gate = null;
+        <% if alert_status && !alert_status.alert_status.blank? %>
+          var gate = {
+            level: '<%= alert_status.alert_status -%>',
+            text: '<%= alert_status.alert_text -%>'
+          };
+        <% else %>
+          var gate = null;
+         <% end %>
       <% end %>
 
       window.sonarqube.overview = {