From d8c57046c8e73ec3ed7a4072b701cf91f56bd35d Mon Sep 17 00:00:00 2001
From: Alex P <thealexpaxton@gmail.com>
Date: Fri, 23 Feb 2018 10:43:24 -0800
Subject: [PATCH] Add Prefix and Suffix to Gauge cells
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Doesn’t look great when the user has set both but that’s a separate
issue
---
 ui/src/dashboards/components/GaugeOptions.js | 49 ++++++++++++++++++--
 ui/src/shared/components/Gauge.js            | 12 +++--
 ui/src/shared/components/GaugeChart.js       |  6 +++
 ui/src/shared/components/RefreshingGraph.js  |  9 +++-
 4 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/ui/src/dashboards/components/GaugeOptions.js b/ui/src/dashboards/components/GaugeOptions.js
index 5229189ecd..10de6d7ccc 100644
--- a/ui/src/dashboards/components/GaugeOptions.js
+++ b/ui/src/dashboards/components/GaugeOptions.js
@@ -15,7 +15,10 @@ import {
   MIN_THRESHOLDS,
 } from 'src/dashboards/constants/gaugeColors'
 
-import {updateGaugeColors} from 'src/dashboards/actions/cellEditorOverlay'
+import {
+  updateGaugeColors,
+  updateAxes,
+} from 'src/dashboards/actions/cellEditorOverlay'
 
 class GaugeOptions extends Component {
   handleAddThreshold = () => {
@@ -118,8 +121,22 @@ class GaugeOptions extends Component {
     return allowedToUpdate
   }
 
+  handleUpdatePrefix = e => {
+    const {handleUpdateAxes, axes} = this.props
+    const newAxes = {...axes, y: {...axes.y, prefix: e.target.value}}
+
+    handleUpdateAxes(newAxes)
+  }
+
+  handleUpdateSuffix = e => {
+    const {handleUpdateAxes, axes} = this.props
+    const newAxes = {...axes, y: {...axes.y, suffix: e.target.value}}
+
+    handleUpdateAxes(newAxes)
+  }
+
   render() {
-    const {gaugeColors} = this.props
+    const {gaugeColors, axes: {y: {prefix, suffix}}} = this.props
 
     const disableMaxColor = gaugeColors.length > MIN_THRESHOLDS
     const disableAddThreshold = gaugeColors.length > MAX_THRESHOLDS
@@ -157,6 +174,28 @@ class GaugeOptions extends Component {
               />
             )}
           </div>
+          <div className="single-stat-controls">
+            <div className="form-group col-xs-6">
+              <label>Prefix</label>
+              <input
+                className="form-control input-sm"
+                placeholder="%, MPH, etc."
+                defaultValue={prefix}
+                onChange={this.handleUpdatePrefix}
+                maxLength="5"
+              />
+            </div>
+            <div className="form-group col-xs-6">
+              <label>Suffix</label>
+              <input
+                className="form-control input-sm"
+                placeholder="%, MPH, etc."
+                defaultValue={suffix}
+                onChange={this.handleUpdateSuffix}
+                maxLength="5"
+              />
+            </div>
+          </div>
         </div>
       </FancyScrollbar>
     )
@@ -176,13 +215,17 @@ GaugeOptions.propTypes = {
     }).isRequired
   ),
   handleUpdateGaugeColors: func.isRequired,
+  handleUpdateAxes: func.isRequired,
+  axes: shape({}).isRequired,
 }
 
