Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Rickshaw Graph is a drop in replacement for Dashing's graph
# Rickshawgraph v0.1.2
class Dashing.Rickshawgraph extends Dashing.Widget
DIVISORS = [
{number: 100000000000000000000000, label: 'Y'},
{number: 100000000000000000000, label: 'Z'},
{number: 100000000000000000, label: 'E'},
{number: 1000000000000000, label: 'P'},
{number: 1000000000000, label: 'T'},
{number: 1000000000, label: 'G'},
{number: 1000000, label: 'M'},
{number: 1000, label: 'K'}
]
# Take a long number like "2356352" and turn it into "2.4M"
formatNumber = (number) ->
for divisior in DIVISORS
if number > divisior.number
number = "#{Math.round(number / (divisior.number/10))/10}#{divisior.label}"
break
return number
getRenderer: () -> return @get('renderer') or @get('graphtype') or 'area'
# Retrieve the `current` value of the graph.
@accessor 'current', ->
answer = null
# Return the value supplied if there is one.
if @get('displayedValue') != null and @get('displayedValue') != undefined
answer = @get('displayedValue')
if answer == null
# Compute a value to return based on the summaryMethod
series = @_parseData {points: @get('points'), series: @get('series')}
if !(series?.length > 0)
# No data in series
answer = ''
else
switch @get('summaryMethod')
when "sum"
answer = 0
answer += (point?.y or 0) for point in s.data for s in series
when "sumLast"
answer = 0
answer += s.data[s.data.length - 1].y or 0 for s in series
when "highest"
answer = 0
if @get('unstack') or (@getRenderer() is "line")
answer = Math.max(answer, (point?.y or 0)) for point in s.data for s in series
else
# Compute the sum of values at each point along the graph
for index in [0...series[0].data.length]
value = 0
for s in series
value += s.data[index]?.y or 0
answer = Math.max(answer, value)
when "none"
answer = ''
else
# Otherwise if there's only one series, pick the most recent value from the series.
if series.length == 1 and series[0].data?.length > 0
data = series[0].data
answer = data[data.length - 1].y
else
# Otherwise just return nothing.
answer = ''
answer = formatNumber answer
return answer
ready: ->
@assignedColors = @get('colors').split(':') if @get('colors')
@strokeColors = @get('strokeColors').split(':') if @get('strokeColors')
@graph = @_createGraph()
@graph.render()
clear: ->
# Remove the old graph/legend if there is one.
$node = $(@node)
$node.find('.rickshaw_graph').remove()
if @$legendDiv
@$legendDiv.remove()
@$legendDiv = null
# Handle new data from Dashing.
onData: (data) ->
series = @_parseData data
if @graph
# Remove the existing graph if the number of series has changed or any names have changed.
needClear = false
needClear |= (series.length != @graph.series.length)
if @get("legend") then for subseries, index in series
needClear |= @graph.series[index]?.name != series[index]?.name
if needClear then @graph = @_createGraph()
# Copy over the new graph data
for subseries, index in series
@graph.series[index] = subseries
@graph.render()
# Create a new Rickshaw graph.
_createGraph: ->
$node = $(@node)
$container = $node.parent()
@clear()
# Gross hacks. Let's fix this.
width = (Dashing.widget_base_dimensions[0] * $container.data("sizex")) + Dashing.widget_margins[0] * 2 * (($container.data("sizex") ? 1) - 1)
height = (Dashing.widget_base_dimensions[1] * $container.data("sizey")) + Dashing.widget_margins[1] * 2 * (($container.data("sizey") ? 1) - 1)
if @get("legend")
# Shave 20px off the bottom of the graph for the legend
height -= 20
$graph = $("<div style='height: #{height}px;'></div>")
$node.append $graph
series = @_parseData {points: @get('points'), series: @get('series')}
graphOptions = {
element: $graph.get(0),
renderer: @getRenderer(),
width: width,
height: height,
series: series
}
if !!@get('stroke') then graphOptions.stroke = true
if @get('min') != null then graphOptions.min = @get('min')
if @get('max') != null then graphOptions.max = @get('max')
try
graph = new Rickshaw.Graph graphOptions
catch err
nullsFound = false
if err.toString() is "x and y properties of points should be numbers instead of number and object"
# This will happen with older versions of Rickshaw that don't support nulls in the data set.
for s in series
for point in s.data
if point.y is null
nullsFound = true
point.y = 0
if nullsFound
# Try to create the graph again now that we've patched up the data.
graph = new Rickshaw.Graph graphOptions
if !@rickshawVersionWarning
console.log "#{@get 'id'} - Nulls were found in your data, but Rickshaw didn't like" +
" them. Consider upgrading your rickshaw to 1.4.3 or higher."
@rickshawVersionWarning = true
else
# No nulls were found - this is some other problem, so just re-throw the exception.
throw err
graph.renderer.unstack = !!@get('unstack')
xAxisOptions = {
graph: graph
}
if Rickshaw.Fixtures.Time.Local
xAxisOptions.timeFixture = new Rickshaw.Fixtures.Time.Local()
x_axis = new Rickshaw.Graph.Axis.Time xAxisOptions
y_axis = new Rickshaw.Graph.Axis.Y(graph: graph, tickFormat: Rickshaw.Fixtures.Number.formatKMBT)
if @get("legend")
# Add a legend
@$legendDiv = $("<div style='width: #{width}px;'></div>")
$node.append(@$legendDiv)
legend = new Rickshaw.Graph.Legend {
graph: graph
element: @$legendDiv.get(0)
}
return graph
# Parse a {series, points} object with new data from Dashing.
#
_parseData: (data) ->
series = []
# Figure out what kind of data we've been passed
if data.series
dataSeries = if isString(data.series) then JSON.parse data.series else data.series
for subseries, index in dataSeries
try
series.push @_parseSeries subseries
catch err
console.log "Error while parsing series: #{err}"
else if data.points
points = data.points
if isString(points) then points = JSON.parse points
if points[0]? and !points[0].x?
# Not already in Rickshaw format; assume graphite data
points = graphiteDataToRickshaw(points)
series.push {data: points}
if series.length is 0
# No data - create a dummy series to keep Rickshaw happy
series.push {data: [{x:0, y:0}]}
@_updateColors(series)
# Fix any missing data in the series.
if Rickshaw.Series.fill then Rickshaw.Series.fill(series, null)
return series
# Parse a series of data from an array passed to `_parseData()`.
# This accepts both Graphite and Rickshaw style data sets.
_parseSeries: (series) ->
if series?.datapoints?
# This is a Graphite series
answer = {
name: series.target
data: graphiteDataToRickshaw series.datapoints
color: series.color
stroke: series.stroke
}
else if series?.data?
# Rickshaw data. Need to clone, otherwise we could end up with multiple graphs sharing
# the same data, and Rickshaw really doesn't like that.
answer = {
name: series.name
data: series.data
color: series.color
stroke: series.stroke
}
else if !series
throw new Error("No data received for #{@get 'id'}")
else
throw new Error("Unknown data for #{@get 'id'}. series: #{series}")
answer.data.sort (a,b) -> a.x - b.x
return answer
# Update the color assignments for a series. This will assign colors to any data that
# doesn't have a color already.
_updateColors: (series) ->
# If no colors were provided, or of there aren't enough colors, then generate a set of
# colors to use.
if !@defaultColors or @defaultColors?.length != series.length
@defaultColors = computeDefaultColors @, @node, series
for subseries, index in series
# Preferentially pick supplied colors instead of defaults, but don't overwrite a color
# if one was supplied with the data.
subseries.color ?= @assignedColors?[index] or @defaultColors[index]
subseries.stroke ?= @strokeColors?[index] or "#000"
# Convert a collection of Graphite data points into data that Rickshaw will understand.
graphiteDataToRickshaw = (datapoints) ->
answer = []
for datapoint in datapoints
# Need to convert potential nulls from Graphite into a real number for Rickshaw.
answer.push {x: datapoint[1], y: (datapoint[0] or 0)}
answer
# Compute a pleasing set of default colors. This works by starting with the background color,
# and picking colors of intermediate luminance between the background and white (or the
# background and black, for light colored backgrounds.) We use the brightest color for the
# first series, because then multiple series will appear to blend in to the background.
computeDefaultColors = (self, node, series) ->
defaultColors = []
# Use a neutral color if we can't get the background-color for some reason.
backgroundColor = parseColor($(node).css('background-color')) or [50, 50, 50, 1.0]
hsl = rgbToHsl backgroundColor
alpha = if self.get('defaultAlpha')? then self.get('defaultAlpha') else 1
if self.get('colorScheme') in ['rainbow', 'near-rainbow']
saturation = (interpolate hsl[1], 1.0, 3)[1]
luminance = if (hsl[2] < 0.6) then 0.7 else 0.3
hueOffset = 0
if self.get('colorScheme') is 'rainbow'
# Note the first and last values in `hues` will both have the same hue as the background,
# hence the + 2.
hues = interpolate hsl[0], hsl[0] + 1, (series.length + 2)
hueOffset = 1
else
hues = interpolate hsl[0] - 0.25, hsl[0] + 0.25, series.length
for hue, index in hues
if hue > 1 then hues[index] -= 1
if hue < 0 then hues[index] += 1
for index in [0...series.length]
defaultColors[index] = rgbToColor hslToRgb([hues[index + hueOffset], saturation, luminance, alpha])
else
hue = if self.get('colorScheme') is "compliment" then hsl[0] + 0.5 else hsl[0]
if hsl[0] > 1 then hsl[0] -= 1
saturation = hsl[1]
saturationSource = if (saturation < 0.6) then 0.7 else 0.3
saturations = interpolate saturationSource, saturation, (series.length + 1)
luminance = hsl[2]
luminanceSource = if (luminance < 0.6) then 0.9 else 0.1
luminances = interpolate luminanceSource, luminance, (series.length + 1)
for index in [0...series.length]
defaultColors[index] = rgbToColor hslToRgb([hue, saturations[index], luminances[index], alpha])
return defaultColors
# Helper functions
# ================
isString = (obj) ->
return toString.call(obj) is "[object String]"
# Parse a `rgb(x,y,z)` or `rgba(x,y,z,a)` string.
parseRgbaColor = (colorString) ->
match = /^rgb\(\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*\)/.exec(colorString)
if match
return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), 1.0]
match = /^rgba\(\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*,\s*([\d]+)\s*\)/.exec(colorString)
if match
return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), parseInt(match[4])]
return null
# Parse a color string as RGBA
parseColor = (colorString) ->
answer = null
# Try to use the browser to parse the color for us.
div = document.createElement('div')
div.style.color = colorString
if div.style.color
answer = parseRgbaColor div.style.color
if !answer
match = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})/.exec(colorString)
if match then answer = [parseInt(match[1], 16), parseInt(match[2], 16), parseInt(match[3], 16), 1.0]
if !answer
match = /^#([\da-fA-F])([\da-fA-F])([\da-fA-F])/.exec(colorString)
if match then answer = [parseInt(match[1], 16) * 0x11, parseInt(match[2], 16) * 0x11, parseInt(match[3], 16) * 0x11, 1.0]
if !answer then answer = parseRgbaColor colorString
return answer
# Convert an RGB or RGBA color to a CSS color.
rgbToColor = (rgb) ->
if (!3 of rgb) or (rgb[3] == 1.0)
return "rgb(#{rgb[0]},#{rgb[1]},#{rgb[2]})"
else
return "rgba(#{rgb[0]},#{rgb[1]},#{rgb[2]},#{rgb[3]})"
# Returns an array of size `steps`, where the first value is `source`, the last value is `dest`,
# and the intervening values are interpolated. If steps < 2, then returns `[dest]`.
#
interpolate = (source, dest, steps) ->
if steps < 2
answer =[dest]
else
stepSize = (dest - source) / (steps - 1)
answer = (num for num in [source..dest] by stepSize)
# Rounding errors can cause us to drop the last value
if answer.length < steps then answer.push dest
return answer
# Adapted from http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
#
# Converts an RGBA color value to HSLA. Conversion formula
# adapted from http://en.wikipedia.org/wiki/HSL_color_space.
# Assumes r, g, and b are contained in the set [0, 255] and
# a in [0, 1]. Returns h, s, l, a in the set [0, 1].
#
# Returns the HSLA representation as an array.
rgbToHsl = (rgba) ->
[r,g,b,a] = rgba
r /= 255
g /= 255
b /= 255
max = Math.max(r, g, b)
min = Math.min(r, g, b)
l = (max + min) / 2
if max == min
h = s = 0 # achromatic
else
d = max - min
s = if l > 0.5 then d / (2 - max - min) else d / (max + min)
switch max
when r then h = (g - b) / d + (g < b ? 6 : 0)
when g then h = (b - r) / d + 2
when b then h = (r - g) / d + 4
h /= 6;
return [h, s, l, a]
# Adapted from http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
#
# Converts an HSLA color value to RGBA. Conversion formula
# adapted from http://en.wikipedia.org/wiki/HSL_color_space.
# Assumes h, s, l, and a are contained in the set [0, 1] and
# returns r, g, and b in the set [0, 255] and a in [0, 1].
#
# Retunrs the RGBA representation as an array.
hslToRgb = (hsla) ->
[h,s,l,a] = hsla
if s is 0
r = g = b = l # achromatic
else
hue2rgb = (p, q, t) ->
if(t < 0) then t += 1
if(t > 1) then t -= 1
if(t < 1/6) then return p + (q - p) * 6 * t
if(t < 1/2) then return q
if(t < 2/3) then return p + (q - p) * (2/3 - t) * 6
return p
q = if l < 0.5 then l * (1 + s) else l + s - l * s
p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1/3)
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a]
<h1 class="title" data-bind="title"></h1>
<h2 class="value" data-bind="current | prepend prefix"></h2>
<p class="more-info" data-bind="moreinfo"></p>

