Render Jira Agile Burndown in chartist.js? - javascript

Issue
I'm using json data from jira to render a project's burndown chart. For reasons I won't go into, I can't use the built-in Jira Agile charts. I'm using chartist.js to render the burndown but I'm running into troubles and would appreciate a chartist.js user's input.
I've attached an image of the chart I want to generate as a reference.
Problem
Burndown events happen more than once during the day. Each has its own time that it happened. I don't want to show the specific time each happened in the x axis label group. Is there a way to "group" the events for a given day on a specific day, but show that they didn't all happen at once?
I want to create a burndown "guideline" (see the grey line in the attached image). Is there an easy way to have a line start from the top and finish at the bottom for a given time?
Asides
I've been enjoying using chartist.js, but I'm not married to it for my project, I can use any chart library I want. I would gladly accept suggestions for another charting library that does what I need it to.

Although Chartist does not directly support a convenient API for creating time based charts (this will land very soon), we have added dynamic axis configuration which allows you to switch the standard X axis type (step based) to a more sophisticated scale axis.
As Dates will be converted to numbers and the math behind the scene is the same, you can very easily create time based charts with a bit of manual work. We have no tick generator based on time frames as of yet but again this will come with the TimeAxis that will be created very soon in Chartist.
To get more information on the custom axis configuration you can read the docs here: http://gionkunz.github.io/chartist-js/getting-started.html#switching-axis-type
To show you and others how easy it would be to implement a burndown chart I've created one for you with Chartist 0.9.1. I'm using moment.js to format the dates.
Here is the jsbin: http://jsbin.com/lokozu/edit?html,js,output
var chart = new Chartist.Line('.ct-chart', {
series: [{
name: 'remaining',
data: [
{x: new Date(143134652600), y: 53},
{x: new Date(143334652600), y: 40},
{x: new Date(143354652600), y: 45},
{x: new Date(143356652600), y: 41},
{x: new Date(143366652600), y: 40},
{x: new Date(143368652600), y: 38},
{x: new Date(143378652600), y: 34},
{x: new Date(143568652600), y: 32},
{x: new Date(143569652600), y: 18},
{x: new Date(143579652600), y: 11}
]
}, {
name: 'stories',
data: [
{x: new Date(143134652600), y: 53},
{x: new Date(143334652600), y: 30},
{x: new Date(143384652600), y: 30},
{x: new Date(143568652600), y: 10}
]
}]
}, {
axisX: {
type: Chartist.FixedScaleAxis,
divisor: 5,
labelInterpolationFnc: function(value) {
return moment(value).format('MMM D');
}
},
axisY: {
onlyInteger: true,
low: 0
},
series: {
remaining: {
lineSmooth: Chartist.Interpolation.step(),
showPoint: false
},
stories: {
lineSmooth: false
}
}
});

Related

Is it possible to plot points on a line graph using two separate arrays? (highcharts)

I am trying to create a line chart using using two separate arrays pulled from a json file to make one one.
Here is what my json file looks like
{
"time": [1240, 1250, 1300, 1310],
"volt": [12.218, 13, 12, 14]
}
Here is the code I thought would work
https://codesandbox.io/s/boring-elbakyan-bj7gg?file=/data.json
which uses
data: {
x: jsonData.time,
y: jsonData.volt,
},
which seemed to make sense to me but isn't working
This works but the time stamps are not displaying current times or doesn't display at all
https://codesandbox.io/s/awesome-hamilton-kkrgt?file=/index.js
Any help is greatly appreciated!!
You need to map your data to the format required by Highcharts. In your case:
an array of arrays with [x, y] values:
series: [{
data: jsonData2.time.map((x, index) => [x, jsonData2.volt[index]])
}]
or an array of objects with { x, y } values:
series: [{
data: jsonData2.time.map((x, index) => ({ x: x, y: jsonData2.volt[index]}))
}]
Live demo: https://codesandbox.io/s/fancy-cloud-mx9z-mx9ze?file=/index.js
API Reference: https://api.highcharts.com/highcharts/series.line.data

Chart.js 2 - Always display only some tooltips in bubble chart

