Browse Source

graph legend: review fixes

Alexander Zobnin 7 years ago
parent
commit
44ed188c84

+ 47 - 36
public/app/plugins/panel/graph/Legend/Legend.tsx

@@ -57,6 +57,21 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps> {
     onColorChange: () => {},
     onColorChange: () => {},
   };
   };
 
 
+  onToggleSeries = (series, event) => {
+    this.props.onToggleSeries(series, event);
+    this.forceUpdate();
+  };
+
+  onToggleAxis = series => {
+    this.props.onToggleAxis(series);
+    this.forceUpdate();
+  };
+
+  onColorChange = (series, color) => {
+    this.props.onColorChange(series, color);
+    this.forceUpdate();
+  };
+
   sortLegend() {
   sortLegend() {
     let seriesList = this.props.seriesList || [];
     let seriesList = this.props.seriesList || [];
     if (this.props.sort) {
     if (this.props.sort) {
@@ -74,12 +89,6 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps> {
     return seriesList;
     return seriesList;
   }
   }
 
 
-  onToggleSeries(series: TimeSeries, event: Event) {
-    // const scrollPosition = legendScrollbar.scroller.scrollTop;
-    this.props.onToggleSeries(series, event);
-    // legendScrollbar.scroller.scrollTop = scrollPosition;
-  }
-
   render() {
   render() {
     const { optionalClass, hiddenSeries, rightSide, sideWidth, sort, sortDesc, hideEmpty, hideZero } = this.props;
     const { optionalClass, hiddenSeries, rightSide, sideWidth, sort, sortDesc, hideEmpty, hideZero } = this.props;
     const { values, min, max, avg, current, total } = this.props;
     const { values, min, max, avg, current, total } = this.props;
@@ -101,10 +110,10 @@ export class GraphLegend extends React.PureComponent<GraphLegendProps> {
     const legendProps: GraphLegendProps = {
     const legendProps: GraphLegendProps = {
       seriesList: seriesList,
       seriesList: seriesList,
       hiddenSeries: hiddenSeries,
       hiddenSeries: hiddenSeries,
-      onToggleSeries: (s, e) => this.onToggleSeries(s, e),
-      onToggleSort: (sortBy, sortDesc) => this.props.onToggleSort(sortBy, sortDesc),
-      onColorChange: (series, color) => this.props.onColorChange(series, color),
-      onToggleAxis: series => this.props.onToggleAxis(series),
+      onToggleSeries: this.onToggleSeries,
+      onToggleAxis: this.onToggleAxis,
+      onToggleSort: this.props.onToggleSort,
+      onColorChange: this.onColorChange,
       ...seriesValuesProps,
       ...seriesValuesProps,
       ...sortProps,
       ...sortProps,
     };
     };
@@ -121,23 +130,22 @@ class LegendSeriesList extends React.PureComponent<GraphLegendProps> {
   render() {
   render() {
     const { seriesList, hiddenSeries, values, min, max, avg, current, total } = this.props;
     const { seriesList, hiddenSeries, values, min, max, avg, current, total } = this.props;
     const seriesValuesProps = { values, min, max, avg, current, total };
     const seriesValuesProps = { values, min, max, avg, current, total };
-    return seriesList.map((series, i) => (
+    return seriesList.map(series => (
       <LegendItem
       <LegendItem
         key={series.id}
         key={series.id}
         series={series}
         series={series}
-        index={i}
-        hiddenSeries={hiddenSeries}
+        hidden={hiddenSeries[series.alias]}
         {...seriesValuesProps}
         {...seriesValuesProps}
-        onLabelClick={e => this.props.onToggleSeries(series, e)}
-        onColorChange={color => this.props.onColorChange(series, color)}
-        onToggleAxis={() => this.props.onToggleAxis(series)}
+        onLabelClick={this.props.onToggleSeries}
+        onColorChange={this.props.onColorChange}
+        onToggleAxis={this.props.onToggleAxis}
       />
       />
     ));
     ));
   }
   }
 }
 }
 
 
 class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
 class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
-  onToggleSort(stat) {
+  onToggleSort = stat => {
     let sortDesc = this.props.sortDesc;
     let sortDesc = this.props.sortDesc;
     let sortBy = this.props.sort;
     let sortBy = this.props.sort;
     if (stat !== sortBy) {
     if (stat !== sortBy) {
@@ -153,11 +161,11 @@ class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
       sortBy = stat;
       sortBy = stat;
     }
     }
     this.props.onToggleSort(sortBy, sortDesc);
     this.props.onToggleSort(sortBy, sortDesc);
-  }
+  };
 
 
   render() {
   render() {
     const seriesList = this.props.seriesList;
     const seriesList = this.props.seriesList;
-    const { values, min, max, avg, current, total, sort, sortDesc } = this.props;
+    const { values, min, max, avg, current, total, sort, sortDesc, hiddenSeries } = this.props;
     const seriesValuesProps = { values, min, max, avg, current, total };
     const seriesValuesProps = { values, min, max, avg, current, total };
     return (
     return (
       <table>
       <table>
@@ -172,21 +180,20 @@ class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
                     statName={statName}
                     statName={statName}
                     sort={sort}
                     sort={sort}
                     sortDesc={sortDesc}
                     sortDesc={sortDesc}
-                    onClick={e => this.onToggleSort(statName)}
+                    onClick={this.onToggleSort}
                   />
                   />
                 )
                 )
             )}
             )}
           </tr>
           </tr>
-          {seriesList.map((series, i) => (
+          {seriesList.map(series => (
             <LegendItem
             <LegendItem
               key={series.id}
               key={series.id}
               asTable={true}
               asTable={true}
               series={series}
               series={series}
-              index={i}
-              hiddenSeries={this.props.hiddenSeries}
-              onLabelClick={e => this.props.onToggleSeries(series, e)}
-              onColorChange={color => this.props.onColorChange(series, color)}
-              onToggleAxis={() => this.props.onToggleAxis(series)}
+              hidden={hiddenSeries[series.alias]}
+              onLabelClick={this.props.onToggleSeries}
+              onColorChange={this.props.onColorChange}
+              onToggleAxis={this.props.onToggleAxis}
               {...seriesValuesProps}
               {...seriesValuesProps}
             />
             />
           ))}
           ))}
@@ -198,20 +205,24 @@ class LegendTable extends React.PureComponent<Partial<GraphLegendProps>> {
 
 
 interface LegendTableHeaderProps {
 interface LegendTableHeaderProps {
   statName: string;
   statName: string;
-  onClick?: (event) => void;
+  onClick?: (statName: string) => void;
 }
 }
 
 
-function LegendTableHeaderItem(props: LegendTableHeaderProps & LegendSortProps) {
-  const { statName, sort, sortDesc } = props;
-  return (
-    <th className="pointer" onClick={e => props.onClick(e)}>
-      {statName}
-      {sort === statName && <span className={sortDesc ? 'fa fa-caret-down' : 'fa fa-caret-up'} />}
-    </th>
-  );
+class LegendTableHeaderItem extends React.PureComponent<LegendTableHeaderProps & LegendSortProps> {
+  onClick = () => this.props.onClick(this.props.statName);
+
+  render() {
+    const { statName, sort, sortDesc } = this.props;
+    return (
+      <th className="pointer" onClick={this.onClick}>
+        {statName}
+        {sort === statName && <span className={sortDesc ? 'fa fa-caret-down' : 'fa fa-caret-up'} />}
+      </th>
+    );
+  }
 }
 }
 
 
-export class Legend extends React.Component<GraphLegendProps> {
+export class Legend extends React.PureComponent<GraphLegendProps> {
   render() {
   render() {
     return (
     return (
       <CustomScrollbar>
       <CustomScrollbar>

+ 22 - 13
public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx

@@ -5,13 +5,12 @@ import withColorPicker from 'app/core/components/colorpicker/withColorPicker';
 export const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total'];
 export const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total'];
 
 
 export interface LegendLabelProps {
 export interface LegendLabelProps {
-  index: number;
   series: TimeSeries;
   series: TimeSeries;
   asTable?: boolean;
   asTable?: boolean;
-  hiddenSeries?: any;
-  onLabelClick?: (event) => void;
-  onColorChange?: (color: string) => void;
-  onToggleAxis?: () => void;
+  hidden?: boolean;
+  onLabelClick?: (series, event) => void;
+  onColorChange?: (series, color: string) => void;
+  onToggleAxis?: (series) => void;
 }
 }
 
 
 export interface LegendValuesProps {
 export interface LegendValuesProps {
@@ -28,25 +27,35 @@ type LegendItemProps = LegendLabelProps & LegendValuesProps;
 export class LegendItem extends React.PureComponent<LegendItemProps> {
 export class LegendItem extends React.PureComponent<LegendItemProps> {
   static defaultProps = {
   static defaultProps = {
     asTable: false,
     asTable: false,
-    hiddenSeries: undefined,
+    hidden: false,
     onLabelClick: () => {},
     onLabelClick: () => {},
     onColorChange: () => {},
     onColorChange: () => {},
     onToggleAxis: () => {},
     onToggleAxis: () => {},
   };
   };
 
 
+  onLabelClick = e => this.props.onLabelClick(this.props.series, e);
+  onToggleAxis = () => {
+    this.props.onToggleAxis(this.props.series);
+    this.forceUpdate();
+  };
+  onColorChange = color => {
+    this.props.onColorChange(this.props.series, color);
+    // this.forceUpdate();
+  };
+
   render() {
   render() {
-    const { series, hiddenSeries, asTable } = this.props;
+    const { series, hidden, asTable } = this.props;
     const { aliasEscaped, color, yaxis } = this.props.series;
     const { aliasEscaped, color, yaxis } = this.props.series;
-    const seriesOptionClasses = getOptionSeriesCSSClasses(series, hiddenSeries);
+    const seriesOptionClasses = getOptionSeriesCSSClasses(series, hidden);
     const valueItems = this.props.values ? renderLegendValues(this.props, series, asTable) : [];
     const valueItems = this.props.values ? renderLegendValues(this.props, series, asTable) : [];
     const seriesLabel = (
     const seriesLabel = (
       <LegendSeriesLabel
       <LegendSeriesLabel
         label={aliasEscaped}
         label={aliasEscaped}
         color={color}
         color={color}
         yaxis={yaxis}
         yaxis={yaxis}
-        onLabelClick={this.props.onLabelClick}
-        onColorChange={this.props.onColorChange}
-        onToggleAxis={this.props.onToggleAxis}
+        onLabelClick={this.onLabelClick}
+        onColorChange={this.onColorChange}
+        onToggleAxis={this.onToggleAxis}
       />
       />
     );
     );
 
 
@@ -161,12 +170,12 @@ function renderLegendValues(props: LegendItemProps, series, asTable = false) {
   return legendValueItems;
   return legendValueItems;
 }
 }
 
 
-function getOptionSeriesCSSClasses(series, hiddenSeries) {
+function getOptionSeriesCSSClasses(series, hidden) {
   const classes = [];
   const classes = [];
   if (series.yaxis === 2) {
   if (series.yaxis === 2) {
     classes.push('graph-legend-series--right-y');
     classes.push('graph-legend-series--right-y');
   }
   }
-  if (hiddenSeries[series.alias] && hiddenSeries[series.alias] === true) {
+  if (hidden) {
     classes.push('graph-legend-series-hidden');
     classes.push('graph-legend-series-hidden');
   }
   }
   return classes.join(' ');
   return classes.join(' ');

+ 10 - 7
public/app/plugins/panel/graph/graph.ts

@@ -66,13 +66,16 @@ class GraphElement {
 
 
     // global events
     // global events
     appEvents.on('graph-hover', this.onGraphHover.bind(this), scope);
     appEvents.on('graph-hover', this.onGraphHover.bind(this), scope);
-
     appEvents.on('graph-hover-clear', this.onGraphHoverClear.bind(this), scope);
     appEvents.on('graph-hover-clear', this.onGraphHoverClear.bind(this), scope);
-
     this.elem.bind('plotselected', this.onPlotSelected.bind(this));
     this.elem.bind('plotselected', this.onPlotSelected.bind(this));
-
     this.elem.bind('plotclick', this.onPlotClick.bind(this));
     this.elem.bind('plotclick', this.onPlotClick.bind(this));
     scope.$on('$destroy', this.onScopeDestroy.bind(this));
     scope.$on('$destroy', this.onScopeDestroy.bind(this));
+
+    // Bind legend event handlers once in constructor to avoid unnecessary re-rendering
+    this.ctrl.toggleSeries = this.ctrl.toggleSeries.bind(this.ctrl);
+    this.ctrl.toggleSort = this.ctrl.toggleSort.bind(this.ctrl);
+    this.ctrl.changeSeriesColor = this.ctrl.changeSeriesColor.bind(this.ctrl);
+    this.ctrl.toggleAxis = this.ctrl.toggleAxis.bind(this.ctrl);
   }
   }
 
 
   onRender(renderData) {
   onRender(renderData) {
@@ -94,10 +97,10 @@ class GraphElement {
       hiddenSeries: this.ctrl.hiddenSeries,
       hiddenSeries: this.ctrl.hiddenSeries,
       ...legendOptions,
       ...legendOptions,
       ...valueOptions,
       ...valueOptions,
-      onToggleSeries: this.ctrl.toggleSeries.bind(this.ctrl),
-      onToggleSort: this.ctrl.toggleSort.bind(this.ctrl),
-      onColorChange: this.ctrl.changeSeriesColor.bind(this.ctrl),
-      onToggleAxis: this.ctrl.toggleAxis.bind(this.ctrl),
+      onToggleSeries: this.ctrl.toggleSeries,
+      onToggleSort: this.ctrl.toggleSort,
+      onColorChange: this.ctrl.changeSeriesColor,
+      onToggleAxis: this.ctrl.toggleAxis,
     };
     };
     const legendReactElem = React.createElement(Legend, legendProps);
     const legendReactElem = React.createElement(Legend, legendProps);
     const legendElem = this.elem.parent().find('.graph-legend');
     const legendElem = this.elem.parent().find('.graph-legend');