Graphing Widget

The graphing widget shows graphs using the Rickshaw graphing library. The names of data fields should be (vaguely) familiar if you've used Rickshaw before.

It's recommended that you replace the /assets/javascripts/rickshaw.min.js from your dashboard with the latest from here.

Supported HTML data fields

  • data-title: Title to display.
  • data-displayed-value: If provided, then the value to display overtop of the graph. If not provided, then the most recent value will be used if there is only one series.
  • data-renderer: Any valid Rickshaw renderer, including 'area', 'line', 'bar', 'scatterplot'.
  • data-stroke: If "true", then area graphs will be drawn with a stroke.
  • data-unstack: If "true", then area and bar graphs will be "unstacked".
  • data-colors: A ":" separated list of colors to use for each plot. If there are fewer colors provided than there are series to graph, then pleasing colors will be automatically chosen. (e.g.: data-colors="#ccc:#ddd:#eee")
  • data-stroke-colors: A ":" separated list of colors to use for strokes.
  • data-color-scheme: One of "rainbow", "near-rainbow", "compliment", "default". Controls how default colors are assigned.
  • data-default-alpha: Alpha for default colors.
  • data-legend: If "true", then a legend will be added to your graph.
  • data-min and data-max: Set the highest and lowest values of the y-axis.
  • data-summary-method determines how the value shown in the graph is computed. If data-displayed-value is set, this is ignored. Otherwise this should be one of:
    • "last" - Default - If there is only one series, show the most recent value from that series.
    • "sum" - Sum of all values across all series.
    • "sumLast" - Sum of last values across all series.
    • "highest" - For stacked graphs, the highest single data point based on the sum of all series. For unstacked graphs, the highest single data point of any series.

