From 89f3da25b93c8e5e237bc9554314a63a8b054684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Salvador=20P=C3=A9rez=20Garc=C3=ADa?= Date: Wed, 20 Jun 2018 12:01:58 +0200 Subject: [PATCH] Implements #138 and #139 Implements graph with supports for the given period. --- app/assets/javascripts/dashboard_graphs.js | 123 +++++++++++++++++ app/assets/javascripts/stats.js.coffee | 2 +- app/assets/stylesheets/application.scss | 1 - app/assets/stylesheets/proposal.scss | 38 ++++++ .../stylesheets/proposals_dashboard.scss | 127 ------------------ .../proposals_dashboard_controller.rb | 9 ++ app/services/proposal_supports_query.rb | 50 +++++++ app/views/layouts/_header.html.erb | 19 +-- app/views/layouts/application.html.erb | 4 +- .../layouts/proposals_dashboard.html.erb | 18 ++- app/views/proposals_dashboard/_menu.html.erb | 99 ++++++++++++++ app/views/proposals_dashboard/index.html.erb | 119 +--------------- app/views/proposals_dashboard/stats.html.erb | 20 +++ config/initializers/assets.rb | 1 + config/locales/en/general.yml | 14 +- config/locales/es/general.yml | 14 +- config/routes/proposal.rb | 2 + 17 files changed, 398 insertions(+), 262 deletions(-) create mode 100644 app/assets/javascripts/dashboard_graphs.js delete mode 100644 app/assets/stylesheets/proposals_dashboard.scss create mode 100644 app/services/proposal_supports_query.rb create mode 100644 app/views/proposals_dashboard/_menu.html.erb create mode 100644 app/views/proposals_dashboard/stats.html.erb diff --git a/app/assets/javascripts/dashboard_graphs.js b/app/assets/javascripts/dashboard_graphs.js new file mode 100644 index 000000000..75de05bca --- /dev/null +++ b/app/assets/javascripts/dashboard_graphs.js @@ -0,0 +1,123 @@ +//= require d3 +//= require c3 +//= require c3ext + +(function(){ + 'use strict'; + + var ProposalGraph = function(url) { + this.url = url; + this.targetId = null; + this.groupBy = null; + this.progressLabel = 'Progress'; + this.supportsLabel = 'Supports'; + }; + + ProposalGraph.prototype.refresh = function() { + $.ajax({ + url: this.url, + cache: false, + success: function (data) { + this.draw(data); + }.bind(this), + data: { + group_by: this.groupBy + } + }); + }; + + ProposalGraph.prototype.draw = function(data) { + var xColumnValues = [ 'x' ], + progressColumnValues = [ this.progressLabel ], // [ '<%= t('.progress') %>' ], + key; + + for (key in data) { + if (data.hasOwnProperty(key)) { + xColumnValues.push(key); + progressColumnValues.push(data[key]); + } + } + + c3.generate({ + bindto: '#' + this.targetId, + data: { + x: 'x', + columns: [ + xColumnValues, + progressColumnValues + ] + }, + axis: { + y: { + label: { + text: this.supportsLabel, // '<%= t '.supports' %> ', + position: 'outer-middle' + } + }, + x: { + type: 'category' + } + } + }); + }; + + $(document).ready(function () { + $('[data-proposal-graph-url]').each(function () { + var graph = new ProposalGraph($(this).data('proposal-graph-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.refresh(); + }); + }); +})(); + +// function drawProposalGraph(data) { +// var xColumnValues = [ 'x' ], +// progressColumnValues = [ 'Progreso' ]; // [ '<%= t('.progress') %>' ], +// key; +// +// for (key in data) { +// if (data.hasOwnProperty(key)) { +// xColumnValues.push(key); +// progressColumnValues.push(data[key]); +// } +// } +// +// c3.generate({ +// bindto: '#proposal-graph', +// data: { +// x: 'x', +// columns: [ +// xColumnValues, +// progressColumnValues +// ] +// }, +// axis: { +// y: { +// label: { +// text: 'Apoyos', // '<%= t '.supports' %> ', +// position: 'outer-middle' +// } +// }, +// x: { +// type: 'category' +// } +// } +// }); +// } +// +// $(document).ready(function () { +// $.ajax({ +// url: '<%= supports_proposal_dashboard_index_path(proposal, format: :json) %>', +// cache: false, +// success: function (data) { +// drawProposalGraph(data); +// }, +// data: { +// group_by: '<%= params[:group_by] %>' +// } +// }); +// }); diff --git a/app/assets/javascripts/stats.js.coffee b/app/assets/javascripts/stats.js.coffee index 7fcdfb00a..9e32c0bd7 100644 --- a/app/assets/javascripts/stats.js.coffee +++ b/app/assets/javascripts/stats.js.coffee @@ -1,4 +1,4 @@ -# Helper for generate C3.js graphs +}# Helper for generate C3.js graphs #---------------------------------------------------------------------- buildGraph = (el) -> diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 51149006d..5de3bb76d 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,7 +8,6 @@ @import 'participation'; @import 'pages'; @import 'proposal'; -@import 'proposals_dashboard'; @import 'legislation'; @import 'legislation_process'; @import 'community'; diff --git a/app/assets/stylesheets/proposal.scss b/app/assets/stylesheets/proposal.scss index 6ca80a791..63f90694c 100644 --- a/app/assets/stylesheets/proposal.scss +++ b/app/assets/stylesheets/proposal.scss @@ -16,3 +16,41 @@ background-color: #e7f3fd; } } + +.proposal-dashboard { + margin-top: -1.5rem; + + .columns { + padding: 0; + } + + .row { + max-width: 100%; + } + + .has-tip { + border-bottom: none; + font-weight: normal; + } + + .title { + border-bottom: 1pt solid lightgray; + + h5 { + padding: 1rem 1.5rem 1rem 1.5rem; + font-size: 16pt; + margin: 0; + } + } + + .left-menu { + border-right: 1pt solid lightgray; + border-bottom: 1pt solid lightgray; + padding: 1rem 1.5rem 1rem 1.5rem; + background-color: #fbfbfb; + } + + .body { + padding: 1rem 1.5rem 1rem 1.5rem; + } +} diff --git a/app/assets/stylesheets/proposals_dashboard.scss b/app/assets/stylesheets/proposals_dashboard.scss deleted file mode 100644 index 3c1351593..000000000 --- a/app/assets/stylesheets/proposals_dashboard.scss +++ /dev/null @@ -1,127 +0,0 @@ -.proposals-dashboard { - display: flex; - flex-direction: column; - margin-top: -1.5rem; - - .column-wrapper { - flex: 2; - display: flex; - - .left-column { - flex: 0 0 150pt; - background: lightgray; - margin-right: 5px; - padding: 5pt; - - .state-box { - .logo { - height: 100pt; - width: 100pt; - margin-left: 20pt; - margin-right: 20pt; - border-radius: 50pt; - background-color: #fff3cb; - border: 2pt solid white; - } - - .status { - height: 25pt; - width: 100pt; - margin-left: 20pt; - margin-right: 20pt; - padding-top: 3pt; - color: #055392; - font-weight: bold; - text-align: center; - vertical-align: middle; - } - - .draft { - background-color: #ffe699; - } - - .published { - background-color: #d3ebd2; - } - } - - .dashboard-menu { - color: #a9a9a9; - font-size: 16pt; - - .menu-title { - margin-top: 10pt; - } - - .menu-entry { - color: #a9a9a9; - padding-left: 25pt; - line-height: 30pt; - vertical-align: middle; - display: block; - } - - .menu-entry:focus, .menu-entry:active, .menu-entry:hover { - outline: 0; - text-decoration: none; - } - - .selected { - font-weight: bold; - color: #454545; - } - - .menu-entry.selected { - text-decoration: underline #a9a9a9; - } - } - } - - .right-column { - background: lightgray; - flex: 1 1; - padding: 5pt; - //min-height: 775px; - - .progress-info { - display: flex; - flex-flow: row wrap; - justify-content: flex-start; - align-items: center; - align-content: stretch; - width: 1440px; - } - - .cell-data { - flex-grow: 1; - width: 33%; - font-size: 16pt; - font-weight: bold; - line-height: 32pt; - vertical-align: middle; - padding-left: 42pt; - - .caption { - width: 150pt; - float: left; - } - - .value { - width: 50pt; - float: left; - text-align: right; - } - - .value:after { - clear: both; - } - } - - .body { - background-color: white; - height: 500px; - } - } - } -} - diff --git a/app/controllers/proposals_dashboard_controller.rb b/app/controllers/proposals_dashboard_controller.rb index 73c7f4778..12034a86a 100644 --- a/app/controllers/proposals_dashboard_controller.rb +++ b/app/controllers/proposals_dashboard_controller.rb @@ -50,6 +50,15 @@ class ProposalsDashboardController < ApplicationController end end + def stats + authorize! :dashboard, proposal + end + + def supports + authorize! :dashboard, proposal + render json: ProposalSupportsQuery.for(params) + end + private def proposal_executed_dashboard_action_params diff --git a/app/services/proposal_supports_query.rb b/app/services/proposal_supports_query.rb new file mode 100644 index 000000000..b886770d4 --- /dev/null +++ b/app/services/proposal_supports_query.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +class ProposalSupportsQuery + attr_reader :params + + def self.for(params) + query = ProposalSupportsQuery.new params + query.results + end + + def initialize(params) + @params = params + end + + def results + grouped_votes = groups + grouped_votes.each do |group, votes| + grouped_votes[group] = votes.inject(0) { |sum, vote| sum + vote.vote_weight } + end + + grouped_votes + end + + private + + def groups + return votes.group_by { |v| v.created_at.to_date.year } if params[:group_by] == 'year' + return votes.group_by { |v| "#{v.created_at.to_date.cweek}/#{v.created_at.to_date.year}" } if params[:group_by] == 'week' + return votes.group_by { |v| "#{v.created_at.to_date.year}-#{v.created_at.to_date.month}" } if params[:group_by] == 'month' + votes.group_by { |v| v.created_at.to_date } + end + + def votes + Vote.where(votable: proposal, created_at: start_date..end_date).order(created_at: :asc) + end + + def proposal + @proposal ||= Proposal.find(params[:proposal_id]) + end + + def start_date + return Date.parse(params[:start_date]) unless params[:start_date].blank? + proposal.created_at.to_date + end + + def end_date + return Date.parse(params[:end_date]) unless params[:end_date].blank? + Date.today + end +end diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index 8b4c0a171..c2c3aeb0b 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -63,15 +63,16 @@ -