]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9546 Display only the first custom graph as preview on project dashboard
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Tue, 18 Jul 2017 13:24:50 +0000 (15:24 +0200)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Wed, 19 Jul 2017 08:10:10 +0000 (10:10 +0200)
server/sonar-web/src/main/js/apps/overview/events/PreviewGraph.js
server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltips.js
server/sonar-web/src/main/js/apps/overview/events/PreviewGraphTooltipsContent.js
server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltips-test.js.snap
server/sonar-web/src/main/js/apps/overview/events/__tests__/__snapshots__/PreviewGraphTooltipsContent-test.js.snap
server/sonar-web/src/main/js/apps/overview/styles.css
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.js
server/sonar-web/src/main/js/apps/projectActivity/utils.js
server/sonar-web/src/main/js/components/charts/ZoomTimeLine.js

index aea2204b3c9188597a4b3b65bca7b99044c63a42..ed1bc391b187467dbfd941f259cc64ef4c250ae5 100644 (file)
@@ -24,7 +24,8 @@ import { AutoSizer } from 'react-virtualized';
 import {
   getDisplayedHistoryMetrics,
   generateSeries,
-  getSeriesMetricType
+  getSeriesMetricType,
+  splitSeriesInGraphs
 } from '../../projectActivity/utils';
 import { getCustomGraph, getGraph } from '../../../helpers/storage';
 import AdvancedTimeline from '../../../components/charts/AdvancedTimeline';
@@ -50,6 +51,8 @@ type State = {
 };
 
 const GRAPH_PADDING = [4, 0, 4, 0];