Passing Data

Data can be provided in a number of formats. Data can be passed as a series of points:

points = [{x:1, y: 4}, {x:2, y:27}, {x:3, y:6}]
send_event('convergence', points: points)

Note that the x values are interpreted as unix timestamps. Data can also be passed as full-on Rickshaw-style series:

series = [
    {
        name: "Convergence",
        data: [{x:1, y: 4}, {x:2, y:27}, {x:3, y:6}]
    },
    {
        name: "Divergence",
        data: [{x:1, y: 5}, {x:2, y:2}, {x:3, y:9}]
    }
]
send_event('convergence', series: series)

You can even provide colors and strokes here, which will override the values defined in the HTML. Or data can be passed as Graphite-style data:

graphite = [
  {
    target: "stats_counts.http.ok",
    datapoints: [[10, 1378449600], [40, 1378452000], [53, 1378454400], [63, 1378456800], [27, 1378459200]]
  },
  {
    target: "stats_counts.http.err",
    datapoints: [[0, 1378449600], [4, 1378452000], [nil, 1378454400], [3, 1378456800], [0, 1378459200]]
  }
]
send_event('http', series: graphite)

You can even send data as JSON strings, straight from Graphite:

require "rest-client"
SCHEDULER.every '10s', :first_in => 0 do
    target = "aliasSub(summarize(stats_counts.http.*%2C%2720min%27)%2C%27%5E.*http.(%5Cw*).*%27%2C%27%5C1%27)"
    url = "http://graphteserver.local:8000/render?format=json&target=#{target}&from=today"
    graphite_json_data = RestClient.get url
    send_event 'http_counts', { series: graphite_json_data }
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #dc5945;
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.5);
$tick-color: rgba(0, 0, 0, 0.4);
// ----------------------------------------------------------------------------
// Widget-graph styles
// ----------------------------------------------------------------------------
.widget-rickshawgraph {
background-color: $background-color;
position: relative;
.rickshaw_graph {
position: absolute;
left: 0px;
top: 0px;
}
svg {
position: absolute;
left: 0px;
top: 0px;
}
.title, .value {
position: relative;
z-index: 99;
}
.title {
color: $title-color;
}
.more-info {
color: $moreinfo-color;
font-weight: 600;
font-size: 20px;
margin-top: 0;
}
.x_tick {
position: absolute;
bottom: 0;
.title {
font-size: 20px;
color: $tick-color;
opacity: 0.5;
padding-bottom: 3px;
}
}
.y_ticks {
font-size: 20px;
fill: $tick-color;
text {
opacity: 0.5;
}
}
.domain {
display: none;
}
.rickshaw_legend {
position: absolute;
left: 0px;
bottom: 0px;
white-space: nowrap;
overflow-x: hidden;
font-size: 15px;
height: 20px;
ul {
margin: 0;
padding: 0;
list-style-type: none;
text-align: center;
}
ul li {
display: inline;
}
.swatch {
display: inline-block;
width: 14px;
height: 14px;
margin-left: 5px;
}
.label {
display: inline-block;
margin-left: 5px;
}
}
}
@LKLG