-const mapStateToProps = ({cellEditorOverlay: {gaugeColors}}) => ({
+const mapStateToProps = ({cellEditorOverlay: {gaugeColors, cell: {axes}}}) => ({
   gaugeColors,
+  axes,
 })
 
 const mapDispatchToProps = dispatch => ({
   handleUpdateGaugeColors: bindActionCreators(updateGaugeColors, dispatch),
+  handleUpdateAxes: bindActionCreators(updateAxes, dispatch),
 })
 export default connect(mapStateToProps, mapDispatchToProps)(GaugeOptions)
diff --git a/ui/src/shared/components/Gauge.js b/ui/src/shared/components/Gauge.js
index c9adfd521c..aa18fd8eda 100644
--- a/ui/src/shared/components/Gauge.js
+++ b/ui/src/shared/components/Gauge.js
@@ -226,6 +226,7 @@ class Gauge extends Component {
     minValue,
     maxValue
   ) => {
+    const {prefix, suffix} = this.props
     const {degree, lineCount, labelColor, labelFontSize} = GAUGE_SPECS
 
     const incrementValue = (maxValue - minValue) / lineCount
@@ -258,12 +259,14 @@ class Gauge extends Component {
       if (i > 3) {
         ctx.textAlign = 'left'
       }
+      const labelText = `${prefix}${gaugeValues[i]}${suffix}`
+
       ctx.rotate(startDegree)
       ctx.rotate(i * arcIncrement)
       ctx.translate(labelRadius, 0)
       ctx.rotate(i * -arcIncrement)
       ctx.rotate(-startDegree)
-      ctx.fillText(gaugeValues[i], 0, 0)
+      ctx.fillText(labelText, 0, 0)
       ctx.rotate(startDegree)
       ctx.rotate(i * arcIncrement)
       ctx.translate(-labelRadius, 0)
@@ -273,7 +276,7 @@ class Gauge extends Component {
   }
 
   drawGaugeValue = (ctx, radius, labelValueFontSize) => {
-    const {gaugePosition} = this.props
+    const {gaugePosition, prefix, suffix} = this.props
     const {valueColor} = GAUGE_SPECS
 
     ctx.font = `${labelValueFontSize}px Roboto`
@@ -282,7 +285,8 @@ class Gauge extends Component {
     ctx.textAlign = 'center'
 
     const textY = radius
-    ctx.fillText(gaugePosition.toString(), 0, textY)
+    const textContent = `${prefix}${gaugePosition.toString()}${suffix}`
+    ctx.fillText(textContent, 0, textY)
   }
 
   drawNeedle = (ctx, radius, minValue, maxValue) => {
@@ -335,6 +339,8 @@ Gauge.propTypes = {
       value: string.isRequired,
     }).isRequired
   ).isRequired,
+  prefix: string.isRequired,
+  suffix: string.isRequired,
 }
 
 export default Gauge
diff --git a/ui/src/shared/components/GaugeChart.js b/ui/src/shared/components/GaugeChart.js
index a329a89ecf..fddfe57c66 100644
--- a/ui/src/shared/components/GaugeChart.js
+++ b/ui/src/shared/components/GaugeChart.js
@@ -17,6 +17,8 @@ class GaugeChart extends PureComponent {
       colors,
       resizeCoords,
       resizerTopHeight,
+      prefix,
+      suffix,
     } = this.props
 
     // If data for this graph is being fetched for the first time, show a graph-wide spinner.
@@ -54,6 +56,8 @@ class GaugeChart extends PureComponent {
           height={height}
           colors={colors}
           gaugePosition={roundedValue}
+          prefix={prefix}
+          suffix={suffix}
         />
       </div>
     )
@@ -81,6 +85,8 @@ GaugeChart.propTypes = {
       value: string.isRequired,
     }).isRequired
   ),
+  prefix: string.isRequired,
+  suffix: string.isRequired,
 }
 
 export default GaugeChart
diff --git a/ui/src/shared/components/RefreshingGraph.js b/ui/src/shared/components/RefreshingGraph.js
index fe389d4ff6..8b294d5c3b 100644
--- a/ui/src/shared/components/RefreshingGraph.js
+++ b/ui/src/shared/components/RefreshingGraph.js
@@ -28,6 +28,9 @@ const RefreshingGraph = ({
   editQueryStatus,
   grabDataForDownload,
 }) => {
+  const prefix = axes.y.prefix || ''
+  const suffix = axes.y.suffix || ''
+
   if (!queries.length) {
     return (
       <div className="graph-empty">
@@ -47,8 +50,8 @@ const RefreshingGraph = ({
         templates={templates}
         autoRefresh={autoRefresh}
         cellHeight={cellHeight}
-        prefix={axes.y.prefix || ''}
-        suffix={axes.y.suffix || ''}
+        prefix={prefix}
+        suffix={suffix}
       />
     )
   }
@@ -64,6 +67,8 @@ const RefreshingGraph = ({
         cellHeight={cellHeight}
         resizerTopHeight={resizerTopHeight}
         resizeCoords={resizeCoords}
+        prefix={prefix}
+        suffix={suffix}
       />
     )
   }