Skip to content

Commit

Permalink
add POC waffle viz
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasneirynck committed May 22, 2017
1 parent 2da49f1 commit dfeadfc
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/core_plugins/waffle_vis/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function (kibana) {

return new kibana.Plugin({
uiExports: {
visTypes: ['plugins/waffle_vis/waffle_vis']
}
});
}
4 changes: 4 additions & 0 deletions src/core_plugins/waffle_vis/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "waffle_vis",
"version": "kibana"
}
27 changes: 27 additions & 0 deletions src/core_plugins/waffle_vis/public/icon-heatmap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/core_plugins/waffle_vis/public/waffle.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.waffle-waffle {
position: absolute;
width: 100%;
height: 100%;
}

.waffle-legend {
position: absolute;
width: 20%;
top: 0;
right: 0;
}
53 changes: 53 additions & 0 deletions src/core_plugins/waffle_vis/public/waffle_vis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { CATEGORY } from 'ui/vis/vis_category';
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { WaffleVisualization } from './waffle_visualization';
import { VisSchemasProvider } from 'ui/vis/editors/default/schemas';
import image from './icon-heatmap.svg';
import './waffle.less';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';


VisTypesRegistryProvider.register(function TileMapVisType(Private) {

const Schemas = Private(VisSchemasProvider);
const VisFactory = Private(VisFactoryProvider);

return VisFactory.createBaseVisualization({
name: 'waffle_vis',
title: 'Waffle Vis',
image,
description: 'Waffle visualization',
category: CATEGORY.BASIC,
visConfig: {
defaults: {}
},
responseHandler: 'basic',
implementsRenderComplete: true,
visualization: WaffleVisualization,
editorConfig: {
collections: {},
optionsTemplate: `<div>Ma options</div>`,
schemas: new Schemas([
{
group: 'metrics',
name: 'metric',
title: 'Squares',
min: 1,
max: 1,
aggFilter: ['!geo_centroid'],
defaults: [
{ schema: 'metric', type: 'count' }
]
},
{
group: 'buckets',
name: 'split',
title: 'Split Chart',
min: 0,
max: 1,
aggFilter: '!geohash_grid'
}
])
}
});
});
168 changes: 168 additions & 0 deletions src/core_plugins/waffle_vis/public/waffle_visualization.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import d3 from 'd3';


class WaffleVisualization {
constructor(container) {
this._container = container;
this._waffleContainer = document.createElement('div');
this._waffleContainer.setAttribute('class', 'waffle-waffle');
this._legendContainer = document.createElement('div');
this._legendContainer.setAttribute('class', 'waffle-legend');
this._container.appendChild(this._waffleContainer);
this._container.appendChild(this._legendContainer);
}


async render(vis, esResponse) {
return new Promise((resolve) => {

this._clear();
const data = convertResponse(esResponse);
console.log(data);
this._createWaffleVis(data);
resolve(true);
});
}


_createWaffleVis(data) {

//copy pasted from http://bl.ocks.org/XavierGimenez/8070956
let total = 0;
const widthSquares = 20;
const heightSquares = 5;
const squareSize = 25;
let squareValue = 0;
const gap = 1;
let theData = [];

const color = d3.scale.category10();

//total
total = d3.sum(data, function (d) {
return d.value;
});

//value of a square
squareValue = total / (widthSquares * heightSquares);

//remap data
data.forEach(function (d, i) {
d.value = +d.value;
d.units = Math.floor(d.value / squareValue);
theData = theData.concat(
new Array(d.units + 1).join(1).split('').map(function () {
return {
squareValue: squareValue,
units: d.units,
value: d.value,
groupIndex: i
};
})
);
});

const width = (squareSize * widthSquares) + widthSquares * gap + 25;
const height = (squareSize * heightSquares) + heightSquares * gap + 25;

let col;
let row;
d3.select(this._waffleContainer)
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.selectAll('div')
.data(theData)
.enter()
.append('rect')
.attr('width', squareSize)
.attr('height', squareSize)
.attr('fill', function (d) {
return color(d.groupIndex);
})
.attr('x', function (d, i) {
//group n squares for column
col = Math.floor(i / heightSquares);
return (col * squareSize) + (col * gap);
})
.attr('y', function (d, i) {
row = i % heightSquares;
return (heightSquares * squareSize) - ((row * squareSize) + (row * gap));
})
.append('title')
.text(function (d) {
return 'Age range: ' + data[d.groupIndex].key + ' | ' + d.value + ' , ' + d.units + '%';
});

//add legend with categorical data
const legend = d3.select(this._legendContainer)
.append('svg')
.attr('width', 300)
.attr('height', 200)
.append('g')
.selectAll('div')
.data(data)
.enter()
.append('g')
.attr('transform', function (d, i) {
return 'translate(0,' + i * 20 + ')';
});
legend.append('rect')
.attr('width', 18)
.attr('height', 18)
.style('fill', function (d, i) {
return color(i);
});
legend.append('text')
.attr('x', 25)
.attr('y', 13)
.text(function (d) {
return d.key;
});

//add value of a unit square
const legend2 = d3.select('#legend')
.select('svg')
.append('g')
.attr('transform', 'translate(100,0)');

legend2.append('text')
.attr('y', '14')
.attr('font-size', '18px')
.text('Total: ' + total)
.attr('fill', '#444444');

}

_clear() {
d3.select(this._waffleContainer).selectAll('*').remove();
d3.select(this._legendContainer).selectAll('*').remove();
}


destroy() {
this._container.innerHTML = '';
}
}


function

convertResponse(esResponse) {
const data = [];
for (let i = 0; i < esResponse.rows.length; i += 1) {
if (esResponse.rows[i].rows[0] && esResponse.rows[i].rows[0][0]) {
data.push({
key: esResponse.rows[i].rows[0][0].$parent.value,
value: esResponse.rows[i].rows[0][0].value
});
}
}
return data;
}


export {
WaffleVisualization
};

0 comments on commit dfeadfc

Please sign in to comment.