This comment has been minimized.

Show comment Hide comment
@LKLG

LKLG Oct 30, 2013

Great Job!
It is much better than the standart-graph-widget!

Thanks for it! :)

LKLG commented Oct 30, 2013

Great Job!
It is much better than the standart-graph-widget!

Thanks for it! :)

@thijzert

This comment has been minimized.

Show comment Hide comment
@thijzert

thijzert Dec 18, 2013

There's a typo in parsing the data-min="" attribute, which is fixed in my fork. Could you merge this change?

There's a typo in parsing the data-min="" attribute, which is fixed in my fork. Could you merge this change?

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Feb 10, 2014

Couple of minor points -- one was to add the "| append suffix" to the HTML on value (to match the number widget - and i needed to add the '%' symbol :P

<h1 class="title" data-bind="title"></h1>

<h2 class="value" data-bind="current | prepend prefix | append suffix"></h2>

<p class="more-info" data-bind="moreinfo"></p>

Also the formatting of the number changed to:

  formatNumber = (number) ->
      number = Math.round(number)
      for divisior in DIVISORS
          if number > divisior.number
              number = "#{Math.round(number / (divisior.number / 10 ) ) / 10}#{divisior.label}"
              break

      return number

I was getting floats out of graphite data, which were not being rounded/truncated - and this just cleaned up the code and resulting pages nicely.

Thanks very much for a great widget!!!

ghost commented Feb 10, 2014

Couple of minor points -- one was to add the "| append suffix" to the HTML on value (to match the number widget - and i needed to add the '%' symbol :P

<h1 class="title" data-bind="title"></h1>

<h2 class="value" data-bind="current | prepend prefix | append suffix"></h2>

<p class="more-info" data-bind="moreinfo"></p>

Also the formatting of the number changed to:

  formatNumber = (number) ->
      number = Math.round(number)
      for divisior in DIVISORS
          if number > divisior.number
              number = "#{Math.round(number / (divisior.number / 10 ) ) / 10}#{divisior.label}"
              break

      return number

I was getting floats out of graphite data, which were not being rounded/truncated - and this just cleaned up the code and resulting pages nicely.

Thanks very much for a great widget!!!

@bubbajoelouis

This comment has been minimized.

Show comment Hide comment
@bubbajoelouis

bubbajoelouis Apr 23, 2014

HoverDetail can be implemented with the following added to rickshawgraph.coffee right after the 'if @get("legend")' block but before return graph:

if @get("hover")
  hoverDetail = new Rickshaw.Graph.HoverDetail {
    graph: graph
  }

return graph

then add data-hover="true" to your widget definition in the dashboard.

HoverDetail can be implemented with the following added to rickshawgraph.coffee right after the 'if @get("legend")' block but before return graph:

if @get("hover")
  hoverDetail = new Rickshaw.Graph.HoverDetail {
    graph: graph
  }

return graph

then add data-hover="true" to your widget definition in the dashboard.

@activars

This comment has been minimized.

Show comment Hide comment
@activars

activars Jun 12, 2014

Hi @jwalton

First, thanks for the amazing work! It's sad that I would expect this is pulled into the official repo.

I made a dashing-contrib gem recently. The aim is to bring common dashing widgets into a maintainable fashion. And I also make your widget as a default one to begin with. It's extremely easy to install and upgrade external widgets with dashing-contrib.

I'm hoping to merge a couple of yours into the repository, let me know if you are interested! thanks!

https://github.com/QubitProducts/dashing-contrib

Hi @jwalton

First, thanks for the amazing work! It's sad that I would expect this is pulled into the official repo.

I made a dashing-contrib gem recently. The aim is to bring common dashing widgets into a maintainable fashion. And I also make your widget as a default one to begin with. It's extremely easy to install and upgrade external widgets with dashing-contrib.

I'm hoping to merge a couple of yours into the repository, let me know if you are interested! thanks!

https://github.com/QubitProducts/dashing-contrib

@c-arnab

This comment has been minimized.

Show comment Hide comment
@c-arnab

c-arnab Jun 24, 2014

Hi,
Really nice work..,
if I send two data points in a series, is it possible to make one rendered as bar and the other rendered as line in the same graph..

c-arnab commented Jun 24, 2014

Hi,
Really nice work..,
if I send two data points in a series, is it possible to make one rendered as bar and the other rendered as line in the same graph..

@EllenSebastian

This comment has been minimized.

Show comment Hide comment
@EllenSebastian

EllenSebastian Jul 24, 2014

Hi jwalton, thanks for the awesome widget. We are using it extensively in our dashboard.
Currently if you drag-resize the widget containing the Rickshawgraph, the graph itself does not resize. If I drag the widget to be 2x2, the graph is still 1x1.
Is there a way to make the graph resizable?

Hi jwalton, thanks for the awesome widget. We are using it extensively in our dashboard.
Currently if you drag-resize the widget containing the Rickshawgraph, the graph itself does not resize. If I drag the widget to be 2x2, the graph is still 1x1.
Is there a way to make the graph resizable?

@Sweenj

This comment has been minimized.

Show comment Hide comment
@Sweenj

Sweenj Sep 17, 2014

I'm trying to change some of the values in the scss fine, but it looks like they are not updating accordingly. Any idea why that would be?

Sweenj commented Sep 17, 2014

I'm trying to change some of the values in the scss fine, but it looks like they are not updating accordingly. Any idea why that would be?

@kkzinger

This comment has been minimized.

Show comment Hide comment
@kkzinger

kkzinger Sep 29, 2014

There is a error in rickshawgraph.coffee

At Line 143 there should be

if @get('min') != null then graphOptions.min = @get('min')

instead of

if @get('min') != null then graphOptions.max = @get('min')

After that the "data-min" and "data-max" values are processed right.
Thank you for the great widget!

There is a error in rickshawgraph.coffee

At Line 143 there should be

if @get('min') != null then graphOptions.min = @get('min')

instead of

if @get('min') != null then graphOptions.max = @get('min')

After that the "data-min" and "data-max" values are processed right.
Thank you for the great widget!

@markwainwright

This comment has been minimized.

Show comment Hide comment
@markwainwright

markwainwright Oct 21, 2014

To fix the height of the graph when the widget spans more than one row, you can just change line 124 to:

height = (Dashing.widget_base_dimensions[1] * container.data("sizey")) + Dashing.widget_margins[1] * 2 * (container.data("sizey") - 1)

as in this pull request: Shopify/dashing#309

To fix the height of the graph when the widget spans more than one row, you can just change line 124 to:

height = (Dashing.widget_base_dimensions[1] * container.data("sizey")) + Dashing.widget_margins[1] * 2 * (container.data("sizey") - 1)

as in this pull request: Shopify/dashing#309

@benkirkley

This comment has been minimized.

Show comment Hide comment
@benkirkley

benkirkley Nov 19, 2014

This widget crashes the browser on all my PCs when I try to use the following options:

data-color-scheme="rainbow"
data-color-scheme="near-rainbow"

To reproduce the problem:

  • Create new sample Dashing project
  • Install the rickshaw widget from this gist
  • Place a copy of rickshaw.min.js into assets/javascript (as suggested at top)
  • Change sample.erb file and modify the convergence widget to use the following options:
    data-view="Rickshawgraph" data-color-scheme="rainbow"
  • Start Dashing
  • Browse to dashboard and browser hangs then crashes

This widget crashes the browser on all my PCs when I try to use the following options:

data-color-scheme="rainbow"
data-color-scheme="near-rainbow"

To reproduce the problem:

  • Create new sample Dashing project
  • Install the rickshaw widget from this gist
  • Place a copy of rickshaw.min.js into assets/javascript (as suggested at top)
  • Change sample.erb file and modify the convergence widget to use the following options:
    data-view="Rickshawgraph" data-color-scheme="rainbow"
  • Start Dashing
  • Browse to dashboard and browser hangs then crashes
@gavinhogan

This comment has been minimized.

Show comment Hide comment
@gavinhogan

gavinhogan Nov 28, 2014

Can I change the back-ground color somehow? I usually do this by editing the scss file in the /widgets directlory but I cannot find this file for the Rickshawgraph widget.

Can I change the back-ground color somehow? I usually do this by editing the scss file in the /widgets directlory but I cannot find this file for the Rickshawgraph widget.

@bigg33k

This comment has been minimized.

Show comment Hide comment
@bigg33k

bigg33k Dec 15, 2014

Love this. Having issue displaying the number in the graph. All possibilities of 'data-displayed-value' won't display the number.

bigg33k commented Dec 15, 2014

Love this. Having issue displaying the number in the graph. All possibilities of 'data-displayed-value' won't display the number.

@kevindavis

This comment has been minimized.

Show comment Hide comment
@kevindavis

kevindavis Feb 3, 2015

Also hanging my browser - with seemingly any configuration. Not sure how to debug..

Also hanging my browser - with seemingly any configuration. Not sure how to debug..

@wolfspyre

This comment has been minimized.

Show comment Hide comment
@wolfspyre

wolfspyre Feb 18, 2015

could you demonstrate a couple curl calls to utilize these graphs? I'm having a bit of trouble getting the graph to render the data I post, regardless of which format listed above I attempt to feed a widget.

could you demonstrate a couple curl calls to utilize these graphs? I'm having a bit of trouble getting the graph to render the data I post, regardless of which format listed above I attempt to feed a widget.

@wolfspyre

This comment has been minimized.

Show comment Hide comment
@wolfspyre

wolfspyre Mar 2, 2015

Pretty please? Or point to an example git repo with sample jobs posting data in the proper formats to sample dashboards which display said data for the supported data types? It's mildly difficult for me to piece together all the bits, and examples speak volumes as to how the different parts play together.

Pretty please? Or point to an example git repo with sample jobs posting data in the proper formats to sample dashboards which display said data for the supported data types? It's mildly difficult for me to piece together all the bits, and examples speak volumes as to how the different parts play together.

@wolfspyre

This comment has been minimized.

Show comment Hide comment
@wolfspyre

wolfspyre Mar 2, 2015

I opened an issue against dashing here describing what I'm trying to do, and providing sample debug information. I believe I'm generating the graphite data correctly for send_event, but I'm unable to get graphs to actually render with data. Hopefully, someone will have a greater clue than I what I'm doing wrong, and also have the inclination to point me in the right direction.

I opened an issue against dashing here describing what I'm trying to do, and providing sample debug information. I believe I'm generating the graphite data correctly for send_event, but I'm unable to get graphs to actually render with data. Hopefully, someone will have a greater clue than I what I'm doing wrong, and also have the inclination to point me in the right direction.

@CatsLoveJazz

This comment has been minimized.

Show comment Hide comment
@CatsLoveJazz

CatsLoveJazz Mar 4, 2015

Im having problems when the widgets span more than one row, it seems possibly the padding is'nt taken into account. I have made the edit as recommended above.

  _createGraph: ->
    $node = $(@node)
    $container = $node.parent()
    @clear()
    # Gross hacks. Let's fix this.
    width = (Dashing.widget_base_dimensions[0] * $container.data("sizex")) + Dashing.widget_margins[0] * 2 * ($container.data("sizex") - 1)
    height = (Dashing.widget_base_dimensions[1] * $container.data("sizey")) + Dashing.widget_margins[1] * 2 * ($container.data("sizey") - 1)
    ```
Any help would be appreciated! Thanks

Im having problems when the widgets span more than one row, it seems possibly the padding is'nt taken into account. I have made the edit as recommended above.

  _createGraph: ->
    $node = $(@node)
    $container = $node.parent()
    @clear()
    # Gross hacks. Let's fix this.
    width = (Dashing.widget_base_dimensions[0] * $container.data("sizex")) + Dashing.widget_margins[0] * 2 * ($container.data("sizex") - 1)
    height = (Dashing.widget_base_dimensions[1] * $container.data("sizey")) + Dashing.widget_margins[1] * 2 * ($container.data("sizey") - 1)
    ```
Any help would be appreciated! Thanks
@Hackuracy

This comment has been minimized.

Show comment Hide comment
@Hackuracy

Hackuracy May 20, 2015

Like gavinhogan, i need to change bgcolor.

In my .erb file in div section :
style="background-color:#303A3C"

Like gavinhogan, i need to change bgcolor.

In my .erb file in div section :
style="background-color:#303A3C"

@JC1738

This comment has been minimized.

Show comment Hide comment
@larrycai

This comment has been minimized.

Show comment Hide comment
@larrycai

larrycai Jul 2, 2015

can u add snapshot in gist ?

larrycai commented Jul 2, 2015

can u add snapshot in gist ?

@derro

This comment has been minimized.

Show comment Hide comment
@derro

derro Jul 3, 2015

Does anyone have troubles with the "unstack" attribute?
When I'm using it, it is still stacked when using areas, or not aligned as it should when using bars.

derro commented Jul 3, 2015

Does anyone have troubles with the "unstack" attribute?
When I'm using it, it is still stacked when using areas, or not aligned as it should when using bars.

@Wernervdmerwe

This comment has been minimized.

Show comment Hide comment
@Wernervdmerwe

Wernervdmerwe Jul 10, 2015

My x values are epoc values derived from the 1st day of the month.
For some reason it shows a future month off the widget, resulting in the month overlapping the next widget.
Anyone have an idea how to curb this?

My x values are epoc values derived from the 1st day of the month.
For some reason it shows a future month off the widget, resulting in the month overlapping the next widget.
Anyone have an idea how to curb this?

@ankita25

This comment has been minimized.

Show comment Hide comment
@ankita25

ankita25 Aug 10, 2015

If the series length is unequal, the line graph is not getting rendered properly. Did someone else have same issue?

If the series length is unequal, the line graph is not getting rendered properly. Did someone else have same issue?

@aspence7

This comment has been minimized.

Show comment Hide comment
@aspence7

aspence7 Aug 10, 2015

Great widget, however I'm having trouble with a sizing issue and would welcome any help.

I want to shrink the widget content so that it isn't being drawn from 0,0 and add some padding into it. Currently the labels are all squished and it doesn't look great.

Thanks.

Great widget, however I'm having trouble with a sizing issue and would welcome any help.

I want to shrink the widget content so that it isn't being drawn from 0,0 and add some padding into it. Currently the labels are all squished and it doesn't look great.

Thanks.

@aireater

This comment has been minimized.

Show comment Hide comment
@aireater

aireater Aug 11, 2015

@derro I'm also having trouble with unstacked bar graphs. The stacked part just floats next to where the other bar ends. Did you find a solution?

@derro I'm also having trouble with unstacked bar graphs. The stacked part just floats next to where the other bar ends. Did you find a solution?

@snayler0

This comment has been minimized.

Show comment Hide comment
@snayler0

snayler0 Sep 3, 2015

Has anyone got this working with renderer 'multi'?

I'm trying to build a burnup chart with this and it's so very close to exactly what I need.

my code looks like this but doesn't work:

in the erb file:

<li data-row="3" data-col="4" data-sizex="2" data-sizey="1">
    <div data-id="burnup-chart" data-view="Rickshawgraph" data-renderer="multi" data-max="40"></div>
</li>

and i want to pass the data like so:

iterationEstimates = []
iterationEstimates.push({name: "Delivered", renderer: "bar", data: currentPoints}, {name: "Estimated", renderer: "line", data: estimatePoints}, {name: "Outlook", renderer: "line", data: outlookPoints})

Where currentPoints, estimatePoints, and outlookPoints are predefined x and y points.

Has anyone managed to do something like this? If so.... how? :)

snayler0 commented Sep 3, 2015

Has anyone got this working with renderer 'multi'?

I'm trying to build a burnup chart with this and it's so very close to exactly what I need.

my code looks like this but doesn't work:

in the erb file:

<li data-row="3" data-col="4" data-sizex="2" data-sizey="1">
    <div data-id="burnup-chart" data-view="Rickshawgraph" data-renderer="multi" data-max="40"></div>
</li>

and i want to pass the data like so:

iterationEstimates = []
iterationEstimates.push({name: "Delivered", renderer: "bar", data: currentPoints}, {name: "Estimated", renderer: "line", data: estimatePoints}, {name: "Outlook", renderer: "line", data: outlookPoints})

Where currentPoints, estimatePoints, and outlookPoints are predefined x and y points.

Has anyone managed to do something like this? If so.... how? :)