+const MAX_GRAPH_NB = 1;
+const MAX_SERIES_PER_GRAPH = 3;
 
 export default class PreviewGraph extends React.PureComponent {
   props: Props;
@@ -59,11 +62,16 @@ export default class PreviewGraph extends React.PureComponent {
     super(props);
     const graph = getGraph();
     const customMetrics = getCustomGraph();
+    const series = splitSeriesInGraphs(
+      this.getSeries(props.history, graph, customMetrics, props.metrics),
+      MAX_GRAPH_NB,
+      MAX_SERIES_PER_GRAPH
+    );
     this.state = {
       customMetrics,
       graph,
       selectedDate: null,
-      series: this.getSeries(props.history, graph, customMetrics, props.metrics),
+      series: series.length > 0 ? series[0] : [],
       tooltipIdx: null,
       tooltipXPos: null
     };
@@ -73,16 +81,21 @@ export default class PreviewGraph extends React.PureComponent {
     if (nextProps.history !== this.props.history || nextProps.metrics !== this.props.metrics) {
       const graph = getGraph();
       const customMetrics = getCustomGraph();
+      const series = splitSeriesInGraphs(
+        this.getSeries(nextProps.history, graph, customMetrics, nextProps.metrics),
+        MAX_GRAPH_NB,
+        MAX_SERIES_PER_GRAPH
+      );
       this.setState({
         customMetrics,
         graph,
-        series: this.getSeries(nextProps.history, graph, customMetrics, nextProps.metrics)
+        series: series.length > 0 ? series[0] : []
       });
     }
   }
 
   formatValue = (tick: number | string) =>
-    formatMeasure(tick, getShortType(this.state.series[0].type));
+    formatMeasure(tick, getShortType(getSeriesMetricType(this.state.series)));
 
   getDisplayedMetrics = (graph: string, customMetrics: Array<string>): Array<string> => {
     const metrics: Array<string> = getDisplayedHistoryMetrics(graph, customMetrics);
@@ -92,7 +105,12 @@ export default class PreviewGraph extends React.PureComponent {
     return metrics;
   };
 
-  getSeries = (history: ?History, graph: string, customMetrics: Array<string>, metrics: Array<Metric>) => {
+  getSeries = (
+    history: ?History,
+    graph: string,
+    customMetrics: Array<string>,
+    metrics: Array<Metric>
+  ): Array<Serie> => {
     const myHistory = history;
     if (!myHistory) {
       return [];
index baf2738df615aa73091ff93edc5b64c1b6b66563..7c348aa5f2087095a0b97cc645ab59fb9b70d5ce 100644 (file)
@@ -35,7 +35,7 @@ type Props = {
   tooltipPos: number
 };
 
-const TOOLTIP_WIDTH = 150;
+const TOOLTIP_WIDTH = 160;
 
 export default class PreviewGraphTooltips extends React.PureComponent {
   props: Props;
index a68e72cc9180b57a411ff1fa53a71343f5d7c147..dfdab1902b568b881d35e4cb7f5dd85d2ed3b8f0 100644 (file)
@@ -38,7 +38,7 @@ export default function PreviewGraphTooltipsContent({ style, translatedName, val
       <td className="overview-analysis-graph-tooltip-value text-right little-spacer-right thin">
         {value}
       </td>
-      <td className="text-ellipsis">
+      <td className="text-ellipsis overview-analysis-graph-tooltip-description">
         {translatedName}
       </td>
     </tr>
index 997962effe7ad1c15c75d33d840305e9aa1e2d09..0d0aec9012c0619c9d0157285774bf974b3dc1c6 100644 (file)
@@ -5,9 +5,9 @@ exports[`should render correctly 1`] = `
   customClass="bubble-popup-right"
   position={
     Object {
-      "left": -125,
+      "left": -135,
       "top": 16,
-      "width": 150,
+      "width": 160,
     }
   }
 >
index db45985ac211ee7da46739071ec7e564d7cdd004..4019b80bbe15a8066a22bcc74addd61c7b9a2ed4 100644 (file)
@@ -17,7 +17,7 @@ exports[`should render correctly 1`] = `
     1.2k
   </td>
   <td
-    className="text-ellipsis"
+    className="text-ellipsis overview-analysis-graph-tooltip-description"
   >
     Code Smells
   </td>
index 390ca241dea7b3facd469cd6bc06ac89f2ef4716..8744bb255b3939685fd964b00e20d04c672ab4e8 100644 (file)
   font-weight: bold;
 }
 
+.overview-analysis-graph-tooltip-description {
+  max-width: 120px;
+}
+
 .overview-analysis-event {
 }
 
index a743645085c1a4657c860940bca3f2f6f4937703..08feb4a59531c83da40ee542a9059936e66485c4 100644 (file)
  */
 // @flow
 import React from 'react';
-import { debounce, findLast, maxBy, minBy, sortBy, groupBy, flatMap, chunk } from 'lodash';
+import { debounce, findLast, maxBy, minBy, sortBy } from 'lodash';
 import ProjectActivityGraphsHeader from './ProjectActivityGraphsHeader';
 import GraphsZoom from './GraphsZoom';
 import GraphsHistory from './GraphsHistory';
 import { getCustomGraph, saveCustomGraph, saveGraph } from '../../../helpers/storage';
 import {
   datesQueryChanged,
-  isCustomGraph,
   generateSeries,
   getDisplayedHistoryMetrics,
   getSeriesMetricType,
-  historyQueryChanged
+  historyQueryChanged,
+  isCustomGraph,
+  splitSeriesInGraphs
 } from '../utils';
 import type { RawQuery } from '../../../helpers/query';
 import type { Analysis, MeasureHistory, Metric, Query } from '../types';
@@ -70,7 +71,7 @@ export default class ProjectActivityGraphs extends React.PureComponent {
     );
     this.state = {
       series,
-      graphs: this.splitSeriesInGraphs(series),
+      graphs: splitSeriesInGraphs(series, MAX_GRAPH_NB, MAX_SERIES_PER_GRAPH),
       ...this.getStateZoomDates(null, props, series)
     };
     this.updateQueryDateRange = debounce(this.updateQueryDateRange, 500);
@@ -89,7 +90,7 @@ export default class ProjectActivityGraphs extends React.PureComponent {
         nextProps.metrics,
         getDisplayedHistoryMetrics(nextProps.query.graph, nextProps.query.customMetrics)
       );
-      newGraphs = this.splitSeriesInGraphs(newSeries);
+      newGraphs = splitSeriesInGraphs(newSeries, MAX_GRAPH_NB, MAX_SERIES_PER_GRAPH);
     }
 
     const newDates = this.getStateZoomDates(this.props, nextProps, newSeries);
@@ -152,11 +153,6 @@ export default class ProjectActivityGraphs extends React.PureComponent {
     this.props.updateQuery({ customMetrics });
   };
 
-  splitSeriesInGraphs = (series: Array<Serie>): Array<Array<Serie>> =>
-    flatMap(groupBy(series, serie => serie.type), groupType =>
-      chunk(groupType, MAX_SERIES_PER_GRAPH)
-    ).slice(0, MAX_GRAPH_NB);
-
   updateGraph = (graph: string) => {
     saveGraph(graph);
     if (isCustomGraph(graph) && this.props.query.customMetrics.length <= 0) {
index 83d08e5a171d3726541fbd1036ffd7f385f1e277..d4b52b6df7eb2f7038f67ea2b33d90465e7d1c64 100644 (file)
@@ -19,7 +19,7 @@
  */
 // @flow
 import moment from 'moment';
-import { isEqual, sortBy } from 'lodash';
+import { chunk, flatMap, groupBy, isEqual, sortBy } from 'lodash';
 import {
   cleanQuery,
   parseAsArray,
@@ -122,6 +122,13 @@ export const generateSeries = (
   );
 };
 
+export const splitSeriesInGraphs = (
+  series: Array<Serie>,
+  maxGraph: number,
+  maxSeries: number
+): Array<Array<Serie>> =>
+  flatMap(groupBy(series, serie => serie.type), type => chunk(type, maxSeries)).slice(0, maxGraph);
+
 export const getSeriesMetricType = (series: Array<Serie>): string =>
   series.length > 0 ? series[0].type : 'INT';
 
index 026dc15ac8947d98eceab37f2da191ddd8cf4006..d9b1e7562d74c88fe89eafe94baf1f0f664ecba6 100644 (file)
@@ -291,7 +291,7 @@ export default class ZoomTimeLine extends React.PureComponent {
         className="zoom-selection-handle"
         x={-3}
         y={options.yDim[1]}
-        height={options.yDim[0] - options.yDim[1]}
+        height={options.yDim[0] - options.yDim[1] + 1}
         width={6}
       />
     </Draggable>;
@@ -334,8 +334,8 @@ export default class ZoomTimeLine extends React.PureComponent {
             <rect
               className="zoom-selection"
               x={0}
-              y={yDim[1] + 1}
-              height={yDim[0] - yDim[1]}
+              y={yDim[1]}
+              height={yDim[0] - yDim[1] + 1}
               width={zoomBoxWidth}
               onDoubleClick={this.handleDoubleClick(xScale, xDim)}
             />
@@ -370,7 +370,7 @@ export default class ZoomTimeLine extends React.PureComponent {
     const { xScale, yScale } = this.getScales();
     return (
       <svg className="line-chart " width={this.props.width} height={this.props.height}>
-        <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
+        <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0] + 2})`}>
           {this.renderLeak(xScale, yScale)}
           {this.renderBaseLine(xScale, yScale)}
           {this.props.showXTicks && this.renderTicks(xScale, yScale)}