I work with chart js version 2.5.0. I have a bubble chart and I would like that when a bubble is clicked, it keep the tooltip corresponding remains displayed.
I tried to make a plugin, in which it is enough to add a keepTooltipOpen parameter in the data like that:
datasets: [{
type: 'bubble',
label: "set2",
data: [{
x: 14,
y: 30,
r: 60,
//Here is the added parameter.
keepTooltipOpen: true
}, {
x: 2,
y: 5,
r: 30
}]
You can find the Fiddle here. There is an error in afterDatasetsDrawwhen the tooltip is update. Open web console to see it.
Someone have a suggestion to resolve this problem?
In chart.js version 2.5.0, you need to write _options: chart.options.tooltips,instead of _options: chart.options,.
New Fiddle is here.

FP: Trees - map, fold, each. How?

I have a working OOP code that recursively renders a composition of graphical elements to a canvas. There's quite a bit to dislike about it and I'm trying to see what a functional version will look like.
Sure, one can write a specialised recursive pure function, but as the framework involves similar algorithms, I'd like to:
Harness the power of function composition.
See how FP - and its data piping paradigm (transforming data through pure functions) - lands itself to more complex structures than lists (trees/graphs) and less trivial algorithms (than say, finding all odd number by sequentially iterating the list).
Inspired by Lazy.js, I've started coding and got this far:
LazyTree.from( drawing )
.keepNodes( visible )
.keepChildrenOf( nonClipping )
.traverse( log );
But as for map and fold - I have many unanswered questions.
Goal
Here's a simplified version of the problem I'm trying to solve:
Data
A composition (hierarchy) of rectangles. The bounds of each are in relative coordinates (to its parent):
const drawing = {
name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{
name: 'Left eye',
bounds: { x: 10, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{
name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},{
name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{
name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};
Task - getAbsoluteBounds
The task is to convert this composition to one that has absolute coordinates (as shown in the comments).
Issues and thoughts
Fold?
The absolute coordinates of a child is its relative coordinates transposed by its parent absolute coordinates. So a fold with its accumulator are candidates to do this.
But fold is associated with catamorphism and verbs like combine, and typically returns a single value.
The transformation in question takes a tree and returns an identical structure but with different values - so it sounds more like a map, but one that needs an accumulator.
As far as the accumulator goes, it is worth noting that all the children of a specific node should get the same accumulator. For the data above, both Left eye and Right eye should get the same absolute coordinates of Face (as opposed to the Right eye getting the returned accumulator of Left eye in depth-first-traversal).
Another thing I'm not clear about is who should be in charge of constructing the output tree. Should it be the high-order functions (fold, map, or whatever), or should it be the aggregator?
Stop conditions
Related the the previous section, consider all rectangles to clip their children, and the following composition:
const drawing = {
name: 'Parent',
bounds: { x: 10, y: 10, w: 10, h: 10 },
children: [{
name: 'Child',
bounds: { x: 1000000, y: 1000000, w: 10, h: 10 },
children: [{
name: 'Grandchild',
bounds: { x: 5, y: 5, w: 5, h: 5 }
}]
}]
};
The Child bounds are out-of-bound with relation to its parent (Parent), so branch traversal should stop when traversing to Child (no point traversing to Grandchild).
The question is: How can this be implemented with a fold function? One solution is to stop branch traversal when the accumulator returns an agreed valued (say undefined). But this is somewhat a departure from the fold API for lists.
Pre and post visit
The rendering algorithm involves:
fill( shape );
renderChildren( shape );
stroke( shape );
I wonder how this can be achieved with something like traverse() or each(). Should these take 2 callbacks (pre, post)?
Traversal strategies
Tree traversal may be:
Depth or Breadth first.
Top-down or Bottom-up (for the latter, see a specialised example for transforming an AST, using reduce).
With lists, we have functions like reverse(). Lazy.js allows adding a custom iterator that can then be chained.
So it seems the the FP way to handle traversal strategy is a transforming function. Is there anything else to it?
Summary
I've touched upon a few of the challenges in implementing a rendering algorithm for a tree structure using the data piping model.
I question if any other FP approaches would be more appropriate here? And perhaps the data piping model is not fit for these sort of problems. Or perhaps, I should simply forget the APIs one sees in FP libraries (that deal nearly exclusively lists) and create one that is appropriate for the task at hand (eg, having a map function that also involves an accumulator).
I couldn't find any FP library dedicated for trees, and information out there is typically limited to very simple problems.
So hopefully, someone would reply with something along the lines of 'this is how it should be done'.
As far as I have understood the details you might do as follows.
It will proceed traversing those items remaining within the parent's boundaries, converting their coordinates to absolute and rendering them just afterwards. However if the child's boundaries overlaps the parent's boundaries the child and it's descendants are skipped. No conversion to absolute coordinates and rendering are done for those.
function render(bounds){
console.log("Rendered:", bounds);
}
function relToAbs(o, b = {x: 0, y:0, w:Infinity, h:Infinity}, go = true){
go = o.bounds.x < b.w && o.bounds.y < b.h ? (o.bounds.x += b.x, o.bounds.y += b.y, render(o.bounds), go) : !go;
o.children && go && (o.children = o.children.map(p => relToAbs(p,o.bounds,go)));
return o;
}
var drawing = { name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{ name: 'Left eye',
bounds: { x: 200, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{ name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},
{ name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{ name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};
console.log(JSON.stringify(relToAbs(drawing),null,2));

Highcharts - Is it possible to customize the bars in column range type?

I would like to generate a report using highcharts with extjs. I have tried out the sample http://jsfiddle.net/6qsvjark/2/.
series: [{
name: 'Data',
data: [{
x: 0,
low: 7,
high: 8
},{
x: 0,
low: 8.1,
high: 9,
color: "#202020"
},{
x: 1,
low: 6.5,
high: 7.5
},{
x: 1,
low: 7.5,
high: 8.5,
color: "#202020"
}]
}]
Is it possible to customize the size/shape (eg.,rounded edges) of bars in columnrange type of highcharts? Also, is it possible to place a symbol between 2 data in series? Please refer the image
symbol between two data (with same 'x' point) in a series
You can do quite a bit of customization to highcharts. However achieving these effects often means somewhat pushing the limit of what different customization options were meant to be used for and adding some hard-codded items, hence making your chart less portable for different sizes. It will probably cost some extra time and effort to make it work well.
As a starting point you can use the following sample:
http://jsfiddle.net/c96qy0qa/
Here I use borderRadius to round the corners, and custom label for the 3rd (middle) series to display an icon in between other two series. Also I use series shown in the middle to overlap the other two, in order to hide the rouded corners in the middle.
series: [{
name: 'Male',
borderRadius:20,
data: [-2.2, -2.2]
},{
name: 'Female',
borderRadius:20,
data: [2.1, 3.0 ]
}, {
name: 'blah',
borderWidth:30,
borderRadius:10,
borderColor:"#ffffff",
dataLabels:{
enabled:true,
useHTML:true,
crop:false,
formatter:function(){ return "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AwJCBoDRV/pcAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABkklEQVRo3u1aQRKDMAgsTI4+xP+/xod4p6fOdNqoARZInXpsY8jCAhsTEpHHHR5+3OS5DZB29ifttKENyiJrBBA6ypEIEJHAyqlFO20Ip7VZON4Do4kWZ3PZC06dI55Je07w0ufKsUNAvCCQxeRo/ksgIwY9NLQA6tlrlSB671sjZe4jEcXAQ2GubIYem5/j+RdB9JopZxuPyEPaafvKEe0CrbliAXD2DlfQCN1DhoGgKhSisR79zt6JRxaniYIsslocx9GejpA3vXGM4qiX+176ckQya9RByA4Rpa1GooOWOGylwmwfIDh7MVE7T/YY1i4qsh+5k12zOIQ+O5oDUrWywEyltaw952p8eGdHABoZ0zIXfjafR8vJImuLBiGLrBbg2obKkbx+GRuRIlppo6YW6ruTJzrQ/QiqFGsio6Li+54d6f3MSH9FJFNyoG2li8YoW2UnVpo9vEn9ao4FPB0d7ZiG9iyyKqnEaPWpLqwKok+sqooHae+izHqJgCuMhmx/UbeDMlVBKJDq53/NabbnCakwWb7DRriDAAAAAElFTkSuQmCC'>"; },
x:0
},
data: [0.3, 0.3]
}]

Display multiple rickshaw graphs on the same html page

I currently have a couple of dynamically generated JS based Rickshaw graphs similar to http://code.shutterstock.com/rickshaw/examples/extensions.html
I am kinda new to JS, html etc. How do I go about displaying more than one rickshaw graph on the same html page?
NOTE: I am NOT asking about showing multiple trends on the same graph.
let's say you have the following graph:
var graph = new Rickshaw.Graph({
series: [ { data: [ { x: 0, y: 2 }, { x: 1, y: 4 } ...
renderer: 'area',
element: document.querySelector('#graph')
});
graph.render();
what you've just done is create a global variable called graph that is an instance of the Rickshaw class*, which renders content to the HTML element whose id is graph (ie: <div id="graph"></div>).
To render another graph, create a new instance:
var graph2 = new Rickshaw.Graph({
series: [ { data: [ { x: 0, y: 5 }, { x: 1, y: 9 } ...
renderer: 'area',
element: document.querySelector('#graph2')
});
graph2.render();
... and bind it to a new element:
<div id="graph2">
*Although Javascript has prototypes rather than classes, it is helpful to think of functions in classical terms sometimes when you are invoking them with the new keyword.

Categories

Resources