@andrescolodrero

This comment has been minimized.

Show comment Hide comment
@andrescolodrero

andrescolodrero Oct 28, 2015

Hi,
im having this problem with "redcarpet" when im loading the widget.

i installed the GEM but still failing.

iWARN: tilt autoloading 'redcarpet' in a non thread-safe way; explicit require 'r
edcarpet' suggested.
2015-10-28 14:01:19 - LoadError - cannot load such file -- redcarpet:
C:/Ruby21/lib/ruby/gems/2.1.0/gems/backports-3.6.6/lib/backports/std_lib
.rb:9:in require' C:/Ruby21/lib/ruby/gems/2.1.0/gems/backports-3.6.6/lib/backports/std_lib .rb:9:inrequire_with_backports'
C:/Ruby21/lib/ruby/gems/2.1.0/gems/tilt-1.4.1/lib/tilt/template.rb:144:i
n require_template_library' C:/Ruby21/lib/ruby/gems/2.1.0/gems/tilt-1.4.1/lib/tilt/markdown.rb:56:ininitialize_engine'

Hi,
im having this problem with "redcarpet" when im loading the widget.

i installed the GEM but still failing.

iWARN: tilt autoloading 'redcarpet' in a non thread-safe way; explicit require 'r
edcarpet' suggested.
2015-10-28 14:01:19 - LoadError - cannot load such file -- redcarpet:
C:/Ruby21/lib/ruby/gems/2.1.0/gems/backports-3.6.6/lib/backports/std_lib
.rb:9:in require' C:/Ruby21/lib/ruby/gems/2.1.0/gems/backports-3.6.6/lib/backports/std_lib .rb:9:inrequire_with_backports'
C:/Ruby21/lib/ruby/gems/2.1.0/gems/tilt-1.4.1/lib/tilt/template.rb:144:i
n require_template_library' C:/Ruby21/lib/ruby/gems/2.1.0/gems/tilt-1.4.1/lib/tilt/markdown.rb:56:ininitialize_engine'

