- {{ comment }} -
diff --git a/app/app/urls.py b/app/app/urls.py
index e872d359b65..5ab7a2c6065 100644
--- a/app/app/urls.py
+++ b/app/app/urls.py
@@ -776,18 +776,7 @@
re_path(r'^_administration/stats/$', dataviz.views.stats, name='stats'),
re_path(r'^_administration/cohort/$', dataviz.views.cohort, name='cohort'),
re_path(r'^_administration/funnel/$', dataviz.views.funnel, name='funnel'),
- re_path(r'^_administration/viz/?$', dataviz.d3_views.viz_index, name='viz_index'),
re_path(r'^_administration/mesh/?$', dataviz.d3_views.mesh_network_viz, name='mesh_network_viz'),
- re_path(r'^_administration/viz/sunburst/(.*)?$', dataviz.d3_views.viz_sunburst, name='viz_sunburst'),
- re_path(r'^_administration/viz/chord/(.*)?$', dataviz.d3_views.viz_chord, name='viz_chord'),
- re_path(r'^_administration/viz/steamgraph/(.*)?$', dataviz.d3_views.viz_steamgraph, name='viz_steamgraph'),
- re_path(r'^_administration/viz/circles/(.*)?$', dataviz.d3_views.viz_circles, name='viz_circles'),
- re_path(r'^_administration/viz/sankey/(.*)?$', dataviz.d3_views.viz_sankey, name='viz_sankey'),
- re_path(r'^_administration/viz/spiral/(.*)?$', dataviz.d3_views.viz_spiral, name='viz_spiral'),
- re_path(r'^_administration/viz/heatmap/(.*)?$', dataviz.d3_views.viz_heatmap, name='viz_heatmap'),
- re_path(r'^_administration/viz/calendar/(.*)?$', dataviz.d3_views.viz_calendar, name='viz_calendar'),
- re_path(r'^_administration/viz/draggable/(.*)?$', dataviz.d3_views.viz_draggable, name='viz_draggable'),
- re_path(r'^_administration/viz/scatterplot/(.*)?$', dataviz.d3_views.viz_scatterplot, name='viz_scatterplot'),
url(r'^blocknative', perftools.views.blocknative, name='blocknative'),
# quadratic lands
diff --git a/app/assets/v2/images/dataviz/calendar.png b/app/assets/v2/images/dataviz/calendar.png
deleted file mode 100644
index bc21970a5f3..00000000000
Binary files a/app/assets/v2/images/dataviz/calendar.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/chord.png b/app/assets/v2/images/dataviz/chord.png
deleted file mode 100644
index 9cd2bbf0ee2..00000000000
Binary files a/app/assets/v2/images/dataviz/chord.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/circles.png b/app/assets/v2/images/dataviz/circles.png
deleted file mode 100644
index bec8e37f690..00000000000
Binary files a/app/assets/v2/images/dataviz/circles.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/graph.png b/app/assets/v2/images/dataviz/graph.png
deleted file mode 100644
index 8c3983b3b89..00000000000
Binary files a/app/assets/v2/images/dataviz/graph.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/heatmap.png b/app/assets/v2/images/dataviz/heatmap.png
deleted file mode 100644
index 0af7d0a10cc..00000000000
Binary files a/app/assets/v2/images/dataviz/heatmap.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/progression.png b/app/assets/v2/images/dataviz/progression.png
deleted file mode 100644
index 9b28a06e4f1..00000000000
Binary files a/app/assets/v2/images/dataviz/progression.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/sankey.png b/app/assets/v2/images/dataviz/sankey.png
deleted file mode 100644
index 9e109f9b2a0..00000000000
Binary files a/app/assets/v2/images/dataviz/sankey.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/scatterplot.png b/app/assets/v2/images/dataviz/scatterplot.png
deleted file mode 100644
index 95971be6b92..00000000000
Binary files a/app/assets/v2/images/dataviz/scatterplot.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/spiral.png b/app/assets/v2/images/dataviz/spiral.png
deleted file mode 100644
index e9416798973..00000000000
Binary files a/app/assets/v2/images/dataviz/spiral.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/steamgraph.png b/app/assets/v2/images/dataviz/steamgraph.png
deleted file mode 100644
index b669d8e5272..00000000000
Binary files a/app/assets/v2/images/dataviz/steamgraph.png and /dev/null differ
diff --git a/app/assets/v2/images/dataviz/sunburst.png b/app/assets/v2/images/dataviz/sunburst.png
deleted file mode 100644
index 00236125181..00000000000
Binary files a/app/assets/v2/images/dataviz/sunburst.png and /dev/null differ
diff --git a/app/assets/v2/js/dataviz/dragit.css b/app/assets/v2/js/dataviz/dragit.css
deleted file mode 100644
index 739d88be2ff..00000000000
--- a/app/assets/v2/js/dataviz/dragit.css
+++ /dev/null
@@ -1,51 +0,0 @@
-path.lineTrajectory, path.subTrajectory {
- stroke-width: 2;
- stroke-opacity: 0.2;
- opacity: 0.5;
- fill-opacity: 0.3;
- stroke: gray;
- fill: none;
- pointer-events: none;
-}
-
-path.lineTrajectoryMonotone {
- stroke-width: 2;
- fill: none;
- pointer-events: none;
- stroke: lightgray;
-}
-
-circle.pointTrajectory {
- pointer-events: none;
- stroke: lightgray;
- fill: black;
- opacity: .5;
-}
-
-line.lineClosestTrajectory {
- stroke: black;
- stroke-dasharray: 4,4;
- display: block;
-}
-
-line.lineClosestPoint {
- stroke: black;
- opacity: .1;
- display: block;
-}
-
-.selected {
- opacity: .5;
-}
-
-circle.pointClosestTrajectory {
- opacity: .1;
- display: block;
-}
-
-circle.focusGuide {
- opacity: 1;
- display: block;
- fill: none;
- stroke: black;
-}
\ No newline at end of file
diff --git a/app/assets/v2/js/dataviz/dragit.js b/app/assets/v2/js/dataviz/dragit.js
deleted file mode 100644
index a9c5d18791a..00000000000
--- a/app/assets/v2/js/dataviz/dragit.js
+++ /dev/null
@@ -1,692 +0,0 @@
-(function() {
-
- var dragit = window.dragit || {};
-
- window.dragit = dragit;
-
- dragit.version = '0.1.5';
-
- var vars = {
- 'dev': false,
- evt: [],
- tc: [],
- list_closest_datapoint: [],
- svgLine: null,
- container: null,
- accessor_x: function(d) {
- return d[0];
- },
- accessor_y: function(d) {
- return d[1];
- },
- custom_focus: 'default',
- custom_trajectory: 'default',
- playback: {el: null}
- };
-
- dragit.custom = {};
- dragit.trajectory = {};
- dragit.statemachine = {};
- dragit.utils = {};
- dragit.evt = {};
- dragit.mouse = {};
- dragit.time = {};
- dragit.object = {};
- dragit.data = [];
- dragit.constraint = [];
- dragit.playback = {};
-
- dragit.statemachine = {current_state: 'idle', current_id: -1};
-
- dragit.time = {min: 0, max: 0, current: 0, step: 1, previous: 0, offset: 0};
- dragit.mouse = {scope: 'focus'};
- dragit.object = {update: function() {}, offsetX: 0, offsetY: 0, dragging: 'absolute'};
- dragit.evt = {register: function() {}, call: function() {}};
-
- dragit.custom.line = {
- 'default': {'mark': 'svg:path', 'style': {'stroke': 'black', 'stroke-width': 2}, 'interpolate': 'linear'},
- 'monotone': {'mark': 'svg:path', 'style': {'stroke': 'black', 'stroke-width': 2}, 'interpolate': 'monotone'}
- };
-
- dragit.custom.point = {
- 'default': {'mark': 'svg:circle', 'style': {'stroke': 'black', 'stroke-width': 2},
- 'attr': {'cx': vars.accessor_x, 'cy': vars.accessor_y, 'r': 3},
- 'attr_static': {'cx': -10, 'cy': -10, 'r': 3}
- }
- };
-
- dragit.playback = {playing: false, loop: false, interpolation: 'none', speed: 1000};
-
- vars.svgLine = d3.svg.line()
- .x(vars.accessor_x)
- .y(vars.accessor_y)
- .interpolate(dragit.custom.line[vars.custom_trajectory].interpolate);
-
- dragit.evt.register = function(evt, f, d) {
-
- if (vars.dev)
- console.log('[register]', evt);
-
- if (typeof evt == 'string')
- evt = [evt];
-
- evt.forEach(function(e) {
- if (typeof vars.evt[e] == 'undefined')
- vars.evt[e] = [];
-
- vars.evt[e].push([ f, d ]);
- });
- };
-
- dragit.evt.call = function(evt, a) {
-
- if (vars.dev)
- console.log('[call]', evt, a);
-
- if (typeof vars.evt[evt] == 'undefined') {
- if (vars.dev)
- console.warn('No callback for event', evt, a);
- return;
- }
-
- vars.evt[evt].forEach(function(e) {
- if (vars.dev)
- console.log('[calling evt]', e);
- if (typeof (e[0]) != 'undefined')
- e[0](a);
- });
- };
-
- dragit.init = function(container) {
-
- dragit.time.offset = dragit.time.offset ? dragit.time.offset : 0;
- vars.container = d3.select(container);
- };
-
- dragit.trajectory.display = function(d, i, c) {
-
- // Making sure we do not display twice the same trajectory
- if (dragit.statemachine.current_state == 'drag' && dragit.statemachine.current_id == i)
- return;
-
- if (vars.dev)
- console.log('[display]', dragit.statemachine.current_state, dragit.statemachine.current_id, i);
-
- vars.gDragit = vars.container.insert('g', ':first-child')
- .attr('class', 'gDragit');
-
- if (typeof c != 'undefined' && c != 0) {
- vars.gDragit.classed(c, true);
- } else {
- vars.gDragit.classed('focus', true);
- }
-
- dragit.lineTrajectory = vars.gDragit.selectAll('.lineTrajectory')
- .data([dragit.data[i]])
- .enter().append('path')
- .attr('class', 'lineTrajectory')
- .attr('d', vars.svgLine.interpolate(dragit.custom.line[vars.custom_trajectory].interpolate));
-
- dragit.pointTrajectory = vars.gDragit.selectAll('.pointTrajectory')
- .data(dragit.data[i])
- .enter().append(dragit.custom.point[vars.custom_focus].mark)
- .attr('class', 'pointTrajectory')
- .attr(dragit.custom.point[vars.custom_focus].attr);
-
- return dragit.trajectory.displayUpdate(d, i);
- };
-
- dragit.trajectory.displayUpdate = function(d, i) {
-
- dragit.lineTrajectory.data([dragit.data[i]])
- .transition()
- .duration(0)
- .attr('d', vars.svgLine);
-
- dragit.pointTrajectory.data(dragit.data[i])
- .transition()
- .duration(0)
- .attr(dragit.custom.point[vars.custom_focus].attr);
-
- return dragit.lineTrajectory;
- };
-
- dragit.trajectory.toggleAll = function(c) {
- var c = c || '';
- var class_c = '';
-
- if (c.length > 0)
- class_c = '.' + c;
- if (d3.selectAll('.gDragit' + class_c)[0].length > 0)
- dragit.trajectory.removeAll(c);
- else
- dragit.trajectory.displayAll(c);
- };
-
- dragit.trajectory.displayAll = function(c) {
- var c = c || '';
-
- dragit.data.map(function(d, i) {
- dragit.trajectory.display({}, i, c);
- });
- };
-
- dragit.trajectory.remove = function(d, i) {
- if (dragit.statemachine.current_state != 'drag')
- d3.selectAll('.gDragit.focus').remove();
- };
-
- dragit.trajectory.removeAll = function(c) {
- var c = c || 'focus';
-
- d3.selectAll('.gDragit.' + c).remove();
- };
-
- // Main function that binds drag callbacks to the current element
- dragit.object.activate = function(d, i) {
-
- if (vars.dev)
- console.log('[activate]', d, i);
-
-
- d3.select(this)[0][0].node().addEventListener('mouseenter', function() {
- if (dragit.statemachine.current_state == 'idle') {
- dragit.statemachine.setState('mouseenter');
- }
- }, false);
-
- d3.select(this)[0][0].node().addEventListener('mouseleave', function() {
- if (dragit.statemachine.current_state == 'idle')
- dragit.statemachine.setState('mouseleave');
- }, false);
-
- d.call(d3.behavior.drag()
- .on('dragstart', function(d, i) {
-
- d3.event.sourceEvent.stopPropagation();
- dragit.statemachine.setState('dragstart');
-
- if (vars.dev)
- console.log('[dragstart]', d, i);
-
- dragit.trajectory.index_closest_trajectorypoint = -1;
- dragit.trajectory.index_closest_datapoint = -1;
- // Initial coordinates for the dragged object of interest
- d.x = 0;
- d.y = 0;
-
- switch (dragit.mouse.dragging) {
- case 'free':
- case 'horizontal':
- }
-
- var mousepoint = [ d3.mouse(this)[0] + dragit.object.offsetX, d3.mouse(this)[1] + dragit.object.offsetY ];
-
- // Create the line guide to closest trajectory
- dragit.lineClosestTrajectory = vars.gDragit.append('line')
- .attr('class', 'lineClosestTrajectory');
-
- // Create the line guide to closest point
- dragit.lineClosestPoint = vars.gDragit.append('line')
- .attr('class', 'lineClosestPoint');
-
- // Create the point interesting guide line and closest trajectory
- dragit.pointClosestTrajectory = vars.gDragit.append(dragit.custom.point[vars.custom_focus].mark)
- .attr(dragit.custom.point[vars.custom_focus].attr_static)
- .attr('class', 'pointClosestTrajectory')
- .attr('cx', mousepoint[0])
- .attr('cy', mousepoint[1]);
-
- // Create the focus that follows the mouse cursor
- dragit.focusGuide = vars.gDragit.append(dragit.custom.point[vars.custom_focus].mark)
- .attr(dragit.custom.point[vars.custom_focus].attr_static)
- .attr('class', 'focusGuide')
- .attr('cx', mousepoint[0])
- .attr('cy', mousepoint[1]);
-
- dragit.evt.call('dragstart');
-
- })
- .on('drag', function(d, i) {
-
- d3.event.sourceEvent.stopPropagation();
- dragit.time.previous = dragit.time.current;
- dragit.statemachine.setState('drag');
-
- var mousepoint = [ d3.event.x + dragit.object.offsetX, d3.event.y + dragit.object.offsetY ];
-
- if (vars.dev)
- console.log('[drag]', d, i);
-
- switch (dragit.mouse.dragging) {
-
- case 'free':
-
- d3.select(this).attr('transform', function(d, i) {
- return 'translate(' + [ mousepoint[0], mousepoint[1] ] + ')';
- });
-
- dragit.evt.call('drag');
-
- return;
-
- case 'horizontal':
-
- d.x += d3.event.dx;
- d.y = dragit.utils.findYgivenX(d.x, dragit.lineTrajectory);
-
- d3.select(this).attr('transform', function(d, i) {
- return 'translate(' + [ d.x, d.y ] + ')';
- });
-
- return;
-
- }
-
- var list_distances_datapoint = [],
- list_distances_trajectorypoint = [],
- list_times = [];
- var list_closest_trajectorypoint = [],
- list_closest_datapoint = [];
-
- var new_id = -1;
-
- // Browse all the .lineTrajectory trajectories
- // If scope is focus: only current trajectory is inspected
- // If scope is selected: all trajectories are inspected
- d3.selectAll('.' + dragit.mouse.scope).selectAll('.lineTrajectory').forEach(function(e, j) {
-
- var thisTrajectory = d3.select(e[0]);
-
- var current_index = null;
-
- if (dragit.mouse.scope == 'focus') {
- current_index = i;
- } else if (dragit.mouse.scope == 'selected') {
- current_index = j;
- }
-
- var closest_trajectorypoint = dragit.utils.closestPointToTrajectory(thisTrajectory.node(), mousepoint);
-
- var closest_datapoints = dragit.utils.closestDataPoint(mousepoint, dragit.data[current_index]);
-
- var index_closest_time = closest_datapoints.indexOf(Math.min.apply(Math, closest_datapoints));// + dragit.time.min;
-
- // Find the closest data point
- var closest_datapoint = dragit.data[current_index][index_closest_time];
-
- list_closest_trajectorypoint.push(closest_trajectorypoint.concat([current_index]));
- list_closest_datapoint.push(closest_datapoint.concat([current_index]));
-
- // Store all the closest distances between the mouse and the current trajectory point
- // Will be further used to find out the closest index (if scope is broader than 1 trajectory)
- list_distances_datapoint.push(Math.sqrt((closest_datapoint[0] - mousepoint[0]) * (closest_datapoint[0] - mousepoint[0]) + (closest_datapoint[1] - mousepoint[1]) * (closest_datapoint[1] - mousepoint[1])));
- list_distances_trajectorypoint.push(Math.sqrt((closest_trajectorypoint[0] - mousepoint[0]) * (closest_trajectorypoint[0] - mousepoint[0]) + (closest_trajectorypoint[1] - mousepoint[1]) * (closest_trajectorypoint[1] - mousepoint[1])));
-
- // Store the list of all closest times (one per trajectory)
- list_times.push(index_closest_time);
-
- });
-
- // Find the index of the closest trajectory by looking at the shortest distance
- // index_min should be used to retrieve the dragit.data[min_index] data
- var index_closest_datapoint = list_distances_datapoint.indexOf(d3.min(list_distances_datapoint));
- var index_closest_trajectorypoint = list_distances_trajectorypoint.indexOf(d3.min(list_distances_trajectorypoint));
-
- // It can happens the trajectory is not fully displayed yet, then leave because no closest one
- if (index_closest_trajectorypoint == -1)
- return;
-
- var new_time = list_times[index_closest_datapoint];
-
- // Update the line guide to closest trajectory
- dragit.lineClosestTrajectory.attr('x1', list_closest_trajectorypoint[index_closest_trajectorypoint][0])
- .attr('y1', list_closest_trajectorypoint[index_closest_trajectorypoint][1])
- .attr('x2', mousepoint[0])
- .attr('y2', mousepoint[1]);
-
- // Update the point interesting guide line and closest trajectory
- dragit.pointClosestTrajectory.attr('cx', list_closest_trajectorypoint[index_closest_trajectorypoint][0])
- .attr('cy', list_closest_trajectorypoint[index_closest_trajectorypoint][1]);
-
- // Update line guide to closest point
- dragit.lineClosestPoint.attr('x1', list_closest_datapoint[index_closest_datapoint][0])
- .attr('y1', list_closest_datapoint[index_closest_datapoint][1])
- .attr('x2', mousepoint[0])
- .attr('y2', mousepoint[1]);
-
- // Update the focus that follows the mouse cursor
- dragit.focusGuide.attr('cx', mousepoint[0])
- .attr('cy', mousepoint[1]);
-
-
- if (dragit.object.dragging == 'relative') {
- svg.style('cursor', 'none');
- // console.log("relative", list_closest_trajectorypoint[index_closest_trajectorypoint][0])
-
- }
-
- // We have a new time point
- if (dragit.time.current != new_time || dragit.trajectory.current_id != index_closest_trajectorypoint) {
- dragit.trajectory.index_closest_trajectorypoint = index_closest_trajectorypoint;
- dragit.time.current = new_time;
- dragit.evt.call('update', new_time, 0);
- }
-
- // We have a new trajectoy focus
- if (dragit.statemachine.current_id != index_closest_trajectorypoint && dragit.mouse.scope != 'focus') {
- dragit.statemachine.current_id = index_closest_trajectorypoint;
- dragit.evt.call('new_focus', dragit.statemachine.current_id);
- }
-
- dragit.evt.call('drag');
-
- })
- .on('dragend', function(d, i) {
-
- d3.event.sourceEvent.stopPropagation();
- dragit.statemachine.setState('dragend');
-
- if (vars.dev)
- console.log('[dragend]', d, i);
-
- switch (dragit.mouse.dragging) {
-
- case 'free':
-
- d3.select(this).transition()
- .duration(200)
- .attr('transform', function(d, i) {
- return 'translate(' + [ dragit.data[dragit.statemachine.current_id][dragit.time.current][0], dragit.data[dragit.statemachine.current_id][dragit.time.current][1] ] + ')';
- });
- break;
-
- case 'horizontal':
- break;
- }
-
- dragit.lineClosestTrajectory.remove();
- dragit.lineClosestPoint.remove();
- dragit.pointClosestTrajectory.remove();
- dragit.focusGuide.remove();
-
- // Remove the current focus trajectory
- d3.selectAll('.gDragit.focus').remove();
-
- dragit.evt.call('dragend');
-
- dragit.statemachine.setState('idle');
- })
-
- );
- };
-
- dragit.statemachine.setState = function(state) {
-
- if (vars.dev)
- console.log('[setState]', state);
-
- dragit.statemachine.current_state = state;
- dragit.evt.call('new_state');
- };
-
- dragit.statemachine.getState = function(state) {
-
- return dragit.statemachine.current_state;
- };
-
- dragit.playback.play = function() {
-
- if (dragit.playback.playing) {
- setTimeout(function() {
-
- if (!dragit.playback.playing)
- return;
-
- dragit.time.current++;
-
- dragit.evt.call('update', 0, 0);
-
- if (dragit.time.current == dragit.time.max - 1) {
- if (dragit.playback.loop) {
- dragit.time.current = 0;
- dragit.playback.play();
- } else {
- dragit.playback.stop();
- }
- } else
- dragit.playback.play();
-
- }, dragit.playback.speed);
- }
-
- dragit.evt.call('play');
- };
-
- dragit.playback.start = function() {
-
- if (!dragit.playback.playing) {
- dragit.playback.playing = true;
- d3.select(vars.playback.el).select('button').text('| |').attr('class', 'playing');
-
- if (dragit.time.current == dragit.time.max)
- dragit.time.current;
-
- dragit.playback.play();
- }
- };
-
- dragit.playback.stop = function() {
- d3.select(vars.playback.el).select('button').text('▶').attr('class', 'stop');
- dragit.playback.playing = false;
- };
-
- // Create and add a DOM HTML slider for time navigation
- dragit.utils.slider = function(el, play_button) {
- vars.playback.el = el;
- d3.select(el).append('p')
- .style('clear', 'both');
-
- if (play_button) {
- d3.select(el).append('button')
- .style({'height': '25px', 'width': '25px'})
- .text('▶')
- .attr('class', 'stop')
- .on('click', function() {
- if (dragit.playback.playing == false) {
- dragit.playback.start();
- } else {
- dragit.playback.stop();
- }
- });
- }
-
- d3.select(el).append('span')
- .attr('id', 'min-time')
- .text(dragit.time.min);
-
- d3.select(el).append('input')
- .attr('type', 'range')
- .attr('class', 'slider-time')
- .property('min', dragit.time.min)
- .property('max', dragit.time.max)
- // .attr("step", 1)
- .on('input', function() {
- dragit.time.previous = dragit.time.current;
- dragit.time.current = parseInt(this.value) - dragit.time.min;
- dragit.evt.call('update', this.value, 0);
- });
-
- d3.select(el).append('span')
- .attr('id', 'max-time')
- .text(dragit.time.max);
-
- d3.select('.slider-time').property('value', dragit.time.current + dragit.time.min);
-
- dragit.evt.register('drag', function() {
- d3.select('.slider-time').property('value', dragit.time.current);
- });
-
- };
-
- dragit.utils.sliderUpdate = function(el) {
- d3.select(el).select('#max-time')
- .text(dragit.time.max);
-
- d3.select(el).select('.slider-time')
- .property('max', dragit.time.max)
- .property('value', dragit.time.current);
- };
-
- // Calculate the centroid of a given SVG element
- dragit.utils.centroid = function(s) {
- var e = selection.node(),
- bbox = e.getBBox();
-
- return [ bbox.x + bbox.width / 2, bbox.y + bbox.height / 2 ];
- };
-
- // Credits: http://bl.ocks.org/mbostock/8027637
- dragit.utils.closestPointToTrajectory = function(pathNode, point) {
- var pathLength = pathNode.getTotalLength(),
- precision = 8,
- best,
- bestLength,
- bestDistance = Infinity;
-
- // linear scan for coarse approximation
- for (var scan, scanLength = 0, scanDistance; scanLength <= pathLength; scanLength += precision) {
- if ((scanDistance = distance2(scan = pathNode.getPointAtLength(scanLength))) < bestDistance) {
- best = scan, bestLength = scanLength, bestDistance = scanDistance;
- }
- }
-
- // binary search for precise estimate
- precision /= 2;
- while (precision > 0.5) {
- var before,
- after,
- beforeLength,
- afterLength,
- beforeDistance,
- afterDistance;
-
- if ((beforeLength = bestLength - precision) >= 0 && (beforeDistance = distance2(before = pathNode.getPointAtLength(beforeLength))) < bestDistance) {
- best = before, bestLength = beforeLength, bestDistance = beforeDistance;
- } else if ((afterLength = bestLength + precision) <= pathLength && (afterDistance = distance2(after = pathNode.getPointAtLength(afterLength))) < bestDistance) {
- best = after, bestLength = afterLength, bestDistance = afterDistance;
- } else {
- precision /= 2;
- }
- }
-
- best = [ best.x, best.y ];
- best.distance = Math.sqrt(bestDistance);
- return best;
-
- function distance2(p) {
- var dx = p.x - point[0],
- dy = p.y - point[1];
-
- return dx * dx + dy * dy;
- }
- };
-
- dragit.utils.closestDataPoint = function(p, points) {
- var distances = points.map(function(d, i) {
- var dx = d[0] - p[0];
- var dy = d[1] - p[1];
-
- return Math.sqrt(dx * dx + dy * dy);
- });
-
- return distances;
- };
-
- // Code from http://bl.ocks.org/duopixel/3824661
- dragit.utils.findYgivenX = function(x, path) {
- var pathEl = path.node();
- var pathLength = pathEl.getTotalLength();
- var BBox = pathEl.getBBox();
- var scale = pathLength / BBox.width;
- var offsetLeft = document.getElementsByClassName('lineTrajectory')[0].offsetLeft;
-
- x = x - offsetLeft;
-
- var beginning = x,
- end = pathLength,
- target;
-
- while (true) {
- target = Math.floor((beginning + end) / 2);
- pos = pathEl.getPointAtLength(target);
- if ((target === end || target === beginning) && pos.x !== x) {
- break;
- }
- if (pos.x > x)
- end = target;
- else if (pos.x < x)
- beginning = target;
- else
- break;
- }
- return pos.y - 200;
- };
-
- dragit.utils.animateTrajectory = function(path, start_time, duration) {
-
- var totalLength = path.node().getTotalLength();
-
- path.attr('stroke-width', '5')
- .attr('stroke-dasharray', totalLength + ' ' + totalLength)
- .attr('stroke-dashoffset', totalLength)
- .transition()
- .duration(duration)
- .ease('linear')
- .attr('stroke-dashoffset', 0);
- };
-
- // Credits: http://bl.ocks.org/mbostock/1705868
- dragit.utils.translateAlong = function(path, duration) {
- var l = path.node().getTotalLength();
-
- return function(d, i, a) {
- return function(t) {
- var p = path.node().getPointAtLength(t * l);
-
- return 'translate(' + p.x + ',' + p.y + ')';
- };
- };
- };
-
- dragit.utils.getSubPath = function(start_time, end_time) {
-
- sub_data = dragit.data[dragit.statemachine.current_id].filter(function(d, i) {
- return i >= start_time && i <= end_time;
- });
-
- dragit.subTrajectory = vars.gDragit.selectAll('.subTrajectory')
- .data([sub_data])
- .enter().append('path')
- .attr('class', 'subTrajectory')
- .style({'stroke': 'black', 'stroke-width': 4})
- .attr('d', vars.svgLine.interpolate(dragit.custom.line[vars.custom_trajectory].interpolate));
-
- return dragit.subTrajectory;
-
- };
-
-})();
-
-Array.prototype.equals = function(b) {
- var a = this;
- var i = a.length;
-
- if (i != b.length)
- return false;
- while (i--) {
- if (a[i] !== b[i])
- return false;
- }
- return true;
-};
\ No newline at end of file
diff --git a/app/assets/v2/js/dataviz/heatmap.css b/app/assets/v2/js/dataviz/heatmap.css
deleted file mode 100644
index 93444f72158..00000000000
--- a/app/assets/v2/js/dataviz/heatmap.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body{font-size: 14px;}
-.days-hours-heatmap{padding: 20px 0 20px 0;width: 500px;margin: 0 auto;}
-.days-hours-heatmap .calibration{margin-bottom: 15px;width:400px;}
-.days-hours-heatmap .calibration .group{display: inline-block;}
-.days-hours-heatmap .calibration .description{width:108px;}
-.days-hours-heatmap .calibration .description>label:last-child{float:right;}
-.days-hours-heatmap .calibration>.display-control{float:right;}
-.days-hours-heatmap .calibration>.display-control label{vertical-align: top;}
-.days-hours-heatmap .calibration>.display-control input[type='radio']{cursor: pointer;}
-
-.days-hours-heatmap .heatmap .axis path{display: none;}
-.days-hours-heatmap .heatmap .axis line{fill: none;stroke: #000;shape-rendering: crispEdges;}
-.days-hours-heatmap .heatmap .axis text{font-size: 12px}
diff --git a/app/assets/v2/js/dataviz/heatmap.js b/app/assets/v2/js/dataviz/heatmap.js
deleted file mode 100644
index 6dea67de3be..00000000000
--- a/app/assets/v2/js/dataviz/heatmap.js
+++ /dev/null
@@ -1,161 +0,0 @@
-(function() {
- // UI configuration
- var itemSize = 18;
- var cellSize = itemSize - 1;
- var width = 800;
- var height = 800;
- var margin = {top: 20, right: 20, bottom: 20, left: 25};
-
- // formats
- var hourFormat = d3.time.format('%H');
- var dayFormat = d3.time.format('%j');
- var timeFormat = d3.time.format('%Y-%m-%dT%X');
- var monthDayFormat = d3.time.format('%m.%d');
-
- // data vars for rendering
- var dateExtent = null;
- var data = null;
- var dayOffset = 0;
- var colorCalibration = [ '#f6faaa', '#FEE08B', '#FDAE61', '#F46D43', '#D53E4F', '#9E0142' ];
- var dailyValueExtent = {};
-
- // axises and scales
- var axisWidth = 0;
- var axisHeight = itemSize * 24;
- var xAxisScale = d3.time.scale();
- var xAxis = d3.svg.axis()
- .orient('top')
- .ticks(d3.time.days, 3)
- .tickFormat(monthDayFormat);
- var yAxisScale = d3.scale.linear()
- .range([ 0, axisHeight ])
- .domain([ 0, 24 ]);
- var yAxis = d3.svg.axis()
- .orient('left')
- .ticks(5)
- .tickFormat(d3.format('02d'))
- .scale(yAxisScale);
-
- initCalibration();
-
- var svg = d3.select('[role="heatmap"]');
- var heatmap = svg
- .attr('width', width)
- .attr('height', height)
- .append('g')
- .attr('width', width - margin.left - margin.right)
- .attr('height', height - margin.top - margin.bottom)
- .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
- var rect = null;
-
- var url = document.location.href + '?data=1&format=json';
-
- d3.json(url, function(err, data) {
- data = data.data;
- data.forEach(function(valueObj) {
- valueObj['date'] = timeFormat.parse(valueObj['timestamp']);
- var day = valueObj['day'] = monthDayFormat(valueObj['date']);
-
- var dayData = dailyValueExtent[day] = (dailyValueExtent[day] || [ 1000, -1 ]);
- var pmValue = valueObj['value'];
-
- console.log(day, pmValue);
-
- dayData[0] = d3.min([ dayData[0], pmValue ]);
- dayData[1] = d3.max([ dayData[1], pmValue ]);
- });
-
- dateExtent = d3.extent(data, function(d) {
- return d.date;
- });
-
- axisWidth = itemSize * (dayFormat(dateExtent[1]) - dayFormat(dateExtent[0]) + 1);
-
- // render axises
- xAxis.scale(xAxisScale.range([ 0, axisWidth ]).domain([ dateExtent[0], dateExtent[1] ]));
- svg.append('g')
- .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
- .attr('class', 'x axis')
- .call(xAxis)
- .append('text')
- .text('date')
- .attr('transform', 'translate(' + axisWidth + ',-10)');
-
- svg.append('g')
- .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
- .attr('class', 'y axis')
- .call(yAxis)
- .append('text')
- .text('time')
- .attr('transform', 'translate(-10,' + axisHeight + ') rotate(-90)');
-
- // render heatmap rects
- dayOffset = dayFormat(dateExtent[0]);
- rect = heatmap.selectAll('rect')
- .data(data)
- .enter().append('rect')
- .attr('width', cellSize)
- .attr('height', cellSize)
- .attr('x', function(d) {
- return itemSize * (dayFormat(d.date) - dayOffset);
- })
- .attr('y', function(d) {
- return hourFormat(d.date) * itemSize;
- })
- .attr('fill', '#ffffff');
-
- rect.filter(function(d) {
- return d.value > 0;
- })
- .append('title')
- .text(function(d) {
- return monthDayFormat(d.date) + ' ' + d.value;
- });
-
- renderColor();
- });
-
- function initCalibration() {
- d3.select('[role="calibration"] [role="example"]').select('svg')
- .selectAll('rect').data(colorCalibration).enter()
- .append('rect')
- .attr('width', cellSize)
- .attr('height', cellSize)
- .attr('x', function(d, i) {
- return i * itemSize;
- })
- .attr('fill', function(d) {
- return d;
- });
-
- // bind click event
- d3.selectAll('[role="calibration"] [name="displayType"]').on('click', function() {
- renderColor();
- });
- }
-
- function renderColor() {
- var renderByCount = document.getElementsByName('displayType')[0].checked;
-
- rect
- .filter(function(d) {
- return (d.value >= 0);
- })
- .transition()
- .delay(function(d) {
- return (dayFormat(d.date) - dayOffset) * 15;
- })
- .duration(500)
- .attrTween('fill', function(d, i, a) {
- // choose color dynamicly
- var colorIndex = d3.scale.quantize()
- .range([ 0, 1, 2, 3, 4, 5 ])
- .domain((renderByCount ? [ 0, 500 ] : dailyValueExtent[d.day]));
-
- return d3.interpolate(a, colorCalibration[colorIndex(d.value)]);
- });
- }
-
- // extend frame height in `http://bl.ocks.org/`
- d3.select(self.frameElement).style('height', '600px');
-})();
diff --git a/app/assets/v2/js/dataviz/sequences.css b/app/assets/v2/js/dataviz/sequences.css
deleted file mode 100644
index fb6db0d5ead..00000000000
--- a/app/assets/v2/js/dataviz/sequences.css
+++ /dev/null
@@ -1,54 +0,0 @@
-body {
- font-size: 12px;
- font-weight: 400;
- background-color: #fff;
- width: 960px;
- height: 700px;
- margin-top: 10px;
-}
-
-#main {
- float: left;
- width: 750px;
-}
-
-#sidebar {
- float: right;
- width: 100px;
-}
-
-#sequence {
- width: 600px;
- height: 70px;
-}
-
-#legend {
- padding: 10px 0 0 3px;
-}
-
-#sequence text, #legend text {
- font-weight: 600;
- fill: #fff;
-}
-
-#chart {
- position: relative;
-}
-
-#chart path {
- stroke: #fff;
-}
-
-#explanation {
- position: absolute;
- top: 260px;
- left: 305px;
- width: 140px;
- text-align: center;
- color: #666;
- z-index: -1;
-}
-
-#percentage {
- font-size: 2.5em;
-}
diff --git a/app/assets/v2/js/dataviz/sequences.js b/app/assets/v2/js/dataviz/sequences.js
deleted file mode 100644
index ac0c29801ae..00000000000
--- a/app/assets/v2/js/dataviz/sequences.js
+++ /dev/null
@@ -1,332 +0,0 @@
-// Dimensions of sunburst.
-var width = 750;
-var height = 600;
-var radius = Math.min(width, height) / 2;
-
-// Breadcrumb dimensions: width, height, spacing, width of tip/tail.
-var b = {
- w: 75, h: 30, s: 3, t: 10
-};
-
-
-// Total size of all segments; we set this later, after loading the data.
-var totalSize = 0;
-
-var vis = d3.select('#chart').append('svg:svg')
- .attr('width', width)
- .attr('height', height)
- .append('svg:g')
- .attr('id', 'container')
- .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
-
-var partition = d3.layout.partition()
- .size([ 2 * Math.PI, radius * radius ])
- .value(function(d) {
- return d.size;
- });
-
-var arc = d3.svg.arc()
- .startAngle(function(d) {
- return d.x;
- })
- .endAngle(function(d) {
- return d.x + d.dx;
- })
- .innerRadius(function(d) {
- return Math.sqrt(d.y);
- })
- .outerRadius(function(d) {
- return Math.sqrt(d.y + d.dy);
- });
-
-// Use d3.text and d3.csv.parseRows so that we do not need to have a header
-// row, and can receive the csv as an array of arrays.
-d3.text(document.location.href + '?data=1', function(text) {
- var csv = d3.csv.parseRows(text);
- var json = buildHierarchy(csv);
-
- createVisualization(json);
-});
-
-// Main function to draw and set up the visualization, once we have the data.
-function createVisualization(json) {
-
- // Basic setup of page elements.
- initializeBreadcrumbTrail();
- drawLegend();
- d3.select('#togglelegend').on('click', toggleLegend);
-
- // Bounding circle underneath the sunburst, to make it easier to detect
- // when the mouse leaves the parent g.
- vis.append('svg:circle')
- .attr('r', radius)
- .style('opacity', 0);
-
- // For efficiency, filter nodes to keep only those large enough to see.
- var nodes = partition.nodes(json)
- .filter(function(d) {
- return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
- });
-
- var path = vis.data([json]).selectAll('path')
- .data(nodes)
- .enter().append('svg:path')
- .attr('display', function(d) {
- return d.depth ? null : 'none';
- })
- .attr('d', arc)
- .attr('fill-rule', 'evenodd')
- .style('fill', function(d) {
- return colors[d.name];
- })
- .style('opacity', 1)
- .on('mouseover', mouseover);
-
- // Add the mouseleave handler to the bounding circle.
- d3.select('#container').on('mouseleave', mouseleave);
-
- // Get total size of the tree = value of root node from partition.
- totalSize = path.node().__data__.value;
-}
-
-// Fade all but the current sequence, and show it in the breadcrumb trail.
-function mouseover(d) {
-
- var percentage = (100 * d.value / totalSize).toPrecision(3);
- var percentageString = percentage + '%';
-
- if (percentage < 0.1) {
- percentageString = '< 0.1%';
- }
-
- d3.select('#percentage')
- .text(percentageString);
-
- d3.select('#explanation')
- .style('visibility', '');
-
- var sequenceArray = getAncestors(d);
-
- updateBreadcrumbs(sequenceArray, percentageString);
-
- // Fade all the segments.
- d3.selectAll('path')
- .style('opacity', 0.3);
-
- // Then highlight only those that are an ancestor of the current segment.
- vis.selectAll('path')
- .filter(function(node) {
- return (sequenceArray.indexOf(node) >= 0);
- })
- .style('opacity', 1);
-}
-
-// Restore everything to full opacity when moving off the visualization.
-function mouseleave(d) {
-
- // Hide the breadcrumb trail
- d3.select('#trail')
- .style('visibility', 'hidden');
-
- // Deactivate all segments during transition.
- d3.selectAll('path').on('mouseover', null);
-
- // Transition each segment to full opacity and then reactivate it.
- d3.selectAll('path')
- .transition()
- .duration(1000)
- .style('opacity', 1)
- .each('end', function() {
- d3.select(this).on('mouseover', mouseover);
- });
-
- d3.select('#explanation')
- .style('visibility', 'hidden');
-}
-
-// Given a node in a partition layout, return an array of all of its ancestor
-// nodes, highest first, but excluding the root.
-function getAncestors(node) {
- var path = [];
- var current = node;
-
- while (current.parent) {
- path.unshift(current);
- current = current.parent;
- }
- return path;
-}
-
-function initializeBreadcrumbTrail() {
- // Add the svg area.
- var trail = d3.select('#sequence').append('svg:svg')
- .attr('width', width)
- .attr('height', 50)
- .attr('id', 'trail');
- // Add the label at the end, for the percentage.
-
- trail.append('svg:text')
- .attr('id', 'endlabel')
- .style('fill', '#000');
-}
-
-// Generate a string that describes the points of a breadcrumb polygon.
-function breadcrumbPoints(d, i) {
- var points = [];
-
- points.push('0,0');
- points.push(b.w + ',0');
- points.push(b.w + b.t + ',' + (b.h / 2));
- points.push(b.w + ',' + b.h);
- points.push('0,' + b.h);
- if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
- points.push(b.t + ',' + (b.h / 2));
- }
- return points.join(' ');
-}
-
-// Update the breadcrumb trail to show the current sequence and percentage.
-function updateBreadcrumbs(nodeArray, percentageString) {
-
- // Data join; key function combines name and depth (= position in sequence).
- var g = d3.select('#trail')
- .selectAll('g')
- .data(nodeArray, function(d) {
- return d.name + d.depth;
- });
-
- // Add breadcrumb and label for entering nodes.
- var entering = g.enter().append('svg:g');
-
- entering.append('svg:polygon')
- .attr('points', breadcrumbPoints)
- .style('fill', function(d) {
- return colors[d.name];
- });
-
- entering.append('svg:text')
- .attr('x', (b.w + b.t) / 2)
- .attr('y', b.h / 2)
- .attr('dy', '0.35em')
- .attr('text-anchor', 'middle')
- .text(function(d) {
- return d.name;
- });
-
- // Set position for entering and updating nodes.
- g.attr('transform', function(d, i) {
- return 'translate(' + i * (b.w + b.s) + ', 0)';
- });
-
- // Remove exiting nodes.
- g.exit().remove();
-
- // Now move and update the percentage at the end.
- d3.select('#trail').select('#endlabel')
- .attr('x', (nodeArray.length + 0.5) * (b.w + b.s))
- .attr('y', b.h / 2)
- .attr('dy', '0.35em')
- .attr('text-anchor', 'middle')
- .text(percentageString);
-
- // Make the breadcrumb trail visible, if it's hidden.
- d3.select('#trail')
- .style('visibility', '');
-
-}
-
-function drawLegend() {
-
- // Dimensions of legend item: width, height, spacing, radius of rounded rect.
- var li = {
- w: 75, h: 30, s: 3, r: 3
- };
-
- var legend = d3.select('#legend').append('svg:svg')
- .attr('width', li.w)
- .attr('height', d3.keys(colors).length * (li.h + li.s));
-
- var g = legend.selectAll('g')
- .data(d3.entries(colors))
- .enter().append('svg:g')
- .attr('transform', function(d, i) {
- return 'translate(0,' + i * (li.h + li.s) + ')';
- });
-
- g.append('svg:rect')
- .attr('rx', li.r)
- .attr('ry', li.r)
- .attr('width', li.w)
- .attr('height', li.h)
- .style('fill', function(d) {
- return d.value;
- });
-
- g.append('svg:text')
- .attr('x', li.w / 2)
- .attr('y', li.h / 2)
- .attr('dy', '0.35em')
- .attr('text-anchor', 'middle')
- .text(function(d) {
- return d.key;
- });
-}
-
-function toggleLegend() {
- var legend = d3.select('#legend');
-
- if (legend.style('visibility') == 'hidden') {
- legend.style('visibility', '');
- } else {
- legend.style('visibility', 'hidden');
- }
-}
-
-// Take a 2-column CSV and transform it into a hierarchical structure suitable
-// for a partition layout. The first column is a sequence of step names, from
-// root to leaf, separated by hyphens. The second column is a count of how
-// often that sequence occurred.
-function buildHierarchy(csv) {
- var root = {'name': 'root', 'children': []};
-
- for (var i = 0; i < csv.length; i++) {
- var sequence = csv[i][0];
- var size = +csv[i][1];
-
- if (isNaN(size)) { // e.g. if this is a header row
- continue;
- }
- var parts = sequence.split('-');
- var currentNode = root;
-
- for (var j = 0; j < parts.length; j++) {
- var children = currentNode['children'];
- var nodeName = parts[j];
- var childNode;
-
- if (j + 1 < parts.length) {
- // Not yet at the end of the sequence; move down the tree.
- var foundChild = false;
-
- for (var k = 0; k < children.length; k++) {
- if (children[k]['name'] == nodeName) {
- childNode = children[k];
- foundChild = true;
- break;
- }
- }
- // If we don't already have a child node for this branch, create it.
- if (!foundChild) {
- childNode = {'name': nodeName, 'children': []};
- children.push(childNode);
- }
- currentNode = childNode;
- } else {
- // Reached the end of the sequence; create a leaf node.
- childNode = {'name': nodeName, 'size': size};
- children.push(childNode);
- }
- }
- }
- return root;
-}
diff --git a/app/assets/v2/js/dataviz/spiral.js b/app/assets/v2/js/dataviz/spiral.js
deleted file mode 100644
index 23096d28b93..00000000000
--- a/app/assets/v2/js/dataviz/spiral.js
+++ /dev/null
@@ -1,164 +0,0 @@
-var width = 800;
-var height = 800;
-var start = 0;
-var end = 2.25;
-var numSpirals = 3;
-
-margin = {top: 50, bottom: 50, left: 50, right: 50};
-
-var theta = function(r) {
- return numSpirals * Math.PI * r;
-};
-
- // used to assign nodes color by group
-var color = d3.scaleOrdinal(d3.schemeCategory10);
-
-var r = d3.min([ width, height ]) / 2 - 40;
-
-var radius = d3.scaleLinear()
- .domain([ start, end ])
- .range([ 40, r ]);
-
-var svg = d3.select('#chart').append('svg')
- .attr('width', width + margin.right + margin.left)
- .attr('height', height + margin.left + margin.right)
- .append('g')
- .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
-
-var points = d3.range(start, end + 0.001, (end - start) / 1000);
-
-var spiral = d3.radialLine()
- .curve(d3.curveCardinal)
- .angle(theta)
- .radius(radius);
-
-var path = svg.append('path')
- .datum(points)
- .attr('id', 'spiral')
- .attr('d', spiral)
- .style('fill', 'none')
- .style('stroke', 'steelblue');
-
-var spiralLength = path.node().getTotalLength();
-var N = 365;
-var barWidth = (spiralLength / N) - 1;
-
-var timeScale = d3.scaleTime()
- .domain(d3.extent(someData, function(d) {
- return d.date;
- }))
- .range([ 0, spiralLength ]);
-
- // yScale for the bar height
-var yScale = d3.scaleLinear()
- .domain([ 0, d3.max(someData, function(d) {
- return d.value;
- }) ])
- .range([ 0, (r / numSpirals) - 30 ]);
-
-svg.selectAll('rect')
- .data(someData)
- .enter()
- .append('rect')
- .attr('x', function(d, i) {
-
- var linePer = timeScale(d.date);
- var posOnLine = path.node().getPointAtLength(linePer);
- var angleOnLine = path.node().getPointAtLength(linePer - barWidth);
-
- d.linePer = linePer; // % distance are on the spiral
- d.x = posOnLine.x; // x postion on the spiral
- d.y = posOnLine.y; // y position on the spiral
-
- d.a = (Math.atan2(angleOnLine.y, angleOnLine.x) * 180 / Math.PI) - 90; // angle at the spiral position
-
- return d.x;
- })
- .attr('y', function(d) {
- return d.y;
- })
- .attr('width', function(d) {
- return barWidth;
- })
- .attr('height', function(d) {
- return yScale(d.value);
- })
- .style('fill', function(d) {
- return color(d.group);
- })
- .style('stroke', 'none')
- .attr('transform', function(d) {
- return 'rotate(' + d.a + ',' + d.x + ',' + d.y + ')'; // rotate the bar
- });
-
-// add date labels
-var tF = d3.timeFormat('%b %Y');
-var firstInMonth = {};
-
-svg.selectAll('text')
- .data(someData)
- .enter()
- .append('text')
- .attr('dy', 10)
- .style('text-anchor', 'start')
- .style('font', '10px arial')
- .append('textPath')
-// only add for the first of each month
- .filter(function(d) {
- var sd = tF(d.date);
-
- if (!firstInMonth[sd]) {
- firstInMonth[sd] = 1;
- return true;
- }
- return false;
- })
- .text(function(d) {
- return tF(d.date);
- })
-// place text along spiral
- .attr('xlink:href', '#spiral')
- .style('fill', 'grey')
- .attr('startOffset', function(d) {
- return ((d.linePer / spiralLength) * 100) + '%';
- });
-
-
-var tooltip = d3.select('#chart')
- .append('div')
- .attr('class', 'tooltip');
-
-tooltip.append('div')
- .attr('class', 'date');
-tooltip.append('div')
- .attr('class', 'value');
-
-svg.selectAll('rect')
- .on('mouseover', function(d) {
-
- tooltip.select('.date').html('Date: ' + d.date.toDateString() + '');
- tooltip.select('.value').html('Value: ' + Math.round(d.value * 100) / 100 + '');
-
- d3.select(this)
- .style('fill', '#FFFFFF')
- .style('stroke', '#000000')
- .style('stroke-width', '2px');
-
- tooltip.style('display', 'block');
- tooltip.style('opacity', 2);
-
- })
- .on('mousemove', function(d) {
- tooltip.style('top', (d3.event.layerY + 10) + 'px')
- .style('left', (d3.event.layerX - 25) + 'px');
- })
- .on('mouseout', function(d) {
- d3.selectAll('rect')
- .style('fill', function(d) {
- return color(d.group);
- })
- .style('stroke', 'none');
-
- tooltip.style('display', 'none');
- tooltip.style('opacity', 0);
- });
diff --git a/app/assets/v2/scss/dataviz/sequences.scss b/app/assets/v2/scss/dataviz/sequences.scss
deleted file mode 100644
index fb6db0d5ead..00000000000
--- a/app/assets/v2/scss/dataviz/sequences.scss
+++ /dev/null
@@ -1,54 +0,0 @@
-body {
- font-size: 12px;
- font-weight: 400;
- background-color: #fff;
- width: 960px;
- height: 700px;
- margin-top: 10px;
-}
-
-#main {
- float: left;
- width: 750px;
-}
-
-#sidebar {
- float: right;
- width: 100px;
-}
-
-#sequence {
- width: 600px;
- height: 70px;
-}
-
-#legend {
- padding: 10px 0 0 3px;
-}
-
-#sequence text, #legend text {
- font-weight: 600;
- fill: #fff;
-}
-
-#chart {
- position: relative;
-}
-
-#chart path {
- stroke: #fff;
-}
-
-#explanation {
- position: absolute;
- top: 260px;
- left: 305px;
- width: 140px;
- text-align: center;
- color: #666;
- z-index: -1;
-}
-
-#percentage {
- font-size: 2.5em;
-}
diff --git a/app/dataviz/d3_views.py b/app/dataviz/d3_views.py
index 0d73783bd0a..af15e7d23d9 100644
--- a/app/dataviz/d3_views.py
+++ b/app/dataviz/d3_views.py
@@ -111,197 +111,6 @@ def data_viz_helper_get_data_responses(request, visual_type):
return data_dict
-
-@staff_member_required
-def viz_spiral(request, key='email_open'):
- """Render a spiral graph visualization.
-
- Args:
- key (str): The key type to visualize.
-
- Returns:
- TemplateResponse: The populated spiral data visualization template.
-
- """
- stats = Stat.objects.filter(created_on__hour=1)
- type_options = stats.distinct('key').values_list('key', flat=True)
- stats = stats.filter(key=key).order_by('created_on')
- params = {'stats': stats, 'key': key, 'page_route': 'spiral', 'type_options': type_options, 'viz_type': key, }
- return TemplateResponse(request, 'dataviz/spiral.html', params)
-
-
-@staff_member_required
-def viz_chord(request, key='bounties_paid'):
- """Render a chord graph visualization.
-
- Args:
- key (str): The key type to visualize.
-
- Returns:
- TemplateResponse: The populated chord data visualization template.
-
- """
- type_options = ['bounties_paid']
-
- if request.GET.get('data'):
- rows = [['creditor', 'debtor', 'amount', 'risk']]
- network = 'mainnet'
- for bounty in Bounty.objects.current().filter(network=network, web3_type='bounties_network', idx_status='done'):
- weight = bounty.value_in_usdt_then
- if weight:
- for fulfillment in bounty.fulfillments.filter(accepted=True):
- length = (fulfillment.created_on - bounty.web3_created).seconds
- target = fulfillment.fulfiller_github_username.lower()
- source = bounty.bounty_owner_github_username.lower()
- if source and target:
- rows.append((helper_hide_pii(source), helper_hide_pii(target), str(weight), str(length)))
-
- output_rows = []
- for row in rows:
- row = ",".join(row)
- output_rows.append(row)
-
- output = "\n".join(output_rows)
- return HttpResponse(output)
-
- params = {'key': key, 'page_route': 'spiral', 'type_options': type_options, 'viz_type': key, }
- return TemplateResponse(request, 'dataviz/chord.html', params)
-
-
-@staff_member_required
-def viz_steamgraph(request, key='open'):
- """Render a steamgraph graph visualization.
-
- Args:
- key (str): The key type to visualize.
-
- Returns:
- TemplateResponse: The populated steamgraph data visualization template.
-
- """
- type_options = Bounty.objects.all().distinct('idx_status').values_list('idx_status', flat=True)
- if key not in type_options:
- key = type_options[0]
-
- if request.GET.get('data'):
- rows = [['key', 'value', 'date']]
- network = 'mainnet'
- bounties = Bounty.objects.filter(network=network, web3_type='bounties_network', idx_status=key)
- org_names = set([bounty.org_name for bounty in bounties])
- #start_date = bounties.order_by('web3_created').first().web3_created
- start_date = timezone.now() - timezone.timedelta(days=30)
- end_date = timezone.now()
- current_date = start_date
- while current_date < end_date:
- next_date = current_date + timezone.timedelta(days=1)
- for org_name in org_names:
- if org_name:
- _bounties = bounties.filter(github_url__contains=org_name)
- weight = round(
- sum(
- bounty.value_in_usdt_then for bounty in _bounties
- if bounty.value_in_usdt_then and bounty.was_active_at(current_date)
- ), 2
- )
- output_date = current_date.strftime(('%m/%d/%y'))
- rows.append([org_name, str(weight), output_date])
- current_date = next_date
-
- output_rows = []
- for row in rows:
- row = ",".join(row)
- output_rows.append(row)
-
- output = "\n".join(output_rows)
- return HttpResponse(output)
-
- params = {'key': key, 'page_route': 'steamgraph', 'type_options': type_options, 'viz_type': key, }
- return TemplateResponse(request, 'dataviz/steamgraph.html', params)
-
-
-@staff_member_required
-def viz_calendar(request, key='email_open', template='calendar'):
- return viz_heatmap(request, key, template)
-
-
-@staff_member_required
-def viz_heatmap(request, key='email_open', template='heatmap'):
- """Render a heatmap graph visualization.
-
- Args:
- key (str): The key type to visualize.
-
- Returns:
- JsonResponse: If data param provided, return a JSON representation of data to be graphed.
- TemplateResponse: If data param not provided, return the populated data visualization template.
-
- """
- time_now = timezone.now()
- stats = Stat.objects.filter(created_on__lt=time_now, )
- if template == 'calendar':
- stats = stats.filter(created_on__hour=1)
- else:
- stats = stats.filter(created_on__gt=(time_now - timezone.timedelta(weeks=2)))
-
- type_options = stats.distinct('key').values_list('key', flat=True)
- stats = stats.filter(key=key).order_by('-created_on')
-
- if request.GET and request.GET.get('data'):
- if request.GET.get('format', '') == 'json':
- _max = max([stat.val_since_hour for stat in stats])
- output = {
- # {"timestamp": "2014-10-16T22:00:00", "value": {"PM2.5": 61.92}}
- "data": [{
- 'timestamp': stat.created_on.strftime("%Y-%m-%dT%H:00:00"),
- 'value': stat.val_since_hour * 800.0 / _max,
- } for stat in stats]
- }
- # Example output: https://gist.github.com/mbeacom/44f0114666d69bb5bf2756216c43b64d
- return JsonResponse(output)
- #csv
- rows = [['Date', 'Value']]
- _max = max([stat.val_since_yesterday for stat in stats])
- for stat in stats:
- date = stat.created_on.strftime("%Y-%m-%d")
- value = str(stat.val_since_yesterday / _max) if _max else str(0)
- rows.append([date, value])
- output_rows = []
- for row in rows:
- row = ",".join(row)
- output_rows.append(row)
-
- output = "\n".join(output_rows)
- return HttpResponse(output)
- params = {'stats': stats, 'key': key, 'page_route': template, 'type_options': type_options, 'viz_type': key, }
- return TemplateResponse(request, f'dataviz/{template}.html', params)
-
-
-@staff_member_required
-def viz_index(request):
- """Render the visualization index.
-
- Returns:
- TemplateResponse: The visualization index template response.
-
- """
- return TemplateResponse(request, 'dataviz/index.html', {})
-
-
-@staff_member_required
-def viz_circles(request, visual_type):
- """Render a circle graph visualization.
-
- Args:
- visual_type (str): The visualization type.
-
- Returns:
- JsonResponse: If data param provided, return a JSON representation of data to be graphed.
- TemplateResponse: If data param not provided, return the populated data visualization template.
-
- """
- return viz_sunburst(request, visual_type, 'circles')
-
-
def data_viz_helper_merge_json_trees(output):
"""Handle merging the visualization data trees.
@@ -362,92 +171,6 @@ def data_viz_helper_get_json_output(key, value, depth=0):
return result
-@staff_member_required
-def viz_sunburst(request, visual_type, template='sunburst'):
- """Render a sunburst graph visualization.
-
- Args:
- visual_type (str): The visualization type.
- template (str): The template type to be used. Defaults to: sunburst.
-
- TODO:
- * Reduce the number of local variables in this method from 18 to 15.
-
- Returns:
- JsonResponse: If data param provided, return a JSON representation of data to be graphed.
- TemplateResponse: If data param not provided, return the populated data visualization template.
-
- """
- visual_type_options = ['status_progression', 'repos', 'fulfillers', 'funders', ]
- if visual_type not in visual_type_options:
- visual_type = visual_type_options[0]
-
- if visual_type == 'status_progression':
- title = "Status Progression Viz"
- comment = 'of statuses begin with this sequence of status'
- categories = list(Bounty.objects.distinct('idx_status').values_list('idx_status', flat=True)) + ['_']
- elif visual_type == 'repos':
- title = "Github Structure of All Bounties"
- comment = 'of bounties value with this github structure'
- categories = [
- bounty.org_name.replace('-', '') for bounty in Bounty.objects.filter(network='mainnet') if bounty.org_name
- ]
- categories += [
- bounty.github_repo_name.replace('-', '') for bounty in Bounty.objects.filter(network='mainnet')
- if bounty.github_repo_name
- ]
- categories += [str(bounty.github_issue_number) for bounty in Bounty.objects.filter(network='mainnet')]
- elif visual_type == 'fulfillers':
- title = "Fulfillers"
- comment = 'of bounties value with this fulfiller'
- categories = []
- for bounty in Bounty.objects.filter(network='mainnet'):
- for fulfiller in bounty.fulfillments.all():
- categories.append(fulfiller.fulfiller_github_username.replace('-', ''))
- elif visual_type == 'funders':
- title = "Funders"
- comment = 'of bounties value with this funder'
- categories = []
- for bounty in Bounty.objects.filter(network='mainnet'):
- categories.append(bounty.bounty_owner_github_username.replace('-', ''))
-
- if request.GET.get('data'):
- data_dict = data_viz_helper_get_data_responses(request, visual_type)
-
- _format = request.GET.get('format', 'csv')
- if _format == 'csv':
- rows = []
- for key, value in data_dict.items():
- row = ",".join([key, str(value)])
- rows.append(row)
-
- output = "\n".join(rows)
- return HttpResponse(output)
-
- if _format == 'json':
- output = {'name': 'data', 'children': []}
- for key, val in data_dict.items():
- if val:
- output['children'].append(data_viz_helper_get_json_output(key, val))
- output = data_viz_helper_merge_json_trees(output)
- return JsonResponse(output)
-
- params = {
- 'title': title,
- 'comment': comment,
- 'viz_type': visual_type,
- 'page_route': template,
- 'type_options': visual_type_options,
- 'categories': json.dumps(list(categories)),
- }
- return TemplateResponse(request, f'dataviz/{template}.html', params)
-
-
-@staff_member_required
-def viz_sankey(request, _type, template='square_graph'):
- return viz_graph(request, _type, template)
-
-
def helper_hide_pii(username, num_chars=3):
if not username:
return None
@@ -516,74 +239,10 @@ def viz_graph(request, _type, template='graph'):
return response
-@staff_member_required
-def viz_draggable(request, key='email_open'):
- """Render a draggable graph visualization.
-
- Args:
- key (str): The key type to visualize.
-
- Returns:
- TemplateResponse: The populated draggable data visualization template.
-
- """
- stats = []
- type_options = []
- bfs = BountyFulfillment.objects.filter(accepted=True)
- limit = 50
- usernames = list(
- bfs.exclude(profile__handle='').distinct('profile__handle').values_list('profile__handle', flat=True)
- )[0:limit]
- if request.GET.get('data'):
- output = []
- for username in usernames:
- these_bounties = bfs.filter(profile__handle=username)
- start_date = timezone.now() - timezone.timedelta(days=180)
- income = []
- lifeExpectancy = []
- population = []
- val_usdt = 0
- for i in range(1, 180):
- current_date = start_date + timezone.timedelta(days=i)
- prev_date = start_date + timezone.timedelta(days=(i - 1))
- these_bounties_before_date = these_bounties.filter(created_on__lt=current_date)
- these_bounties_in_range = these_bounties.filter(created_on__lt=current_date, created_on__gt=prev_date)
- val_usdt += sum(bf.bounty.value_in_usdt for bf in these_bounties_in_range if bf.bounty.value_in_usdt)
- num_bounties = these_bounties_before_date.distinct('bounty').count()
- income.append([i, val_usdt]) # x axis
- lifeExpectancy.append([i, num_bounties]) # y axis
- population.append([i, 10000000 * num_bounties]) # size
- #print(username, i, num_bounties, val_usdt)
- output.append({
- 'name': username,
- 'region': username,
- 'income': income,
- 'population': population,
- 'lifeExpectancy': lifeExpectancy,
- })
-
- return JsonResponse(output, safe=False)
-
- params = {
- 'stats': stats,
- 'key': key,
- 'usernames': json.dumps(usernames),
- 'page_route': 'draggable',
- 'type_options': type_options,
- 'viz_type': key,
- }
- return TemplateResponse(request, 'dataviz/draggable.html', params)
-
-
def viz_scatterplot_stripped(request, key='hourly_rate'):
return viz_scatterplot_helper(request, 'hourly_rate', 'dataviz/scatterplot_stripped.html', True)
-@staff_member_required
-def viz_scatterplot(request, key='hourly_rate', template='dataviz/scatterplot.html', hide_usernames=False):
- return viz_scatterplot_helper(request, key, template, hide_usernames)
-
-
def is_an_edge(handle, edges):
for edge in edges:
if handle == edge[0]:
diff --git a/app/dataviz/templates/dataviz/calendar.html b/app/dataviz/templates/dataviz/calendar.html
deleted file mode 100644
index 7d331685b06..00000000000
--- a/app/dataviz/templates/dataviz/calendar.html
+++ /dev/null
@@ -1,86 +0,0 @@
-{% load i18n static bundle %}
-
-
-< back
-{% bundle merge_js file jquery %}
-
-{% endbundle %}
-{% include "dataviz/shared/nav.html" %}
-
-
-
diff --git a/app/dataviz/templates/dataviz/chord.html b/app/dataviz/templates/dataviz/chord.html
deleted file mode 100644
index ec7537cc61c..00000000000
--- a/app/dataviz/templates/dataviz/chord.html
+++ /dev/null
@@ -1,170 +0,0 @@
-{% load i18n static bundle %}
-
-
-
-
-
-< back
-
- payers (top) / payees (top)
-
The redder the node is the longer it took the bounty hunter to turn around.
- -{% bundle merge_js file jquery %} - -{% endbundle %} - diff --git a/app/dataviz/templates/dataviz/circles.html b/app/dataviz/templates/dataviz/circles.html deleted file mode 100644 index 3cd1d726fbd..00000000000 --- a/app/dataviz/templates/dataviz/circles.html +++ /dev/null @@ -1,144 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load humanize i18n static bundle %} -{% comment %} - Copyright (C) 2021 Gitcoin Core - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see- Days ^^ -
- - - - diff --git a/app/dataviz/templates/dataviz/heatmap.html b/app/dataviz/templates/dataviz/heatmap.html deleted file mode 100644 index f306e088b9d..00000000000 --- a/app/dataviz/templates/dataviz/heatmap.html +++ /dev/null @@ -1,127 +0,0 @@ -{% extends "admin/base_site.html" %} -{% load humanize i18n static bundle %} -{% comment %} - Copyright (C) 2021 Gitcoin Core - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see- Repo - | -- NumBounties - | -- Hourly Rate - | -- Standard Deviation - | -
-
-
-
-
-
-
diff --git a/app/dataviz/templates/dataviz/steamgraph.html b/app/dataviz/templates/dataviz/steamgraph.html
deleted file mode 100644
index 03f5ae966e3..00000000000
--- a/app/dataviz/templates/dataviz/steamgraph.html
+++ /dev/null
@@ -1,267 +0,0 @@
-{% extends "admin/base_site.html" %}
-{% load humanize bundle %}
-{% comment %}
- Copyright (C) 2021 Gitcoin Core
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see