diff --git a/js/components/PieChart.js b/js/components/PieChart.js
new file mode 100644
index 0000000..d80fac9
--- /dev/null
+++ b/js/components/PieChart.js
@@ -0,0 +1,136 @@
+var d3 = require('d3');
+var React = require('react');
+
+var Slice = React.createClass({
+ displayName: "Slice",
+ render: function() {
+ if (this.props.angle > Math.PI*2 - 0.00001) {
+ var slice = ();
+ } else {
+ var center = this.props.cx + " " + this.props.cy;
+ var dx = Math.cos(this.props.angle)*this.props.radius - this.props.radius;
+ var dy = Math.sin(this.props.angle)*this.props.radius - 0.00001;
+ var large_arc_flag = this.props.angle > Math.PI ? 1 : 0;
+ var rotateDegrees = this.props.startAngle * 180 / Math.PI;
+
+ slice = ();
+ }
+ return (
+
+ {this.props.title}
+ {slice}
+
+ );
+ }
+});
+
+module.exports = React.createClass({
+ displayName: "PieChart",
+ sortedSeries: function(series) {
+ // Return an array of the series names, from highest to lowest sums (in
+ // absolute terms)
+
+ var seriesNames = [];
+ var seriesValues = {};
+ for (var child in series) {
+ if (series.hasOwnProperty(child)) {
+ seriesNames.push(child);
+ seriesValues[child] = series[child].reduce(function(accum, curr, i, arr) {
+ return accum + curr;
+ }, 0);
+ }
+ }
+ seriesNames.sort(function(a, b) {
+ return seriesValues[b] - seriesValues[a];
+ });
+
+ return [seriesNames, seriesValues];
+ },
+ render: function() {
+ height = 400;
+ width = 600;
+ legendWidth = 100;
+ xMargin = 70;
+ yMargin = 70;
+ height -= yMargin*2;
+ width -= xMargin*2;
+ var radius = Math.min(height, width)/2;
+
+ var sortedSeriesValues = this.sortedSeries(this.props.report.FlattenedSeries);
+ var sortedSeries = sortedSeriesValues[0];
+ var seriesValues = sortedSeriesValues[1];
+ var r = d3.scaleLinear()
+ .range([0, 2*Math.PI])
+ .domain([0, sortedSeries.reduce(function(accum, curr, i, arr) {
+ return accum + Math.abs(seriesValues[curr]);
+ }, 0)]);
+
+ var slices = [];
+
+ // Add all the slices
+ var legendMap = {};
+ var childId=1;
+ var startAngle = 0;
+ for (var i=0; i < sortedSeries.length; i++) {
+ var child = sortedSeries[i];
+ var value = seriesValues[child];
+ if (value == 0)
+ continue;
+
+ var sliceClasses = "chart-element chart-color" + (childId % 12);
+ var self = this;
+ var sliceOnClick = function() {
+ var childName = child;
+ var onSelectSeries = self.props.onSelectSeries;
+ return function() {
+ onSelectSeries(childName);
+ };
+ }();
+
+ var radians = r(Math.abs(value));
+ var title = child + ": " + value;
+
+ slices.push((
+
+ ));
+ legendMap[child] = childId;
+ childId++;
+ startAngle += radians;
+ }
+
+ var legend = [];
+ for (var series in legendMap) {
+ var legendClasses = "chart-color" + (legendMap[series] % 12);
+ var legendY = (legendMap[series] - 1)*15;
+ legend.push((
+
+ ));
+ legend.push((
+ {series}
+ ));
+ }
+
+ return (
+
+ );
+ }
+});