@zd-cseeman

This comment has been minimized.

Show comment Hide comment
@zd-cseeman

zd-cseeman Oct 29, 2015

@andrescolodrero, I'm running into the same issue as you. Any progress?

@andrescolodrero, I'm running into the same issue as you. Any progress?

@sej7278

This comment has been minimized.

Show comment Hide comment
@sej7278

sej7278 Oct 30, 2015

does anyone else have major problems with the axis?

the X axis tick text overwrites itself when using a time base, so you can't read it as it tries to write 24 hours worth of hh:mm text in one column of space!

the Y axis scaling seems a bit random - i've got values that are all over 20 and yet the line graph Y ticks are 0,5,10,20, so you end up with a vertically squashed graph at the top of the widget and the bottom 90% of the widget empty.

so is there any way to auto-scale the Y axis (not data-min/data-max as it needs to be dynamic) and/or limit the number of X ticks?

sej7278 commented Oct 30, 2015

does anyone else have major problems with the axis?

the X axis tick text overwrites itself when using a time base, so you can't read it as it tries to write 24 hours worth of hh:mm text in one column of space!

the Y axis scaling seems a bit random - i've got values that are all over 20 and yet the line graph Y ticks are 0,5,10,20, so you end up with a vertically squashed graph at the top of the widget and the bottom 90% of the widget empty.

