//= require d3 //= require c3 //= require c3ext // TODO: This module is complex enough to require its own tests. Rewrite it using Ecma6 class syntax and // write tests for this feature after consul has been migrated to Rails 5.1 (function() { "use strict"; var ProposalGraph = function(url) { this.url = url; this.successfulProposalDataUrl = null; this.proposalAchievementsUrl = null; this.targetId = null; this.groupBy = null; this.proposalSuccess = null; this.maximumValue = 0; this.progressLabel = "Progress"; this.supportsLabel = "Supports"; this.successLabel = "Success"; this.goals = null; this.achievements = null; this.xColumnValues = null; this.progressColumnValues = null; this.resourcesUrl = null; }; ProposalGraph.prototype.refresh = function() { this.refreshGoals() .then(this.refreshData.bind(this)) .then(this.refreshSuccessfulData.bind(this)) .then(this.refreshAchievements.bind(this)) .done(this.draw.bind(this)); }; ProposalGraph.prototype.refreshGoals = function() { return $.ajax({ url: this.resourcesUrl, cache: false, success: function(data) { this.parseGoals(data); }.bind(this) }); }; ProposalGraph.prototype.parseGoals = function(data) { this.goals = data.map(function(item) { return { value: item.required_supports, text: item.title }; }); }; ProposalGraph.prototype.refreshData = function() { return $.ajax({ url: this.url, cache: false, success: function(data) { this.parseData(data); }.bind(this), data: { group_by: this.groupBy } }); }; ProposalGraph.prototype.parseData = function(data) { var key; this.xColumnValues = []; this.progressColumnValues = [this.progressLabel]; for (key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { this.xColumnValues.push(key); this.progressColumnValues.push(data[key]); if (this.maximumValue < data[key]) { this.maximumValue = data[key]; } } } }; ProposalGraph.prototype.refreshSuccessfulData = function() { return $.ajax({ url: this.successfulProposalDataUrl, cache: false, success: function(data) { this.parseSuccessfulProposalData(data); }.bind(this), data: { group_by: this.groupBy } }); }; ProposalGraph.prototype.parseSuccessfulProposalData = function(data) { var key; this.successfulColumnValues = [this.successLabel]; for (key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { this.addXColumnValue(key); this.successfulColumnValues.push(data[key]); } } }; ProposalGraph.prototype.refreshAchievements = function() { return $.ajax({ url: this.proposalAchievementsUrl, cache: false, success: function(data) { this.parseAchievements(data); }.bind(this), data: { group_by: this.groupBy } }); }; ProposalGraph.prototype.parseAchievements = function(data) { var group; this.achievements = []; for (group in data) { if (Object.prototype.hasOwnProperty.call(data, group)) { this.addXColumnValue(group); this.achievements.push({ value: this.formatGroup(group), text: data[group].title, position: "start" }); } } }; ProposalGraph.prototype.addXColumnValue = function(value) { if (this.xColumnValues.indexOf(value) === -1) { this.xColumnValues.push(value); } }; ProposalGraph.prototype.draw = function() { var colors = {}, maximumValue = this.maximumValue === 0 ? this.proposalSuccess : Math.round(this.maximumValue * 1.10); this.formatXColumnValues(); colors[this.progressColumnValues[0]] = "#004a83"; colors[this.successfulColumnValues[0]] = "#ff7f0e"; c3.generate({ bindto: "#" + this.targetId, data: { x: "x", columns: [ this.xColumnValues, this.progressColumnValues, this.successfulColumnValues ], colors: colors, color: function(color, d) { var achievement; if (d.id === this.successfulColumnValues[0] || !Object.prototype.hasOwnProperty.call(d, "x")) { return color; } achievement = this.achievements.find(function(element) { return element.value === this.xColumnValues[d.index + 1]; }.bind(this)); if (achievement !== undefined) { return "#ff0000"; } return color; }.bind(this) }, axis: { y: { tick: { values: this.tickYValues() }, min: (this.maximumValue === 0 ? Math.round(this.proposalSuccess * 0.10) : 0), max: maximumValue, label: { text: this.supportsLabel, position: "outer-middle" } }, x: { type: "category", tick: { values: this.tickXValues(), centered: true } } }, grid: { y: { lines: this.goals } }, zoom: { enabled: true }, tooltip: { format: { title: function(d) { var achievement = this.achievements.find(function(element) { return element.value === this.xColumnValues[d + 1]; }.bind(this)); if (achievement !== undefined) { return this.xColumnValues[d + 1] + ": " + achievement.text; } return this.xColumnValues[d + 1]; }.bind(this) } } }); }; ProposalGraph.prototype.tickYValues = function() { var i, tick = [0], maximumValue = this.maximumValue === 0 ? this.proposalSuccess : Math.round(this.maximumValue * 1.10), step = maximumValue <= 10 ? 1 : Math.round(maximumValue / 10); for (i = step; i < maximumValue; i += step) { tick.push(i); } tick.push(maximumValue); return tick; }; ProposalGraph.prototype.tickXValues = function() { var i, l, tick = [], step = this.xColumnValues.length < 13 ? 1 : Math.round((this.xColumnValues.length - 1) / 12); if (this.xColumnValues.length > 1) { tick.push(0); for (i = step, l = this.xColumnValues.length - 1; i < l; i += step) { tick.push(i); } } return tick; }; ProposalGraph.prototype.formatXColumnValues = function() { var i, l; this.xColumnValues = this.xColumnValues.sort(); if (this.isDailyGrouped()) { for (i = 0, l = this.xColumnValues.length; i < l; i += 1) { this.xColumnValues[i] = this.formatGroup(this.xColumnValues[i]); } } this.xColumnValues.unshift("x"); }; ProposalGraph.prototype.formatGroup = function(group) { if (this.isDailyGrouped()) { var parts = group.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/); return parts[2] + "/" + parts[3]; } return group; }; ProposalGraph.prototype.isDailyGrouped = function() { return this.groupBy === undefined || this.groupBy === "" || this.groupBy === null; }; $(document).ready(function() { $("[data-proposal-graph-url]").each(function() { var graph = new ProposalGraph($(this).data("proposal-graph-url")); graph.successfulProposalDataUrl = $(this).data("successful-proposal-graph-url"); graph.proposalAchievementsUrl = $(this).data("proposal-achievements-url"); graph.targetId = $(this).attr("id"); graph.groupBy = $(this).data("proposal-graph-group-by"); graph.progressLabel = $(this).data("proposal-graph-progress-label"); graph.supportsLabel = $(this).data("proposal-graph-supports-label"); graph.successLabel = $(this).data("proposal-graph-success-label"); graph.proposalSuccess = parseInt($(this).data("proposal-success"), 10); graph.resourcesUrl = $(this).data("proposal-resources-url"); graph.refresh(); }); }); })();