Commit 2f87425cf091e8a39b63633e024c6810ed9fdb1c

Authored by Victor Costa
1 parent 6403ada6

New proposal ranking

@@ -298,21 +298,23 @@ @@ -298,21 +298,23 @@
298 <td class="abstract-text">Propostas</td> 298 <td class="abstract-text">Propostas</td>
299 <td class="votes-for"></td> 299 <td class="votes-for"></td>
300 <td class="votes-against"></td> 300 <td class="votes-against"></td>
301 - {{!-- <td class="apoio">Apoio</td> --}}  
302 - {{!-- <td class="participacao">Participacao</td> --}}  
303 - <td class="score">Pontuação</td> 301 + <td class="support">Apoio</td>
  302 + <td class="participation">Participação</td>
304 </tr> 303 </tr>
305 - {{#each articles}} 304 + {{#each proposals}}
306 <tr> 305 <tr>
307 <td class="abstract-text"><div class="truncate"><p class="truncated">{{abstract}}</p></div></td> 306 <td class="abstract-text"><div class="truncate"><p class="truncated">{{abstract}}</p></div></td>
308 - <td class="votes-for">{{votes_for}}</td>  
309 - <td class="votes-against">{{votes_against}}</td>  
310 - {{!-- <td class="apoio">{{#apoio .}}{{/apoio}}</td> --}}  
311 - {{!-- <td class="participacao">{{#participacao .}}{{/participacao}}</td> --}}  
312 - <td class="score">{{#score .}}{{/score}}</td> 307 + <td class="votes-for value">{{votes_for}}</td>
  308 + <td class="votes-against value">{{votes_against}}</td>
  309 + <td class="support value">{{#round effective_support}}{{/round}}</td>
  310 + <td class="participation value">{{#round effective_participation}}{{/round}}</td>
313 </tr> 311 </tr>
314 {{/each}} 312 {{/each}}
315 </table> 313 </table>
  314 + <div class="updated-at">
  315 + <span>Atualizado </span>
  316 + <span class="timeago" title="{{updated_at}}"></span>
  317 + </div>
316 </div> 318 </div>
317 </script> 319 </script>
318 320
js/handlebars-helpers.js
@@ -60,21 +60,7 @@ define([&#39;handlebars&#39;], function(Handlebars){ @@ -60,21 +60,7 @@ define([&#39;handlebars&#39;], function(Handlebars){
60 Handlebars.registerHelper('replace', function(string, to_replace, replacement) { 60 Handlebars.registerHelper('replace', function(string, to_replace, replacement) {
61 return (string || '').replace(new RegExp(to_replace, 'g'), replacement); 61 return (string || '').replace(new RegExp(to_replace, 'g'), replacement);
62 }); 62 });
63 -  
64 - Handlebars.registerHelper('score', function(article) {  
65 - return article.votes_for - article.votes_against;  
66 - });  
67 -  
68 - Handlebars.registerHelper('apoio', function(article) {  
69 - // return (article.votes_for - article.votes_against)/(article.countViews);  
70 - return 0;  
71 - });  
72 -  
73 - Handlebars.registerHelper('participacao', function(article) {  
74 - // return (article.votes_for + article.votes_against)/(article.countViews);  
75 - return 0;  
76 - });  
77 - 63 +
78 Handlebars.registerHelper('select_proposal', function(proposals, category_slug, selected_id) { 64 Handlebars.registerHelper('select_proposal', function(proposals, category_slug, selected_id) {
79 var ret = '<label for="proposal-selection" class="sr-only">Selecione o programa</label>' 65 var ret = '<label for="proposal-selection" class="sr-only">Selecione o programa</label>'
80 ret = ret + '<select id="proposal-selection" name="proposal-selection" data-proposal="'+selected_id+'" title="Selecione o programa" class="proposal-selection">'; 66 ret = ret + '<select id="proposal-selection" name="proposal-selection" data-proposal="'+selected_id+'" title="Selecione o programa" class="proposal-selection">';
@@ -101,6 +87,10 @@ define([&#39;handlebars&#39;], function(Handlebars){ @@ -101,6 +87,10 @@ define([&#39;handlebars&#39;], function(Handlebars){
101 } 87 }
102 }); 88 });
103 89
  90 + Handlebars.registerHelper('round', function(num) {
  91 + return +(Math.round(num + "e+2") + "e-2");
  92 + });
  93 +
104 function proposal_has_category(proposal, category_slug) { 94 function proposal_has_category(proposal, category_slug) {
105 for(var i=0; i<proposal.categories.length; i++) { 95 for(var i=0; i<proposal.categories.length; i++) {
106 if(proposal.categories[i].slug == category_slug) 96 if(proposal.categories[i].slug == category_slug)
js/jquery.timeago.js 0 → 100644
@@ -0,0 +1,221 @@ @@ -0,0 +1,221 @@
  1 +/**
  2 + * Timeago is a jQuery plugin that makes it easy to support automatically
  3 + * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
  4 + *
  5 + * @name timeago
  6 + * @version 1.4.1
  7 + * @requires jQuery v1.2.3+
  8 + * @author Ryan McGeary
  9 + * @license MIT License - http://www.opensource.org/licenses/mit-license.php
  10 + *
  11 + * For usage and examples, visit:
  12 + * http://timeago.yarp.com/
  13 + *
  14 + * Copyright (c) 2008-2015, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
  15 + */
  16 +
  17 +(function (factory) {
  18 + if (typeof define === 'function' && define.amd) {
  19 + // AMD. Register as an anonymous module.
  20 + define(['jquery'], factory);
  21 + } else {
  22 + // Browser globals
  23 + factory(jQuery);
  24 + }
  25 +}(function ($) {
  26 + $.timeago = function(timestamp) {
  27 + if (timestamp instanceof Date) {
  28 + return inWords(timestamp);
  29 + } else if (typeof timestamp === "string") {
  30 + return inWords($.timeago.parse(timestamp));
  31 + } else if (typeof timestamp === "number") {
  32 + return inWords(new Date(timestamp));
  33 + } else {
  34 + return inWords($.timeago.datetime(timestamp));
  35 + }
  36 + };
  37 + var $t = $.timeago;
  38 +
  39 + $.extend($.timeago, {
  40 + settings: {
  41 + refreshMillis: 60000,
  42 + allowPast: true,
  43 + allowFuture: false,
  44 + localeTitle: false,
  45 + cutoff: 0,
  46 + strings: {
  47 + prefixAgo: null,
  48 + prefixFromNow: null,
  49 + suffixAgo: "ago",
  50 + suffixFromNow: "from now",
  51 + inPast: 'any moment now',
  52 + seconds: "less than a minute",
  53 + minute: "about a minute",
  54 + minutes: "%d minutes",
  55 + hour: "about an hour",
  56 + hours: "about %d hours",
  57 + day: "a day",
  58 + days: "%d days",
  59 + month: "about a month",
  60 + months: "%d months",
  61 + year: "about a year",
  62 + years: "%d years",
  63 + wordSeparator: " ",
  64 + numbers: []
  65 + }
  66 + },
  67 +
  68 + inWords: function(distanceMillis) {
  69 + if(!this.settings.allowPast && ! this.settings.allowFuture) {
  70 + throw 'timeago allowPast and allowFuture settings can not both be set to false.';
  71 + }
  72 +
  73 + var $l = this.settings.strings;
  74 + var prefix = $l.prefixAgo;
  75 + var suffix = $l.suffixAgo;
  76 + if (this.settings.allowFuture) {
  77 + if (distanceMillis < 0) {
  78 + prefix = $l.prefixFromNow;
  79 + suffix = $l.suffixFromNow;
  80 + }
  81 + }
  82 +
  83 + if(!this.settings.allowPast && distanceMillis >= 0) {
  84 + return this.settings.strings.inPast;
  85 + }
  86 +
  87 + var seconds = Math.abs(distanceMillis) / 1000;
  88 + var minutes = seconds / 60;
  89 + var hours = minutes / 60;
  90 + var days = hours / 24;
  91 + var years = days / 365;
  92 +
  93 + function substitute(stringOrFunction, number) {
  94 + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
  95 + var value = ($l.numbers && $l.numbers[number]) || number;
  96 + return string.replace(/%d/i, value);
  97 + }
  98 +
  99 + var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
  100 + seconds < 90 && substitute($l.minute, 1) ||
  101 + minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
  102 + minutes < 90 && substitute($l.hour, 1) ||
  103 + hours < 24 && substitute($l.hours, Math.round(hours)) ||
  104 + hours < 42 && substitute($l.day, 1) ||
  105 + days < 30 && substitute($l.days, Math.round(days)) ||
  106 + days < 45 && substitute($l.month, 1) ||
  107 + days < 365 && substitute($l.months, Math.round(days / 30)) ||
  108 + years < 1.5 && substitute($l.year, 1) ||
  109 + substitute($l.years, Math.round(years));
  110 +
  111 + var separator = $l.wordSeparator || "";
  112 + if ($l.wordSeparator === undefined) { separator = " "; }
  113 + return $.trim([prefix, words, suffix].join(separator));
  114 + },
  115 +
  116 + parse: function(iso8601) {
  117 + var s = $.trim(iso8601);
  118 + s = s.replace(/\.\d+/,""); // remove milliseconds
  119 + s = s.replace(/-/,"/").replace(/-/,"/");
  120 + s = s.replace(/T/," ").replace(/Z/," UTC");
  121 + s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
  122 + s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900
  123 + return new Date(s);
  124 + },
  125 + datetime: function(elem) {
  126 + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
  127 + return $t.parse(iso8601);
  128 + },
  129 + isTime: function(elem) {
  130 + // jQuery's `is()` doesn't play well with HTML5 in IE
  131 + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
  132 + }
  133 + });
  134 +
  135 + // functions that can be called via $(el).timeago('action')
  136 + // init is default when no action is given
  137 + // functions are called with context of a single element
  138 + var functions = {
  139 + init: function(){
  140 + var refresh_el = $.proxy(refresh, this);
  141 + refresh_el();
  142 + var $s = $t.settings;
  143 + if ($s.refreshMillis > 0) {
  144 + this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);
  145 + }
  146 + },
  147 + update: function(time){
  148 + var parsedTime = $t.parse(time);
  149 + $(this).data('timeago', { datetime: parsedTime });
  150 + if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString());
  151 + refresh.apply(this);
  152 + },
  153 + updateFromDOM: function(){
  154 + $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
  155 + refresh.apply(this);
  156 + },
  157 + dispose: function () {
  158 + if (this._timeagoInterval) {
  159 + window.clearInterval(this._timeagoInterval);
  160 + this._timeagoInterval = null;
  161 + }
  162 + }
  163 + };
  164 +
  165 + $.fn.timeago = function(action, options) {
  166 + var fn = action ? functions[action] : functions.init;
  167 + if(!fn){
  168 + throw new Error("Unknown function name '"+ action +"' for timeago");
  169 + }
  170 + // each over objects here and call the requested function
  171 + this.each(function(){
  172 + fn.call(this, options);
  173 + });
  174 + return this;
  175 + };
  176 +
  177 + function refresh() {
  178 + //check if it's still visible
  179 + if(!$.contains(document.documentElement,this)){
  180 + //stop if it has been removed
  181 + $(this).timeago("dispose");
  182 + return this;
  183 + }
  184 +
  185 + var data = prepareData(this);
  186 + var $s = $t.settings;
  187 +
  188 + if (!isNaN(data.datetime)) {
  189 + if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) {
  190 + $(this).text(inWords(data.datetime));
  191 + }
  192 + }
  193 + return this;
  194 + }
  195 +
  196 + function prepareData(element) {
  197 + element = $(element);
  198 + if (!element.data("timeago")) {
  199 + element.data("timeago", { datetime: $t.datetime(element) });
  200 + var text = $.trim(element.text());
  201 + if ($t.settings.localeTitle) {
  202 + element.attr("title", element.data('timeago').datetime.toLocaleString());
  203 + } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
  204 + element.attr("title", text);
  205 + }
  206 + }
  207 + return element.data("timeago");
  208 + }
  209 +
  210 + function inWords(date) {
  211 + return $t.inWords(distance(date));
  212 + }
  213 +
  214 + function distance(date) {
  215 + return (new Date().getTime() - date.getTime());
  216 + }
  217 +
  218 + // fix for IE6 suckage
  219 + document.createElement("abbr");
  220 + document.createElement("time");
  221 +}));
js/jquery.timeago.pt-br.js 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +// Brazilian Portuguese
  2 +jQuery.timeago.settings.strings = {
  3 + prefixAgo: "há",
  4 + prefixFromNow: "em",
  5 + suffixAgo: null,
  6 + suffixFromNow: null,
  7 + seconds: "alguns segundos",
  8 + minute: "um minuto",
  9 + minutes: "%d minutos",
  10 + hour: "uma hora",
  11 + hours: "%d horas",
  12 + day: "um dia",
  13 + days: "%d dias",
  14 + month: "um mês",
  15 + months: "%d meses",
  16 + year: "um ano",
  17 + years: "%d anos"
  18 +};
@@ -17,7 +17,7 @@ define([&#39;handlebars&#39;, &#39;fastclick&#39;, &#39;handlebars_helpers&#39;], function(Handlebars, F @@ -17,7 +17,7 @@ define([&#39;handlebars&#39;, &#39;fastclick&#39;, &#39;handlebars_helpers&#39;], function(Handlebars, F
17 17
18 var loginButton; 18 var loginButton;
19 19
20 - var participa = true; 20 + var participa = false;
21 if(participa){ 21 if(participa){
22 var host = 'http://www.participa.br'; 22 var host = 'http://www.participa.br';
23 var private_token = '375bee7e17d0021af7160ce664874618'; //participa 23 var private_token = '375bee7e17d0021af7160ce664874618'; //participa
@@ -102,12 +102,13 @@ define([&#39;handlebars&#39;, &#39;fastclick&#39;, &#39;handlebars_helpers&#39;], function(Handlebars, F @@ -102,12 +102,13 @@ define([&#39;handlebars&#39;, &#39;fastclick&#39;, &#39;handlebars_helpers&#39;], function(Handlebars, F
102 $resultsContainer.find('.loading').show(); 102 $resultsContainer.find('.loading').show();
103 $resultsContainer.find('.results-content').hide(); 103 $resultsContainer.find('.results-content').hide();
104 104
105 - var url = host + '/api/v1/articles/' + topic_id + '/children' + '?private_token=' + private_token + '&limit=10&order=votes_score&fields=id,name,abstract,votes_for,votes_against&content_type=ProposalsDiscussionPlugin::Proposal'; 105 + var url = host + '/api/v1/proposals_discussion_plugin/' + topic_id + '/ranking' + '?private_token=' + private_token + '&limit=10';
106 $.getJSON(url).done(function( data ) { 106 $.getJSON(url).done(function( data ) {
107 107
108 $resultsContainer.html(resultsTemplate(data)); 108 $resultsContainer.html(resultsTemplate(data));
109 $resultsContainer.find('.loading').hide(); 109 $resultsContainer.find('.loading').hide();
110 $resultsContainer.find('.results-content').show(); 110 $resultsContainer.find('.results-content').show();
  111 + $(".timeago").timeago();
111 $resultsContainer.show(); 112 $resultsContainer.show();
112 113
113 // scroll to the end 114 // scroll to the end
js/requirejs-config.js
@@ -12,6 +12,8 @@ requirejs.config({ @@ -12,6 +12,8 @@ requirejs.config({
12 jquery_xdomainrequest: 'jquery.xdomainrequest.min', 12 jquery_xdomainrequest: 'jquery.xdomainrequest.min',
13 jquery_ui: 'jquery-ui-1.11.4.custom/jquery-ui.min', 13 jquery_ui: 'jquery-ui-1.11.4.custom/jquery-ui.min',
14 jquery_cookie: 'jquery.cookie', 14 jquery_cookie: 'jquery.cookie',
  15 + jquery_timeago: 'jquery.timeago',
  16 + jquery_timeago_pt: 'jquery.timeago.pt-br',
15 handlebars: 'handlebars-v3.0.1', 17 handlebars: 'handlebars-v3.0.1',
16 handlebars_helpers: 'handlebars-helpers', 18 handlebars_helpers: 'handlebars-helpers',
17 jquery_maxlength: 'jquery.maxlength.min', 19 jquery_maxlength: 'jquery.maxlength.min',
@@ -29,6 +31,12 @@ requirejs.config({ @@ -29,6 +31,12 @@ requirejs.config({
29 'jquery_xdomainrequest': { 31 'jquery_xdomainrequest': {
30 deps: ['jquery'] 32 deps: ['jquery']
31 }, 33 },
  34 + 'jquery_timeago': {
  35 + deps: ['jquery']
  36 + },
  37 + 'jquery_timeago_pt': {
  38 + deps: ['jquery_timeago']
  39 + },
32 'jquery_ui': { 40 'jquery_ui': {
33 deps: ['jquery'] 41 deps: ['jquery']
34 }, 42 },
@@ -54,5 +62,5 @@ requirejs.config({ @@ -54,5 +62,5 @@ requirejs.config({
54 } 62 }
55 }); 63 });
56 64
57 -requirejs(['jquery', 'proposal_app', 'jquery_ui', 'jquery_xdomainrequest', 'handlebars_helpers']); 65 +requirejs(['jquery', 'proposal_app', 'jquery_ui', 'jquery_xdomainrequest', 'jquery_timeago_pt', 'handlebars_helpers']);
58 requirejs(['slick', 'fastclick', 'jquery_maxlength', 'layout','main']); 66 requirejs(['slick', 'fastclick', 'jquery_maxlength', 'layout','main']);
sass/_proposal_detail.scss
@@ -135,10 +135,18 @@ @@ -135,10 +135,18 @@
135 display: block; 135 display: block;
136 float: right; 136 float: right;
137 } 137 }
  138 + .updated-at {
  139 + font-size: 12px;
  140 + color: gray;
  141 + float: right;
  142 + }
138 } 143 }
139 table { 144 table {
140 clear: both; 145 clear: both;
141 margin-top: 20px; 146 margin-top: 20px;
  147 + td {
  148 + padding: 0 5px;
  149 + }
142 tbody tr:nth-child(odd) { 150 tbody tr:nth-child(odd) {
143 background-color: #e5e5e5; 151 background-color: #e5e5e5;
144 } 152 }
@@ -146,18 +154,12 @@ @@ -146,18 +154,12 @@
146 .abstract-text { 154 .abstract-text {
147 width: 80%; 155 width: 80%;
148 } 156 }
149 - .votes-for { 157 + .value {
150 width: 10%; 158 width: 10%;
151 text-align: center; 159 text-align: center;
152 } 160 }
153 - .votes-against {  
154 - @extend .votes-for;  
155 - }  
156 - .score {  
157 - @extend .votes-for;  
158 - }  
159 .header { 161 .header {
160 - line-height: 32px; 162 + line-height: 22px;
161 font-weight: bold; 163 font-weight: bold;
162 text-align: center; 164 text-align: center;
163 color: rgb(68, 68, 68); 165 color: rgb(68, 68, 68);
@@ -168,11 +170,9 @@ @@ -168,11 +170,9 @@
168 background-position: center; 170 background-position: center;
169 } 171 }
170 .votes-against { 172 .votes-against {
  173 + @extend .votes-for;
171 background-image: url(./images/result-dislike.png); 174 background-image: url(./images/result-dislike.png);
172 } 175 }
173 - .score {  
174 - background-image: none;  
175 - }  
176 } 176 }
177 177
178 .truncate { 178 .truncate {