so is there any way to auto-scale the Y axis (not data-min/data-max as it needs to be dynamic) and/or limit the number of X ticks?

@cob16

This comment has been minimized.

Show comment Hide comment
@cob16

cob16 Nov 25, 2015

@sej7278 you can send min and max in you send event so for raw graphite data you can do:

def data_with_minmax(nested_array)
  out = nested_array.first[:datapoints].collect {|ind| ind[0]}.minmax
  {series: nested_array, min: out[0]-1, max: out[1]+1 }
end

send_event("open_tickets"  , data_with_minmax(graphite_data) )

Results

capture

cob16 commented Nov 25, 2015

@sej7278 you can send min and max in you send event so for raw graphite data you can do:

def data_with_minmax(nested_array)
  out = nested_array.first[:datapoints].collect {|ind| ind[0]}.minmax
  {series: nested_array, min: out[0]-1, max: out[1]+1 }
end

send_event("open_tickets"  , data_with_minmax(graphite_data) )

Results

capture

@dallimor

This comment has been minimized.

Show comment Hide comment
@dallimor

dallimor Dec 16, 2015

@andrescolodrero, @zd-cseeman, I ran into the redcarpet problem as well. The solution is to add gem 'redcarpet' to your Gemfile.

@andrescolodrero, @zd-cseeman, I ran into the redcarpet problem as well. The solution is to add gem 'redcarpet' to your Gemfile.

@MattRK

This comment has been minimized.

Show comment Hide comment
@MattRK

MattRK Jan 3, 2016

@snayler0 did you ever get the multi renderer working? I've tried it about 20 different ways and have yet to get it working.

MattRK commented Jan 3, 2016

@snayler0 did you ever get the multi renderer working? I've tried it about 20 different ways and have yet to get it working.

@davepmarshall

This comment has been minimized.

Show comment Hide comment
@davepmarshall

davepmarshall Jan 26, 2016

@derro, @aireater, @jwalton
I believe the unstack option failing is due to this issue.

I think this is fixed in my fork.

@derro, @aireater, @jwalton
I believe the unstack option failing is due to this issue.

I think this is fixed in my fork.

@aysark

This comment has been minimized.

Show comment Hide comment
@aysark

aysark Jan 27, 2016

@davepmarshall thanks that fixed it!

@MattRK, i got multi rendering working:

Simply send your event like so, setting your renderer for each plot:

        series = [
          {
            name: 'Lines Added',
            data: lines_added_points,
            renderer: 'bar'
          },
          {
            name: 'Lines Deleted',
            data: lines_deleted_points,
            renderer: 'bar'
          },
          {
            name: 'Linear Regression',
            data: line_fit_points,
            renderer: 'line'
          }
        ]
        send_event("code churn #{data_id}", series: series)

And in your graph2.coffee, change the graphOptions to set the renderer as multi:

    graphOptions = {
        element:  $graph.get(0),
        renderer: 'multi',
        width:    width,
        height:   height,
        series:   series,
        stack:    !@get('unstack')
      }

Let me know if that works for you... i did multi rendering 2 months ago so i maybe forgetting something else, but that's all i remember now :shipit:

aysark commented Jan 27, 2016

@davepmarshall thanks that fixed it!

@MattRK, i got multi rendering working:

Simply send your event like so, setting your renderer for each plot:

        series = [
          {
            name: 'Lines Added',
            data: lines_added_points,
            renderer: 'bar'
          },
          {
            name: 'Lines Deleted',
            data: lines_deleted_points,
            renderer: 'bar'
          },
          {
            name: 'Linear Regression',
            data: line_fit_points,
            renderer: 'line'
          }
        ]
        send_event("code churn #{data_id}", series: series)

And in your graph2.coffee, change the graphOptions to set the renderer as multi:

    graphOptions = {
        element:  $graph.get(0),
        renderer: 'multi',
        width:    width,
        height:   height,
        series:   series,
        stack:    !@get('unstack')
      }

Let me know if that works for you... i did multi rendering 2 months ago so i maybe forgetting something else, but that's all i remember now :shipit:

@Rufix

This comment has been minimized.

Show comment Hide comment
@Rufix

Rufix Feb 3, 2016

@aysark, this is quite out of context, could you please elaborate on this? Tried everything you mentioned and it doesn't work :(

Rufix commented Feb 3, 2016

@aysark, this is quite out of context, could you please elaborate on this? Tried everything you mentioned and it doesn't work :(

@pdolinaj

This comment has been minimized.

Show comment Hide comment
@pdolinaj

pdolinaj Feb 3, 2016

It seems to be impossible to change graph X-axis label color from default black to anything else, e.g. white?

Interestingly the Y-axis label color can be changed easily through the CSS.

Can anyone please help?

@cob16 - I can see that your graph has white labels, how did you make it work?

pdolinaj commented Feb 3, 2016

It seems to be impossible to change graph X-axis label color from default black to anything else, e.g. white?

Interestingly the Y-axis label color can be changed easily through the CSS.

Can anyone please help?

@cob16 - I can see that your graph has white labels, how did you make it work?

@pcompassion

This comment has been minimized.

Show comment Hide comment
@pcompassion

pcompassion Feb 8, 2016

Sorry but I have to ask, how can I use this widget?

I have no experience with coffee nor scss.

I asked a question in SO (http://stackoverflow.com/questions/35272320/how-to-use-rickshawgraph-of-django-dashing) about this..

Sorry but I have to ask, how can I use this widget?

I have no experience with coffee nor scss.

I asked a question in SO (http://stackoverflow.com/questions/35272320/how-to-use-rickshawgraph-of-django-dashing) about this..

@Spartacus38

This comment has been minimized.

Show comment Hide comment
@Spartacus38

Spartacus38 Apr 27, 2016

Have trouble getting this working, as soon as I drop the coffee file in all my dashboards go blank, any advice?

Have trouble getting this working, as soon as I drop the coffee file in all my dashboards go blank, any advice?

@jimthree

This comment has been minimized.

Show comment Hide comment
@jimthree

jimthree May 4, 2016

I have learnt to delete my history.yml file everytime prior to starting Dashing, this seems to help with bad "crashy" data not being used.

However, my problem is that I just can't get my X axis ticks to display, despite passing in unix timestamps, my data look like:
{"x"=>1461898499, "y"=>3.255}
I don't have any ticks or values displayed at all on the X axis

I'm having a hard time working out how I can apply the documentation on the official Rickshaw page to Rickshaw-Dashing. The official Rickshaw docs (http://code.shutterstock.com/rickshaw/) suggest to enable time, use this:

var xAxis = new Rickshaw.Graph.Axis.Time({
    graph: graph
});

xAxis.render();

...but I've got no idea where that goes or how it applies to rickshaw-dashing. Does anyone have any help?

jimthree commented May 4, 2016

I have learnt to delete my history.yml file everytime prior to starting Dashing, this seems to help with bad "crashy" data not being used.

However, my problem is that I just can't get my X axis ticks to display, despite passing in unix timestamps, my data look like:
{"x"=>1461898499, "y"=>3.255}
I don't have any ticks or values displayed at all on the X axis

I'm having a hard time working out how I can apply the documentation on the official Rickshaw page to Rickshaw-Dashing. The official Rickshaw docs (http://code.shutterstock.com/rickshaw/) suggest to enable time, use this:

var xAxis = new Rickshaw.Graph.Axis.Time({
    graph: graph
});

xAxis.render();

...but I've got no idea where that goes or how it applies to rickshaw-dashing. Does anyone have any help?

@cFigJr

This comment has been minimized.

Show comment Hide comment
@cFigJr

cFigJr Jul 26, 2016

Hi! Great widget!!

Has anyone implemented a graph with two y-axis? If so, can you share the solution?
I've seen it done in a Rickshaw example page, but so far I was not able to get it working on Dashing.
http://code.shutterstock.com/rickshaw/examples/scaled.html

Thanks!

cFigJr commented Jul 26, 2016

Hi! Great widget!!

Has anyone implemented a graph with two y-axis? If so, can you share the solution?
I've seen it done in a Rickshaw example page, but so far I was not able to get it working on Dashing.
http://code.shutterstock.com/rickshaw/examples/scaled.html

Thanks!

@johno1985

This comment has been minimized.

Show comment Hide comment
@johno1985

johno1985 Aug 22, 2016

Hi, is there a way to change the x-axis to display beneath the graph area?

Hi, is there a way to change the x-axis to display beneath the graph area?

@GillesC

This comment has been minimized.

Show comment Hide comment
@GillesC

GillesC Sep 21, 2017

Hello
Is it possible to hide/remove the x-axis?

GillesC commented Sep 21, 2017

Hello
Is it possible to hide/remove the x-axis?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment