Merge branch 'master' into api-dev

This commit is contained in:
Alberto Miedes Garcés
2016-11-18 16:40:33 +01:00
118 changed files with 516 additions and 510 deletions

View File

@@ -34,6 +34,16 @@ If you want to contribute code to solve an issue:
* Follow these [best practices](https://github.com/styleguide/ruby) * Follow these [best practices](https://github.com/styleguide/ruby)
* Open a *pull request* to the main repository describing what issue you are addressing. * Open a *pull request* to the main repository describing what issue you are addressing.
## Cleaning up
In the rush of time sometimes things get messy, you can help us cleaning things up:
* implement [pending specs](https://travis-ci.org/consul/consul)
* increase [code coverage](https://coveralls.io/github/consul/consul?branch=master)
* improve [code quality](https://codeclimate.com/github/consul/consul)
* update [dependencies](https://gemnasium.com/consul/consul)
* make [code consistent](https://github.com/bbatsov/rubocop)
## Other ways of contributing without coding ## Other ways of contributing without coding
* If you think there's a feature missing, or find a bug, create an issue (make sure it has not already been reported). * If you think there's a feature missing, or find a bug, create an issue (make sure it has not already been reported).

View File

@@ -34,6 +34,16 @@ Cuando quieras resolver una incidencia mediante código:
* Sigue estas [buenas prácticas](https://github.com/styleguide/ruby) * Sigue estas [buenas prácticas](https://github.com/styleguide/ruby)
* Envía una *pull request* al repositorio principal indicando la incidencia que se está arreglando * Envía una *pull request* al repositorio principal indicando la incidencia que se está arreglando
## Limpiar
En la urgencia del momento, las cosas a veces se ensucian, puedes ayudarnos a limpiar la casa:
* implementando [tests pendientes](https://travis-ci.org/consul/consul)
* incrementando la [cobertura de tests](https://coveralls.io/github/consul/consul?branch=master)
* mejorando la [calidad del código](https://codeclimate.com/github/consul/consul)
* actualizando [dependecias](https://gemnasium.com/consul/consul)
* haciendo el [código consistente](https://github.com/bbatsov/rubocop)
## Otras formas de contribuir sin código ## Otras formas de contribuir sin código
* Si crees que hay una funcionalidad que hace falta, o descubres un problema, abre una incidencia (asegúrate de que * Si crees que hay una funcionalidad que hace falta, o descubres un problema, abre una incidencia (asegúrate de que

View File

@@ -88,6 +88,7 @@ group :development, :test do
gem 'capistrano3-delayed-job', '~> 1.0' gem 'capistrano3-delayed-job', '~> 1.0'
gem "bullet" gem "bullet"
gem "faker" gem "faker"
gem 'rubocop', '~> 0.45.0', require: false
end end
group :test do group :test do

View File

@@ -59,7 +59,7 @@ GEM
ancestry (2.2.1) ancestry (2.2.1)
activerecord (>= 3.0.0) activerecord (>= 3.0.0)
arel (6.0.3) arel (6.0.3)
ast (2.2.0) ast (2.3.0)
babel-source (5.8.35) babel-source (5.8.35)
babel-transpiler (0.7.0) babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6) babel-source (>= 4.0, < 6)
@@ -274,7 +274,7 @@ GEM
orm_adapter (0.5.0) orm_adapter (0.5.0)
paranoia (2.2.0) paranoia (2.2.0)
activerecord (>= 4.0, < 5.1) activerecord (>= 4.0, < 5.1)
parser (2.3.0.6) parser (2.3.1.4)
ast (~> 2.2) ast (~> 2.2)
pg (0.19.0) pg (0.19.0)
pg_search (1.0.6) pg_search (1.0.6)
@@ -285,6 +285,7 @@ GEM
capybara (~> 2.1) capybara (~> 2.1)
cliver (~> 0.3.1) cliver (~> 0.3.1)
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
powerpack (0.1.1)
quiet_assets (1.1.0) quiet_assets (1.1.0)
railties (>= 3.1, < 5.0) railties (>= 3.1, < 5.0)
rack (1.6.4) rack (1.6.4)
@@ -318,6 +319,7 @@ GEM
activesupport (= 4.2.7.1) activesupport (= 4.2.7.1)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.1.0)
raindrops (0.16.0) raindrops (0.16.0)
rake (11.3.0) rake (11.3.0)
redcarpet (3.3.4) redcarpet (3.3.4)
@@ -349,6 +351,12 @@ GEM
rspec-mocks (~> 3.5.0) rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0) rspec-support (~> 3.5.0)
rspec-support (3.5.0) rspec-support (3.5.0)
rubocop (0.45.0)
parser (>= 2.3.1.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.8.1) ruby-progressbar (1.8.1)
safe_yaml (1.0.4) safe_yaml (1.0.4)
safely_block (0.1.1) safely_block (0.1.1)
@@ -415,6 +423,7 @@ GEM
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (3.0.3) uglifier (3.0.3)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unicode-display_width (1.1.1)
unicorn (5.1.0) unicorn (5.1.0)
kgio (~> 2.6) kgio (~> 2.6)
raindrops (~> 0.7) raindrops (~> 0.7)
@@ -499,6 +508,7 @@ DEPENDENCIES
rinku (~> 2.0.2) rinku (~> 2.0.2)
rollbar (~> 2.13.3) rollbar (~> 2.13.3)
rspec-rails (~> 3.5) rspec-rails (~> 3.5)
rubocop (~> 0.45.0)
sass-rails (~> 5.0, >= 5.0.4) sass-rails (~> 5.0, >= 5.0.4)
savon savon
social-share-button social-share-button

View File

@@ -45,6 +45,7 @@
//= require valuation_spending_proposal_form //= require valuation_spending_proposal_form
//= require embed_video //= require embed_video
//= require banners //= require banners
//= require social_share
//= require custom //= require custom
var initialize_modules = function() { var initialize_modules = function() {
@@ -66,6 +67,7 @@ var initialize_modules = function() {
App.ValuationSpendingProposalForm.initialize(); App.ValuationSpendingProposalForm.initialize();
App.EmbedVideo.initialize(); App.EmbedVideo.initialize();
App.Banners.initialize(); App.Banners.initialize();
App.SocialShare.initialize();
}; };
$(function(){ $(function(){

View File

@@ -0,0 +1,7 @@
App.SocialShare =
initialize: ->
$(".social-share-button a").each ->
element = $(this)
site = element.data('site')
element.append("<span class='sr-only'>#{site}</span>")

View File

@@ -51,6 +51,7 @@ $base-font-size: rem-calc(17);
$base-line: rem-calc(26); $base-line: rem-calc(26);
$small-font-size: rem-calc(14); $small-font-size: rem-calc(14);
$line-height: rem-calc(24); $line-height: rem-calc(24);
$tiny-font-size: rem-calc(12);
$brand: #004A83; $brand: #004A83;
$dark: darken($brand, 10%); $dark: darken($brand, 10%);
@@ -66,7 +67,6 @@ $link-hover: darken($link, 20%);
$debates: #008CCF; $debates: #008CCF;
$votes: #26AEEE;
$like: #7BD2A8; $like: #7BD2A8;
$unlike: #EF8585; $unlike: #EF8585;
@@ -79,7 +79,7 @@ $budget: #454372;
$budget-hover: #7571BF; $budget-hover: #7571BF;
$highlight: #E7F2FC; $highlight: #E7F2FC;
$featured: #FED900; $featured: #FFDC5C;
$footer-border: #BFC1C3; $footer-border: #BFC1C3;

View File

@@ -475,8 +475,16 @@ header {
&.active { &.active {
border-bottom: 2px solid $brand; border-bottom: 2px solid $brand;
color: $brand; color: $brand;
&:hover {
text-decoration: none;
} }
} }
}
h2 {
font-size: $base-font-size;
}
} }
.search-form-header input[type=text] { .search-form-header input[type=text] {
@@ -1247,13 +1255,14 @@ table {
} }
.share-supported { .share-supported {
text-align: center;
.social-share-button { .social-share-button {
display: inline-block; display: inline-block;
} }
.ssb-twitter { .ssb-twitter {
background: none; background: #45B0E3;
color: white; color: white;
height: $line-height; height: $line-height;
position: relative; position: relative;
@@ -1276,7 +1285,7 @@ table {
} }
.ssb-facebook { .ssb-facebook {
background: none; background: #3B5998;
color: white; color: white;
height: rem-calc(24); height: rem-calc(24);
position: relative; position: relative;
@@ -1299,7 +1308,7 @@ table {
} }
.ssb-google_plus { .ssb-google_plus {
background: none; background: #DE4C34;
color: white; color: white;
height: rem-calc(24); height: rem-calc(24);
position: relative; position: relative;
@@ -1550,7 +1559,7 @@ table {
.comment-votes { .comment-votes {
color: $text-medium; color: $text-medium;
font-size: rem-calc(14); font-size: $small-font-size;
line-height: $line-height; line-height: $line-height;
a { a {
@@ -1560,12 +1569,21 @@ table {
&:hover { &:hover {
color: $text-medium; color: $text-medium;
text-decoration: none;
.icon-like {
color: $like;
}
.icon-unlike {
color: $unlike;
}
} }
} }
[class^="icon-"] { [class^="icon-"] {
font-size: rem-calc(20); font-size: $base-font-size;
vertical-align: middle; vertical-align: sub;
} }
} }
@@ -1685,7 +1703,8 @@ table {
} }
.flag-disable, .flag-active { .flag-disable, .flag-active {
vertical-align: middle; line-height: 0;
vertical-align: sub;
} }
.flag-disable { .flag-disable {

View File

@@ -12,14 +12,21 @@
// ---------------------- // ----------------------
@mixin votes { @mixin votes {
background: $votes; border-top: 1px solid $border;
margin: 0 rem-calc(-12); margin-top: $line-height;
padding: rem-calc(14) rem-calc(12); padding: $line-height 0;
position: relative; position: relative;
@include breakpoint(medium) {
border-left: 1px solid $border;
border-top: 0;
margin-top: 0;
padding-top: $line-height*2;
}
.icon-like, .icon-unlike { .icon-like, .icon-unlike {
background: white; background: white;
border: 2px solid $votes; border: 2px solid $text-light;
border-radius: rem-calc(3); border-radius: rem-calc(3);
color: $text-light; color: $text-light;
display: inline-block; display: inline-block;
@@ -29,7 +36,6 @@
position: relative; position: relative;
&:hover, &:active { &:hover, &:active {
border-color: white;
color: white; color: white;
cursor: pointer; cursor: pointer;
opacity: 1 !important; opacity: 1 !important;
@@ -40,6 +46,7 @@
&:hover, &:active { &:hover, &:active {
background: $like; background: $like;
border: 2px solid $like;
} }
} }
@@ -47,50 +54,64 @@
&:hover, &:active { &:hover, &:active {
background: $unlike; background: $unlike;
border: 2px solid $unlike;
} }
} }
.like, .unlike { .like, .unlike {
line-height: rem-calc(48); line-height: rem-calc(48);
vertical-align: super; vertical-align: super;
text-decoration: none;
span.percentage { span.percentage {
color: white; color: $text;
display: inline-block; display: inline-block;
font-size: rem-calc(16); font-size: $small-font-size;
line-height: $line-height*2; line-height: $line-height*2;
padding-left: rem-calc(8); padding-right: $line-height/2;
vertical-align: top; vertical-align: top;
@include breakpoint(medium) {
display: block;
line-height: $line-height;
padding-right: 0;
}
} }
} }
.voted { .voted {
.icon-like, .icon-unlike { .icon-like, .icon-unlike {
border-color: white;
color: white; color: white;
} }
.icon-like { .icon-like {
background: $like; background: $like;
border: 2px solid $like;
} }
.icon-unlike { .icon-unlike {
background: $unlike; background: $unlike;
border: 2px solid $unlike;
} }
} }
.no-voted { .no-voted {
.icon-like, .icon-unlike { .icon-like, .icon-unlike {
opacity: .5; opacity: .3;
} }
} }
.total-votes { .total-votes {
color: white; font-weight: bold;
float: right; float: right;
line-height: $line-height*2; line-height: $line-height*2;
@include breakpoint(medium) {
display: block;
float: none;
}
} }
.divider { .divider {
@@ -99,64 +120,65 @@
} }
@mixin supports { @mixin supports {
background: $proposals; padding: $line-height 0;
margin: 0 rem-calc(-12);
padding: rem-calc(14) rem-calc(12);
position: relative; position: relative;
.progress { .progress {
background-color: rgba(255,255,255,.8); background: lighten($proposals, 35%);
height: $line-height/2; border: 1px solid lighten($proposals, 35%);
height: rem-calc(14);
position: relative;
.meter { .meter {
background: $like; background: $proposals;
border-radius: 0;
border-bottom-right-radius: rem-calc(3);
border-top-right-radius: rem-calc(3);
display: block; display: block;
height: $line-height/2; height: $line-height/2;
} }
} }
.percentage { .percentage {
font-size: rem-calc(10); color: $text;
color: $brand; font-size: $tiny-font-size;
vertical-align: top;
position: absolute; position: absolute;
top: 13px; right: 6px;
right: 20px; top: -2px;
vertical-align: top;
} }
abbr { abbr {
color: white; color: $text-medium;
&[title] { &[title] {
border-bottom: 1px dotted white; border-bottom: 1px dotted $text-medium;
} }
} }
.button-support { .button-support {
background: white; background: $proposals;
color: $text; color: $text;
display: inline-block; display: inline-block;
font-size: $small-font-size; font-size: $small-font-size;
margin-top: rem-calc(12); margin-top: rem-calc(12);
&:hover { &:hover, &:active {
background: darken($proposals, 35%); background: lighten($proposals, 25%);
color: white;
cursor: pointer; cursor: pointer;
} }
&:active {
opacity: .75;
}
} }
.total-supports { .total-supports {
color: white; color: $text;
display: block;
font-weight: bold;
text-align: center; text-align: center;
font-size: $small-font-size;
span { span {
display: block; display: block;
font-size: $small-font-size;
font-weight: normal;
} }
} }
@@ -165,23 +187,17 @@
} }
.supported { .supported {
color: white; color: $text;
margin-top: rem-calc(12); margin-top: rem-calc(12);
} }
} }
.message { .supports-container {
@include supports; border-top: 1px solid $border;
background: none;
border-top: 0;
@include breakpoint(medium) { @include breakpoint(medium) {
border-left: 1px solid $border; border-left: 1px solid $border;
margin: $line-height rem-calc(-25) 0 rem-calc(12); border-top: 0;
}
p {
font-size: $small-font-size;
} }
} }
@@ -276,7 +292,9 @@
// 03. Show participation // 03. Show participation
// ---------------------- // ----------------------
.debate-show, .proposal-show, .investment-project-show { .debate-show,
.proposal-show,
.investment-project-show {
p { p {
word-wrap: break-word; word-wrap: break-word;
@@ -413,47 +431,8 @@
} }
} }
.votes {
@include votes;
border: 0;
border-radius: 0;
margin: 0;
.total-votes {
display: block;
float: none;
line-height: $line-height;
}
@include breakpoint(small + rem-calc(1) and medium down) {
.in-favor, .against {
text-align: left;
width: rem-calc(100);
}
}
.divider {
display: none;
}
@include breakpoint(medium) {
.divider {
display: inline-block;
}
}
}
.supports { .supports {
@include supports; @include supports;
border: 0;
border-radius: 0;
margin: 0;
.total-supports {
display: block;
float: none;
line-height: $line-height;
}
} }
.leave-comment { .leave-comment {
@@ -478,6 +457,17 @@
word-break: break-word; word-break: break-word;
} }
.proposal-show, .investment-project-show {
.supports {
padding: $line-height/2 0 0;
}
.share-supported {
display: none;
}
}
// 04. List participation // 04. List participation
// ---------------------- // ----------------------
@@ -496,8 +486,7 @@
} }
.debate, .proposal, .investment-project { .debate, .proposal, .investment-project {
margin-bottom: 0; margin: $line-height/4 0;
margin-top: 0;
.panel { .panel {
background: white; background: white;
@@ -651,107 +640,30 @@
} }
} }
.debate { .debate, .debate-show {
.votes { .votes {
@include votes; @include votes;
border: 1px solid $votes;
margin: 0 rem-calc(-12);
@include breakpoint(medium) { .against {
border-top-left-radius: 3px; margin-left: $line-height/4;
border-bottom-left-radius: 3px;
margin: 0 rem-calc(-25) 0 rem-calc(12);
}
&:after {
content: none;
position: absolute;
display: block;
border-style: solid;
border-color: #166387 transparent transparent transparent;
bottom: -14px;
border-left-width: 0;
border-right-color: transparent;
right: -1px;
border-width: 13px 13px 0 0;
@include breakpoint(medium) {
content: "";
}
}
.total-votes {
display: inline-block;
line-height: $line-height;
margin-left: rem-calc(24);
padding-top: rem-calc(12);
vertical-align: top;
@include breakpoint(medium) {
display: block;
float: none;
line-height: $line-height*2;
margin-left: 0;
padding-top: 0;
}
} }
@include breakpoint(medium) { @include breakpoint(medium) {
.like, .unlike { text-align: center;
}
}
}
span.percentage { .debate-show .votes {
display: block; border: 0;
line-height: $line-height/2; padding: $line-height/2 0;
}
}
}
}
} }
.proposal { .proposal {
.supports { .supports {
@include supports; @include supports;
border: 1px solid $proposals;
margin: 0 rem-calc(-12);
@include breakpoint(medium) {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
margin: 0 rem-calc(-25) 0 rem-calc(12);
}
&:after {
content: none;
position: absolute;
display: block;
border-style: solid;
border-color: #664212 transparent transparent transparent;
bottom: -14px;
border-left-width: 0;
border-right-color: transparent;
right: -1px;
border-width: 13px 13px 0 0;
@include breakpoint(medium) {
content: "";
}
}
.total-supports {
display: inline-block;
line-height: $line-height;
padding-top: rem-calc(12);
vertical-align: top;
@include breakpoint(medium) {
display: block;
float: none;
margin-left: 0;
padding-top: 0;
}
}
} }
} }
@@ -759,20 +671,6 @@
.supports { .supports {
@include supports; @include supports;
background: none;
border: 0;
border-left: 1px solid $border;
margin: 0 rem-calc(-12);
min-height: rem-calc(180);
padding-top: 0;
@include breakpoint(medium) {
padding-top: $line-height*1.5;
}
&:after {
content: none;
}
.investment-project-amount { .investment-project-amount {
color: $budget; color: $budget;
@@ -802,31 +700,12 @@
font-weight: bold; font-weight: bold;
} }
.supported {
color: $budget;
margin-top: 0;
width: 100%;
}
.remove .icon-check-circle { .remove .icon-check-circle {
display: block; display: block;
font-size: rem-calc(70); font-size: rem-calc(70);
line-height: rem-calc(70); line-height: rem-calc(70);
} }
.share-supported {
.ssb-twitter,
.ssb-facebook,
.ssb-google_plus {
color: $budget;
} }
}
}
}
.investment-project-show .supports {
border: 0;
} }
.proposals-summary { .proposals-summary {
@@ -903,7 +782,14 @@
} }
.button-support { .button-support {
background: $text;
color: $featured;
margin-top: 0; margin-top: 0;
&:hover {
background: white;
color: $text;
}
} }
.participation-not-allowed { .participation-not-allowed {
@@ -924,6 +810,7 @@
.supported { .supported {
margin-top: 0; margin-top: 0;
font-size: $small-font-size;
} }
.share-supported { .share-supported {
@@ -931,7 +818,10 @@
.ssb-twitter, .ssb-twitter,
.ssb-facebook, .ssb-facebook,
.ssb-google_plus { .ssb-google_plus {
height: rem-calc(33); background: none;
color: $text;
height: rem-calc(33) !important;
&:before { &:before {
font-size: rem-calc(18); font-size: rem-calc(18);

View File

@@ -38,6 +38,7 @@ class Admin::BannersController < Admin::BaseController
end end
private private
def banner_params def banner_params
params.require(:banner).permit(:title, :description, :target_url, :style, :image, :post_started_at, :post_ended_at) params.require(:banner).permit(:title, :description, :target_url, :style, :image, :post_started_at, :post_ended_at)
end end
@@ -53,4 +54,5 @@ class Admin::BannersController < Admin::BaseController
def banner_imgs def banner_imgs
@banner_imgs = Setting.all.banner_img.map { |banner_img| [banner_img.value, banner_img.key.split('.')[1]] } @banner_imgs = Setting.all.banner_img.map { |banner_img| [banner_img.value, banner_img.key.split('.')[1]] }
end end
end end

View File

@@ -20,6 +20,7 @@ class Admin::CommentsController < Admin::BaseController
end end
private private
def load_comment def load_comment
@comment = Comment.with_hidden.find(params[:id]) @comment = Comment.with_hidden.find(params[:id])
end end

View File

@@ -25,6 +25,7 @@ class Admin::OfficialsController < Admin::BaseController
end end
private private
def user_params def user_params
params.require(:user).permit(:official_position, :official_level) params.require(:user).permit(:official_position, :official_level)
end end

View File

@@ -15,7 +15,9 @@ class Admin::SettingsController < Admin::BaseController
end end
private private
def settings_params def settings_params
params.require(:setting).permit(:value) params.require(:setting).permit(:value)
end end
end end

View File

@@ -32,4 +32,5 @@ class Admin::StatsController < Admin::BaseController
@direct_messages = DirectMessage.count @direct_messages = DirectMessage.count
@users_who_have_sent_message = DirectMessage.select(:sender_id).distinct.count @users_who_have_sent_message = DirectMessage.select(:sender_id).distinct.count
end end
end end

View File

@@ -30,8 +30,10 @@ class Admin::ValuatorsController < Admin::BaseController
end end
private private
def create_params def create_params
params[:valuator][:description] = nil if params[:valuator][:description].blank? params[:valuator][:description] = nil if params[:valuator][:description].blank?
params.require(:valuator).permit(:user_id, :description) params.require(:valuator).permit(:user_id, :description)
end end
end end

View File

@@ -1,6 +1,7 @@
module Polymorphic module Polymorphic
private private
def resource def resource
@resource ||= instance_variable_get("@#{resource_name}") @resource ||= instance_variable_get("@#{resource_name}")
end end

View File

@@ -6,6 +6,7 @@ class Management::AccountController < Management::BaseController
end end
private private
def only_verified_users def only_verified_users
check_verified_user t("management.account.alert.unverified_user") check_verified_user t("management.account.alert.unverified_user")
end end

View File

@@ -24,6 +24,7 @@ class Organizations::RegistrationsController < Devise::RegistrationsController
end end
protected protected
def after_inactive_sign_up_path_for(resource) def after_inactive_sign_up_path_for(resource)
organizations_sign_up_success_path organizations_sign_up_success_path
end end

View File

@@ -56,5 +56,4 @@ class Verification::LetterController < ApplicationController
end end
end end
end end

View File

@@ -9,6 +9,7 @@ class Verification::VerifiedUserController < ApplicationController
end end
private private
def user_data_present? def user_data_present?
return false if @verified_users.blank? return false if @verified_users.blank?

View File

@@ -16,5 +16,4 @@ class WelcomeController < ApplicationController
redirect_to verification_path if signed_in? redirect_to verification_path if signed_in?
end end
end end

View File

@@ -5,7 +5,7 @@ module AdminHelper
end end
def official_level_options def official_level_options
options = [["",0]] options = [["", 0]]
(1..5).each do |i| (1..5).each do |i|
options << [[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(': '), i] options << [[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(': '), i]
end end

View File

@@ -1,5 +1,7 @@
module BannersHelper module BannersHelper
def has_banners def has_banners
@banners.count > 0 @banners.count > 0
end end
end end

View File

@@ -39,4 +39,5 @@ module CommentsHelper
"" # Default not author class "" # Default not author class
end end
end end
end end

View File

@@ -3,4 +3,5 @@ module DebatesHelper
def has_featured? def has_featured?
Debate.all.featured.count > 0 Debate.all.featured.count > 0
end end
end end

View File

@@ -9,15 +9,15 @@ module EmbedVideosHelper
end end
if server == "Vimeo" if server == "Vimeo"
regExp = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/ reg_exp = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
src = "https://player.vimeo.com/video/" src = "https://player.vimeo.com/video/"
elsif server == "YouTube" elsif server == "YouTube"
regExp = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/ reg_exp = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
src = "https://www.youtube.com/embed/" src = "https://www.youtube.com/embed/"
end end
if regExp if reg_exp
match = link.match(regExp) match = link.match(reg_exp)
end end
if match and match[2] if match and match[2]

View File

@@ -1,4 +1,2 @@
module NotificationsHelper module NotificationsHelper
end end

View File

@@ -20,4 +20,5 @@ module StatsHelper
opt[:data][:graph] = admin_api_stats_path(spending_proposals: true) opt[:data][:graph] = admin_api_stats_path(spending_proposals: true)
content_tag :div, "", opt content_tag :div, "", opt
end end
end end

View File

@@ -1,4 +1,5 @@
module TracksHelper module TracksHelper
def track_event(data={}) def track_event(data={})
track_data = "" track_data = ""
prefix = " data-track-event-" prefix = " data-track-event-"
@@ -9,4 +10,5 @@ module TracksHelper
track_data track_data
end end
end end
end end

View File

@@ -24,8 +24,8 @@ class Comment < ActiveRecord::Base
scope :not_as_admin_or_moderator, -> { where("administrator_id IS NULL").where("moderator_id IS NULL")} scope :not_as_admin_or_moderator, -> { where("administrator_id IS NULL").where("moderator_id IS NULL")}
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) } scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
scope :sort_by_most_voted , -> { order(confidence_score: :desc, created_at: :desc) } scope :sort_by_most_voted, -> { order(confidence_score: :desc, created_at: :desc) }
scope :sort_descendants_by_most_voted , -> { order(confidence_score: :desc, created_at: :asc) } scope :sort_descendants_by_most_voted, -> { order(confidence_score: :desc, created_at: :asc) }
scope :sort_by_newest, -> { order(created_at: :desc) } scope :sort_by_newest, -> { order(created_at: :desc) }
scope :sort_descendants_by_newest, -> { order(created_at: :desc) } scope :sort_descendants_by_newest, -> { order(created_at: :desc) }

View File

@@ -28,7 +28,7 @@ class Debate < ActiveRecord::Base
before_save :calculate_hot_score, :calculate_confidence_score before_save :calculate_hot_score, :calculate_confidence_score
scope :for_render, -> { includes(:tags) } scope :for_render, -> { includes(:tags) }
scope :sort_by_hot_score , -> { reorder(hot_score: :desc) } scope :sort_by_hot_score, -> { reorder(hot_score: :desc) }
scope :sort_by_confidence_score, -> { reorder(confidence_score: :desc) } scope :sort_by_confidence_score, -> { reorder(confidence_score: :desc) }
scope :sort_by_created_at, -> { reorder(created_at: :desc) } scope :sort_by_created_at, -> { reorder(created_at: :desc) }
scope :sort_by_most_commented, -> { reorder(comments_count: :desc) } scope :sort_by_most_commented, -> { reorder(comments_count: :desc) }

View File

@@ -49,4 +49,5 @@ class Notification < ActiveRecord::Base
def linkable_resource def linkable_resource
notifiable.is_a?(ProposalNotification) ? notifiable.proposal : notifiable notifiable.is_a?(ProposalNotification) ? notifiable.proposal : notifiable
end end
end end

View File

@@ -246,6 +246,7 @@ class User < ActiveRecord::Base
delegate :can?, :cannot?, to: :ability delegate :can?, :cannot?, to: :ability
private private
def clean_document_number def clean_document_number
self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank? self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank?
end end

View File

@@ -6,13 +6,17 @@
<span class="in_favor"> <span class="in_favor">
<% if can?(:vote, comment) %> <% if can?(:vote, comment) %>
<%= link_to vote_comment_path(comment, value: 'yes'), <%= link_to vote_comment_path(comment, value: 'yes'),
method: "post", remote: true do %> method: "post", remote: true, title: t('votes.agree') do %>
<span class="icon-angle-up"> <span class="icon-like">
<span class="sr-only"><%= t('votes.agree') %></span> <span class="sr-only"><%= t('votes.agree') %></span>
</span> </span>
<% end %> <% end %>
<% else %> <% else %>
<span class="icon-angle-up"></span> <%= link_to new_user_session_path do %>
<span class="icon-like">
<span class="sr-only"><%= t('votes.agree') %></span>
</span>
<% end %>
<% end %> <% end %>
<%= comment.total_likes %> <%= comment.total_likes %>
</span> </span>
@@ -20,13 +24,15 @@
<span class="against"> <span class="against">
<% if can?(:vote, comment) %> <% if can?(:vote, comment) %>
<%= link_to vote_comment_path(comment, value: 'no'), <%= link_to vote_comment_path(comment, value: 'no'),
method: "post", remote: true do %> method: "post", remote: true, title: t('votes.disagree') do %>
<span class="icon-angle-down"> <span class="icon-unlike">
<span class="sr-only"><%= t('votes.disagree') %></span> <span class="sr-only"><%= t('votes.disagree') %></span>
</span> </span>
<% end %> <% end %>
<% else %> <% else %>
<span class="icon-angle-down"></span> <span class="icon-unlike">
<span class="sr-only"><%= t('votes.disagree') %></span>
</span>
<% end %> <% end %>
<%= comment.total_dislikes %> <%= comment.total_dislikes %>
</span> </span>
@@ -40,26 +46,40 @@
<span class="in_favor"> <span class="in_favor">
<% if can?(:vote, comment) %> <% if can?(:vote, comment) %>
<%= link_to vote_comment_path(comment, value: 'yes'), <%= link_to vote_comment_path(comment, value: 'yes'),
method: "post", remote: true do %> method: "post", remote: true, title: t('votes.agree') do %>
<span class="icon-angle-up"></span> <span class="icon-like">
<span class="sr-only"><%= t('votes.agree') %></span>
</span>
<% end %> <% end %>
<% else %> <% else %>
<span class="icon-angle-up"></span> <%= link_to new_user_session_path do %>
<span class="icon-like">
<span class="sr-only"><%= t('votes.agree') %></span>
</span>
<% end %>
<% end %> <% end %>
<%= comment.total_likes %> <%= comment.total_likes %>
</span> </span>
<span class="against"> <span class="against">
<% if can?(:vote, comment) %> <% if can?(:vote, comment) %>
<%= link_to vote_comment_path(comment, value: 'no'), <%= link_to vote_comment_path(comment, value: 'no'),
method: "post", remote: true do %> method: "post", remote: true, title: t('votes.disagree') do %>
<span class="icon-angle-down"></span> <span class="icon-unlike">
<span class="sr-only"><%= t('votes.disagree') %></span>
</span>
<% end %> <% end %>
<% else %> <% else %>
<span class="icon-angle-down"></span> <%= link_to new_user_session_path do %>
<span class="icon-unlike">
<span class="sr-only"><%= t('votes.disagree') %></span>
</span>
<% end %>
<% end %> <% end %>
<%= comment.total_dislikes %> <%= comment.total_dislikes %>
</span> </span>
</div> </div>
<div class="participation-not-allowed" style='display:none' aria-hidden="false"> <div class="participation-not-allowed" style='display:none' aria-hidden="false">
<%= t("votes.comment_unauthenticated", <%= t("votes.comment_unauthenticated",
signin: link_to(t("votes.signin"), new_user_session_path), signin: link_to(t("votes.signin"), new_user_session_path),

View File

@@ -48,7 +48,7 @@
</div> </div>
</div> </div>
<div id="<%= dom_id(debate) %>_votes" class="small-12 medium-3 column text-center"> <div id="<%= dom_id(debate) %>_votes" class="small-12 medium-3 column">
<%= render 'debates/votes', debate: debate %> <%= render 'debates/votes', debate: debate %>
</div> </div>

View File

@@ -6,6 +6,8 @@
<% end %> <% end %>
<main> <main>
<h1 class="sr-only"><%= t("shared.outline.debates") %></h1>
<div class="row"> <div class="row">
<div id="debates" class="debates-list small-12 medium-9 column"> <div id="debates" class="debates-list small-12 medium-9 column">

View File

@@ -45,11 +45,9 @@
<aside class="small-12 medium-3 column"> <aside class="small-12 medium-3 column">
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h3><%= t("votes.supports") %></h3> <h3><%= t("votes.supports") %></h3>
<div class="text-center">
<div id="<%= dom_id(@debate) %>_votes"> <div id="<%= dom_id(@debate) %>_votes">
<%= render 'debates/votes', debate: @debate %> <%= render 'debates/votes', debate: @debate %>
</div> </div>
</div>
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h3><%= t("debates.show.share") %></h3> <h3><%= t("debates.show.share") %></h3>
<div class="social-share-full"> <div class="social-share-full">

View File

@@ -1,6 +1,7 @@
<%= paginator.render do -%> <%= paginator.render do -%>
<div class="pagination-centered"> <div class="pagination-centered">
<nav> <nav>
<h1 class="sr-only"><%= t("shared.outline.pagination") %></h1>
<ul class="pagination text-center margin-top" aria-label="Pagination"> <ul class="pagination text-center margin-top" aria-label="Pagination">
<%= first_page_tag unless current_page.first? %> <%= first_page_tag unless current_page.first? %>
<%= prev_page_tag unless current_page.first? %> <%= prev_page_tag unless current_page.first? %>

View File

@@ -22,6 +22,8 @@
<%= setting['per_page_code'].try(:html_safe) %> <%= setting['per_page_code'].try(:html_safe) %>
</head> </head>
<body> <body>
<h1 class="sr-only"><%= setting['org_name'] %></h1>
<div class="wrapper"> <div class="wrapper">
<%= render 'layouts/header' %> <%= render 'layouts/header' %>

View File

@@ -1,4 +1,4 @@
<div class="supports"> <div class="supports text-center">
<div class="in-favor"> <div class="in-favor">
<% if voted_for?(@featured_proposals_votes, proposal) %> <% if voted_for?(@featured_proposals_votes, proposal) %>
<div class="supported"> <div class="supported">

View File

@@ -52,26 +52,22 @@
</div> </div>
</div> </div>
<div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 column"> <div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 column supports-container">
<div class="supports text-center">
<% if proposal.successfull? %> <% if proposal.successfull? %>
<div class="message">
<p> <p>
<%= t("proposal_ballots.successfull", <%= t("proposal_ballots.successfull",
voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %> voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %>
</p> </p>
</div>
<% elsif proposal.archived? %> <% elsif proposal.archived? %>
<div class="message">
<strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong> <strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong>
<p><%= t("proposals.proposal.archived") %></p> <p><%= t("proposals.proposal.archived") %></p>
</div>
<% else %> <% else %>
<div class="text-center">
<%= render 'votes', <%= render 'votes',
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %> { proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %>
</div>
<% end %> <% end %>
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>

View File

@@ -1,24 +1,22 @@
<div class="supports"> <div class="progress small-12 round">
<div class="progress small-12 round">
<span class="meter" style="width: <%= progress_bar_percentage(proposal) %>%;"></span> <span class="meter" style="width: <%= progress_bar_percentage(proposal) %>%;"></span>
<span class="percentage"> <span class="percentage">
<%= supports_percentage(proposal) %>&nbsp;/&nbsp;<%= t("proposals.proposal.total_percent") %> <%= supports_percentage(proposal) %>&nbsp;/&nbsp;<%= t("proposals.proposal.total_percent") %>
</span> </span>
</div> </div>
<span class="total-supports"> <span class="total-supports">
<%= t("proposals.proposal.supports", count: proposal.total_votes) %>&nbsp; <%= t("proposals.proposal.supports", count: proposal.total_votes) %>&nbsp;
<span> <span>
<abbr title="<%= t("proposals.proposal.reason_for_supports_necessary") %>"> <abbr title="<%= t("proposals.proposal.reason_for_supports_necessary") %>">
<%= t("proposals.proposal.supports_necessary", number: number_with_delimiter(Proposal.votes_needed_for_success)) %> <%= t("proposals.proposal.supports_necessary", number: number_with_delimiter(Proposal.votes_needed_for_success)) %>
</abbr> </abbr>
</span> </span>
</span> </span>
<div class="in-favor"> <div class="in-favor">
<% if voted_for?(@proposal_votes, proposal) %> <% if voted_for?(@proposal_votes, proposal) %>
<div class="supported"> <div class="supported callout success">
<%= t("proposals.proposal.already_supported") %> <%= t("proposals.proposal.already_supported") %>
</div> </div>
<% else %> <% else %>
@@ -28,32 +26,31 @@
<%= t("proposals.proposal.support") %> <%= t("proposals.proposal.support") %>
<% end %> <% end %>
<% end %> <% end %>
</div> </div>
<% if user_signed_in? && current_user.organization? %> <% if user_signed_in? && current_user.organization? %>
<div class="participation-not-allowed" style='display:none' aria-hidden="false"> <div class="participation-not-allowed" style='display:none' aria-hidden="false">
<p> <p>
<%= t("votes.organizations") %> <%= t("votes.organizations") %>
</p> </p>
</div> </div>
<% elsif user_signed_in? && !proposal.votable_by?(current_user)%> <% elsif user_signed_in? && !proposal.votable_by?(current_user)%>
<div class="participation-not-allowed" style='display:none' aria-hidden="false"> <div class="participation-not-allowed" style='display:none' aria-hidden="false">
<p> <p>
<%= t("votes.verified_only", <%= t("votes.verified_only",
verify_account: link_to(t("votes.verify_account"), verification_path )).html_safe %> verify_account: link_to(t("votes.verify_account"), verification_path )).html_safe %>
</p> </p>
</div> </div>
<% elsif !user_signed_in? %> <% elsif !user_signed_in? %>
<div class="participation-not-allowed" style='display:none' aria-hidden="false"> <div class="participation-not-allowed" style='display:none' aria-hidden="false">
<%= t("votes.unauthenticated", <%= t("votes.unauthenticated",
signin: link_to(t("votes.signin"), new_user_session_path), signin: link_to(t("votes.signin"), new_user_session_path),
signup: link_to(t("votes.signup"), new_user_registration_path)).html_safe %> signup: link_to(t("votes.signup"), new_user_registration_path)).html_safe %>
</div> </div>
<% end %> <% end %>
<% if voted_for?(@proposal_votes, proposal) && setting['twitter_handle'] %> <% if voted_for?(@proposal_votes, proposal) && setting['twitter_handle'] %>
<div class="share-supported"> <div class="share-supported">
<%= social_share_button_tag("#{proposal.title} #{setting['twitter_hashtag']}", url: proposal_url(proposal), via: setting['twitter_handle']) %> <%= social_share_button_tag("#{proposal.title} #{setting['twitter_hashtag']}", url: proposal_url(proposal), via: setting['twitter_handle']) %>
</div> </div>
<% end %> <% end %>
</div>

View File

@@ -6,6 +6,8 @@
<% end %> <% end %>
<main> <main>
<h1 class="sr-only"><%= t("shared.outline.proposals") %></h1>
<div class="row"> <div class="row">
<div id="proposals" class="proposals-list small-12 medium-9 column"> <div id="proposals" class="proposals-list small-12 medium-9 column">

View File

@@ -102,22 +102,20 @@
<aside class="small-12 medium-3 column"> <aside class="small-12 medium-3 column">
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h3><%= t("votes.supports") %></h3> <h3><%= t("votes.supports") %></h3>
<div id="<%= dom_id(@proposal) %>_votes"> <div id="<%= dom_id(@proposal) %>_votes" class="supports text-center">
<% if @proposal.successfull? %> <% if @proposal.successfull? %>
<p> <p>
<%= t("proposal_ballots.successfull", <%= t("proposal_ballots.successfull",
voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %> voting: link_to(t("proposal_ballots.voting"), proposal_ballots_path)).html_safe %>
</p> </p>
<% elsif @proposal.archived? %> <% elsif @proposal.archived? %>
<p class="text-center"> <p>
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong> <strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
</p> </p>
<p><%= t("proposals.proposal.archived") %></p> <p><%= t("proposals.proposal.archived") %></p>
<% else %> <% else %>
<div class="text-center">
<%= render 'votes', <%= render 'votes',
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %> { proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
</div>
<% end %> <% end %>
</div> </div>
<div id="social-share" class="sidebar-divider"></div> <div id="social-share" class="sidebar-divider"></div>

View File

@@ -1,7 +1,9 @@
<section class="submenu"> <div class="submenu">
<% valid_orders.each do |order| %> <% valid_orders.each do |order| %>
<%= link_to t("#{i18n_namespace}.orders.#{order}"), <%= link_to current_path_with_query_params(order: order, page: 1), class: order == @current_order ? 'active' : '' do %>
current_path_with_query_params(order: order, page: 1), <%= content_tag(order == @current_order ? :h2 : :span) do %>
class: order == @current_order ? 'active' : '' %> <%= t("#{i18n_namespace}.orders.#{order}") %>
<% end %> <% end %>
</section> <% end %>
<% end %>
</div>

View File

@@ -1,4 +1,5 @@
<div id="search_form" class="search-form-header"> <div id="search_form" class="search-form-header">
<h1 class="sr-only"><%= t("shared.outline.searcher") %></h1>
<%= form_tag search_path, method: :get do %> <%= form_tag search_path, method: :get do %>
<div class="input-group"> <div class="input-group">
<label class="sr-only"><%= t("#{i18n_namespace}.title") %></label> <label class="sr-only"><%= t("#{i18n_namespace}.title") %></label>

View File

@@ -1,8 +1,7 @@
<section class="top-links hide-for-small-only"> <div class="top-links hide-for-small-only">
<div class="row"> <div class="row">
<%= render "shared/locale_switcher" %> <%= render "shared/locale_switcher" %>
<div class="external-links"> <div class="external-links">
<%= link_to setting['org_name'], root_path, class: ("selected" unless current_page?("/opendata")) %>&nbsp;|
<%= link_to t("layouts.header.external_link_transparency"), t("layouts.header.external_link_transparency_url") %>&nbsp;| <%= link_to t("layouts.header.external_link_transparency"), t("layouts.header.external_link_transparency_url") %>&nbsp;|
<%= link_to t("layouts.header.external_link_opendata"), "/opendata", class: ("selected" if current_page?("/opendata")) %> <%= link_to t("layouts.header.external_link_opendata"), "/opendata", class: ("selected" if current_page?("/opendata")) %>
<% if setting['blog_url'] %> <% if setting['blog_url'] %>
@@ -13,4 +12,4 @@
<% end %> <% end %>
</div> </div>
</div> </div>
</section> </div>

View File

@@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<div id="<%= dom_id(spending_proposal) %>_votes" class="small-12 medium-3 column text-center"> <div id="<%= dom_id(spending_proposal) %>_votes" class="small-12 medium-3 column supports-container">
<%= render 'votes', <%= render 'votes',
{ spending_proposal: spending_proposal, vote_url: vote_spending_proposal_path(spending_proposal, value: 'yes') } %> { spending_proposal: spending_proposal, vote_url: vote_spending_proposal_path(spending_proposal, value: 'yes') } %>
</div> </div>

View File

@@ -1,4 +1,4 @@
<div class="supports"> <div class="supports text-center">
<% reason = spending_proposal.reason_for_not_being_votable_by(current_user) %> <% reason = spending_proposal.reason_for_not_being_votable_by(current_user) %>
<% voting_allowed = true unless reason.presence == :not_voting_allowed %> <% voting_allowed = true unless reason.presence == :not_voting_allowed %>
@@ -10,7 +10,7 @@
<div class="in-favor"> <div class="in-favor">
<% if user_voted_for %> <% if user_voted_for %>
<div class="supported"> <div class="supported callout success">
<%= t("spending_proposals.spending_proposal.already_supported") %> <%= t("spending_proposals.spending_proposal.already_supported") %>
</div> </div>
<% elsif voting_allowed %> <% elsif voting_allowed %>

View File

@@ -6,6 +6,8 @@
<% end %> <% end %>
<main> <main>
<h1 class="sr-only"><%= t("shared.outline.budget") %></h1>
<div class="row"> <div class="row">
<div id="investment-projects" class="investment-projects-list small-12 medium-9 column"> <div id="investment-projects" class="investment-projects-list small-12 medium-9 column">

View File

@@ -343,7 +343,7 @@ en:
other: "%{count} comments" other: "%{count} comments"
zero: No comments zero: No comments
proposal: Proposal proposal: Proposal
reason_for_supports_necessary: 2% of Census reason_for_supports_necessary: 1% of Census
support: Support support: Support
support_title: Support this proposal support_title: Support this proposal
supports: supports:
@@ -449,6 +449,12 @@ en:
categories: "Categories" categories: "Categories"
target_blank_html: " (link opens in new window)" target_blank_html: " (link opens in new window)"
unflag: Unflag unflag: Unflag
outline:
debates: Debates
proposals: Proposals
budget: Participatory budget
pagination: Pagination
searcher: Searcher
social: social:
blog: Blog blog: Blog
facebook: Facebook facebook: Facebook

View File

@@ -343,7 +343,7 @@ es:
other: "%{count} Comentarios" other: "%{count} Comentarios"
zero: Sin comentarios zero: Sin comentarios
proposal: Propuesta proposal: Propuesta
reason_for_supports_necessary: 2% del Censo reason_for_supports_necessary: 1% del Censo
support: Apoyar support: Apoyar
support_title: Apoyar esta propuesta support_title: Apoyar esta propuesta
supports: supports:
@@ -449,6 +449,12 @@ es:
categories: "Categorías" categories: "Categorías"
target_blank_html: " (se abre en ventana nueva)" target_blank_html: " (se abre en ventana nueva)"
unflag: Deshacer denuncia unflag: Deshacer denuncia
outline:
debates: Debates
proposals: Propuestas
budget: Presupuestos ciudadanos
pagination: Paginación
searcher: Buscador
social: social:
blog: Blog blog: Blog
facebook: Facebook facebook: Facebook

View File

@@ -1316,7 +1316,7 @@ fr:
other: "%{count} commentaires" other: "%{count} commentaires"
zero: Aucun commentaire zero: Aucun commentaire
proposal: Proposition proposal: Proposition
reason_for_supports_necessary: 2% du Recensement reason_for_supports_necessary: 1% du Recensement
support: Soutenir support: Soutenir
supports: supports:
one: 1 soutien one: 1 soutien

View File

@@ -39,7 +39,7 @@ en:
The proposals can be supported by every citizen registered that has verified their account in the participation platform. In this way, the citizenship, and not someone in its name, will decide which are the proposals that are worthwhile to carry out. The proposals can be supported by every citizen registered that has verified their account in the participation platform. In this way, the citizenship, and not someone in its name, will decide which are the proposals that are worthwhile to carry out.
One that the proposal has achive support of 2% census, it will be studied by a city council group and to move beyond the popular referendum phase, in which citizenship will vote if it is carried out or not. The maximum period to obtain support enough is 12 months. One that the proposal has achive support of 1% census, it will be studied by a city council group and to move beyond the popular referendum phase, in which citizenship will vote if it is carried out or not. The maximum period to obtain support enough is 12 months.
how_to_use: how_to_use:
text: |- text: |-
Use it in your local government or help us to improve it, it is free software. Use it in your local government or help us to improve it, it is free software.

View File

@@ -39,7 +39,7 @@ es:
Las propuestas pueden ser apoyadas por ciudadanos empadronados que hayan verificado su cuenta en la plataforma de participación, de tal manera que será la propia ciudadanía, y nadie en su nombre, la que decida cuáles son las propuestas que merecen la pena ser llevadas a cabo. Las propuestas pueden ser apoyadas por ciudadanos empadronados que hayan verificado su cuenta en la plataforma de participación, de tal manera que será la propia ciudadanía, y nadie en su nombre, la que decida cuáles son las propuestas que merecen la pena ser llevadas a cabo.
Una vez que una propuesta alcance una cantidad de apoyos equivalente al 2% del censo, automáticamente pasa a ser estudiada por un grupo de trabajo del Ayuntamiento y pasará a la siguiente fase de consulta popular, en la que la ciudadanía votará si se lleva a cabo o no. El plazo máximo para recabar los apoyos necesarios será de 12 meses. Una vez que una propuesta alcance una cantidad de apoyos equivalente al 1% del censo, automáticamente pasa a ser estudiada por un grupo de trabajo del Ayuntamiento y pasará a la siguiente fase de consulta popular, en la que la ciudadanía votará si se lleva a cabo o no. El plazo máximo para recabar los apoyos necesarios será de 12 meses.
how_to_use: how_to_use:
text: |- text: |-
Utilízalo en tu municipio libremente o ayúdanos a mejorarlo, es software libre. Utilízalo en tu municipio libremente o ayúdanos a mejorarlo, es software libre.

View File

@@ -1214,8 +1214,8 @@ pt-BR:
podem ser apoiadas por todos os cidadãos registrados em Madrid que verificaram podem ser apoiadas por todos os cidadãos registrados em Madrid que verificaram
a sua conta na plataforma de participação. Desta forma, a cidadania e não a sua conta na plataforma de participação. Desta forma, a cidadania e não
alguém em seu nome, irá decidir quais são as propostas que valem a pena alguém em seu nome, irá decidir quais são as propostas que valem a pena
levar a cabo.\r\n\r\nAssim que a proposta atingir o apoio de 2% Madrid recenseada levar a cabo.\r\n\r\nAssim que a proposta atingir o apoio de 1% Madrid recenseada
(cerca de 53.000 pessoas), será estudado por um grupo conselheiro da cidade, (cerca de 28.000 pessoas), será estudado por um grupo conselheiro da cidade,
avançar além da fase de consulta popular, em que a cidadania de Madrid vai avançar além da fase de consulta popular, em que a cidadania de Madrid vai
votar se a proposta será realizada ou não. O prazo máximo para obter apoio votar se a proposta será realizada ou não. O prazo máximo para obter apoio
suficiente é de 12 meses." suficiente é de 12 meses."
@@ -1339,7 +1339,7 @@ pt-BR:
other: "%{count} comentários" other: "%{count} comentários"
zero: Nenhum comentário zero: Nenhum comentário
proposal: Proposta proposal: Proposta
reason_for_supports_necessary: 2% do Censo reason_for_supports_necessary: 1% do Censo
support: Apoiar support: Apoiar
supports: supports:
one: 1 apoio one: 1 apoio

View File

@@ -80,11 +80,11 @@ end
(1..40).each do |i| (1..40).each do |i|
user = create_user("user#{i}@consul.dev") user = create_user("user#{i}@consul.dev")
level = [1,2,3].sample level = [1, 2, 3].sample
if level >= 2 then if level >= 2
user.update(residence_verified_at: Time.now, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: Faker::Number.number(10), document_type: "1" ) user.update(residence_verified_at: Time.now, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: Faker::Number.number(10), document_type: "1" )
end end
if level == 3 then if level == 3
user.update(verified_at: Time.now, document_number: Faker::Number.number(10) ) user.update(verified_at: Time.now, document_number: Faker::Number.number(10) )
end end
end end
@@ -113,7 +113,7 @@ ActsAsTaggableOn::Tag.create!(name: "Medio Ambiente", featured: true, kind: "ca
puts "Creating Debates" puts "Creating Debates"
tags = Faker::Lorem.words(25) tags = Faker::Lorem.words(25)
(1..30).each do |i| (1..30).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>" description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
debate = Debate.create!(author: author, debate = Debate.create!(author: author,
@@ -128,7 +128,7 @@ end
tags = ActsAsTaggableOn::Tag.where(kind: 'category') tags = ActsAsTaggableOn::Tag.where(kind: 'category')
(1..30).each do |i| (1..30).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>" description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
debate = Debate.create!(author: author, debate = Debate.create!(author: author,
@@ -165,7 +165,7 @@ end
puts "Creating Archived Proposals" puts "Creating Archived Proposals"
tags = Faker::Lorem.words(25) tags = Faker::Lorem.words(25)
(1..5).each do |i| (1..5).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>" description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
proposal = Proposal.create!(author: author, proposal = Proposal.create!(author: author,
@@ -185,7 +185,7 @@ end
tags = ActsAsTaggableOn::Tag.where(kind: 'category') tags = ActsAsTaggableOn::Tag.where(kind: 'category')
(1..30).each do |i| (1..30).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>" description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"
proposal = Proposal.create!(author: author, proposal = Proposal.create!(author: author,
@@ -205,7 +205,7 @@ end
puts "Commenting Debates" puts "Commenting Debates"
(1..100).each do |i| (1..100).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
debate = Debate.reorder("RANDOM()").first debate = Debate.reorder("RANDOM()").first
Comment.create!(user: author, Comment.create!(user: author,
@@ -229,7 +229,7 @@ end
puts "Commenting Comments" puts "Commenting Comments"
(1..200).each do |i| (1..200).each do
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
parent = Comment.reorder("RANDOM()").first parent = Comment.reorder("RANDOM()").first
Comment.create!(user: author, Comment.create!(user: author,
@@ -243,7 +243,7 @@ end
puts "Voting Debates, Proposals & Comments" puts "Voting Debates, Proposals & Comments"
(1..100).each do |i| (1..100).each do
voter = not_org_users.reorder("RANDOM()").first voter = not_org_users.reorder("RANDOM()").first
vote = [true, false].sample vote = [true, false].sample
debate = Debate.reorder("RANDOM()").first debate = Debate.reorder("RANDOM()").first
@@ -257,7 +257,7 @@ end
comment.vote_by(voter: voter, vote: vote) comment.vote_by(voter: voter, vote: vote)
end end
(1..100).each do |i| (1..100).each do
voter = User.level_two_or_three_verified.reorder("RANDOM()").first voter = User.level_two_or_three_verified.reorder("RANDOM()").first
proposal = Proposal.reorder("RANDOM()").first proposal = Proposal.reorder("RANDOM()").first
proposal.vote_by(voter: voter, vote: true) proposal.vote_by(voter: voter, vote: true)
@@ -266,19 +266,19 @@ end
puts "Flagging Debates & Comments" puts "Flagging Debates & Comments"
(1..40).each do |i| (1..40).each do
debate = Debate.reorder("RANDOM()").first debate = Debate.reorder("RANDOM()").first
flagger = User.where(["users.id <> ?", debate.author_id]).reorder("RANDOM()").first flagger = User.where(["users.id <> ?", debate.author_id]).reorder("RANDOM()").first
Flag.flag(flagger, debate) Flag.flag(flagger, debate)
end end
(1..40).each do |i| (1..40).each do
comment = Comment.reorder("RANDOM()").first comment = Comment.reorder("RANDOM()").first
flagger = User.where(["users.id <> ?", comment.user_id]).reorder("RANDOM()").first flagger = User.where(["users.id <> ?", comment.user_id]).reorder("RANDOM()").first
Flag.flag(flagger, comment) Flag.flag(flagger, comment)
end end
(1..40).each do |i| (1..40).each do
proposal = Proposal.reorder("RANDOM()").first proposal = Proposal.reorder("RANDOM()").first
flagger = User.where(["users.id <> ?", proposal.author_id]).reorder("RANDOM()").first flagger = User.where(["users.id <> ?", proposal.author_id]).reorder("RANDOM()").first
Flag.flag(flagger, proposal) Flag.flag(flagger, proposal)
@@ -288,7 +288,7 @@ puts "Creating Spending Proposals"
tags = Faker::Lorem.words(10) tags = Faker::Lorem.words(10)
(1..60).each do |i| (1..60).each do
geozone = Geozone.reorder("RANDOM()").first geozone = Geozone.reorder("RANDOM()").first
author = User.reorder("RANDOM()").first author = User.reorder("RANDOM()").first
description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>" description = "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>"

View File

@@ -30,7 +30,6 @@ class DeviseCreateUsers < ActiveRecord::Migration
# t.string :unlock_token # Only if unlock strategy is :email or :both # t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at # t.datetime :locked_at
t.timestamps null: false t.timestamps null: false
end end

View File

@@ -1,12 +1,12 @@
class CreateSimpleCaptchaData < ActiveRecord::Migration class CreateSimpleCaptchaData < ActiveRecord::Migration
def self.up def self.up
create_table :simple_captcha_data do |t| create_table :simple_captcha_data do |t|
t.string :key, :limit => 40 t.string :key, limit: 40
t.string :value, :limit => 6 t.string :value, limit: 6
t.timestamps t.timestamps
end end
add_index :simple_captcha_data, :key, :name => "idx_key" add_index :simple_captcha_data, :key, name: "idx_key"
end end
def self.down def self.down

View File

@@ -6,7 +6,7 @@ class CreateTolkTables < ActiveRecord::Migration
t.datetime :updated_at t.datetime :updated_at
end end
add_index :tolk_locales, :name, :unique => true add_index :tolk_locales, :name, unique: true
create_table :tolk_phrases do |t| create_table :tolk_phrases do |t|
t.text :key t.text :key
@@ -19,17 +19,17 @@ class CreateTolkTables < ActiveRecord::Migration
t.integer :locale_id t.integer :locale_id
t.text :text t.text :text
t.text :previous_text t.text :previous_text
t.boolean :primary_updated, :default => false t.boolean :primary_updated, default: false
t.datetime :created_at t.datetime :created_at
t.datetime :updated_at t.datetime :updated_at
end end
add_index :tolk_translations, [:phrase_id, :locale_id], :unique => true add_index :tolk_translations, [:phrase_id, :locale_id], unique: true
end end
def self.down def self.down
remove_index :tolk_translations, :column => [:phrase_id, :locale_id] remove_index :tolk_translations, column: [:phrase_id, :locale_id]
remove_index :tolk_locales, :column => :name remove_index :tolk_locales, column: :name
drop_table :tolk_translations drop_table :tolk_translations
drop_table :tolk_phrases drop_table :tolk_phrases

View File

@@ -1,4 +1,5 @@
namespace :proposals do namespace :proposals do
desc "Updates all proposals by recalculating their hot_score" desc "Updates all proposals by recalculating their hot_score"
task touch: :environment do task touch: :environment do
Proposal.find_in_batches do |proposals| Proposal.find_in_batches do |proposals|

View File

@@ -1,4 +1,5 @@
namespace :spending_proposals do namespace :spending_proposals do
desc "Sends an email to the authors of unfeasible spending proposals" desc "Sends an email to the authors of unfeasible spending proposals"
task send_unfeasible_emails: :environment do task send_unfeasible_emails: :environment do
SpendingProposal.find_each do |spending_proposal| SpendingProposal.find_each do |spending_proposal|

View File

@@ -6,6 +6,7 @@ require 'rails_helper'
describe 'CustomizationEngine' do describe 'CustomizationEngine' do
let(:test_key) { I18n.t('account.show.change_credentials_link') } let(:test_key) { I18n.t('account.show.change_credentials_link') }
let!(:default_path) { I18n.load_path }
it "should load custom and override original locales" do it "should load custom and override original locales" do
I18n.load_path += Dir[Rails.root.join('spec', 'support', 'locales', 'custom', '*.{rb,yml}')] I18n.load_path += Dir[Rails.root.join('spec', 'support', 'locales', 'custom', '*.{rb,yml}')]
@@ -19,4 +20,10 @@ describe 'CustomizationEngine' do
I18n.reload! I18n.reload!
expect(test_key).to eq 'Not overriden string with custom locales' expect(test_key).to eq 'Not overriden string with custom locales'
end end
after(:each) do
I18n.load_path = default_path
I18n.reload!
end
end end

View File

@@ -1,6 +1,7 @@
require 'rails_helper' require 'rails_helper'
feature 'Admin banners magement' do feature 'Admin banners magement' do
background do background do
login_as(create(:administrator).user) login_as(create(:administrator).user)
end end
@@ -124,8 +125,8 @@ feature 'Admin banners magement' do
fill_in 'banner_description', with: 'Edited text' fill_in 'banner_description', with: 'Edited text'
within('div#js-banner-style') do within('div#js-banner-style') do
expect(page).to have_selector('h2', :text => 'Modified title') expect(page).to have_selector('h2', text: 'Modified title')
expect(page).to have_selector('h3', :text => 'Edited text') expect(page).to have_selector('h3', text: 'Edited text')
end end
click_button 'Save changes' click_button 'Save changes'
@@ -139,13 +140,14 @@ feature 'Admin banners magement' do
end end
scenario 'Delete a banner' do scenario 'Delete a banner' do
banner1 = create(:banner, title: 'Ugly banner', create(:banner, title: 'Ugly banner',
description: 'Bad text', description: 'Bad text',
target_url: 'http://www.url.com', target_url: 'http://www.url.com',
style: 'banner-style.banner-one', style: 'banner-style.banner-one',
image: 'banner-img.banner-one', image: 'banner-img.banner-one',
post_started_at: (Time.now + 4.days), post_started_at: (Time.now + 4.days),
post_ended_at: (Time.now + 10.days)) post_ended_at: (Time.now + 10.days))
visit admin_root_path visit admin_root_path
within("#side_menu") do within("#side_menu") do

View File

@@ -60,4 +60,5 @@ feature 'Admin feature flags' do
expect(page).to have_link "Spending proposals" expect(page).to have_link "Spending proposals"
end end
end end
end end

View File

@@ -33,5 +33,5 @@ feature 'Admin managers' do
expect(page).to_not have_content @manager.name expect(page).to_not have_content @manager.name
end end
end end
end
end

View File

@@ -27,4 +27,5 @@ feature 'Admin settings' do
expect(page).to have_content 'Value updated' expect(page).to have_content 'Value updated'
end end
end end

View File

@@ -956,7 +956,6 @@ feature 'Debates' do
end end
end end
context 'Suggesting debates' do context 'Suggesting debates' do
scenario 'Shows up to 5 suggestions', :js do scenario 'Shows up to 5 suggestions', :js do
author = create(:user) author = create(:user)
@@ -1029,7 +1028,6 @@ feature 'Debates' do
end end
end end
scenario 'Index include featured debates' do scenario 'Index include featured debates' do
admin = create(:administrator) admin = create(:administrator)
login_as(admin.user) login_as(admin.user)

View File

@@ -25,7 +25,6 @@ feature 'Proposal ballots' do
successfull_proposals.each do |proposal| successfull_proposals.each do |proposal|
within("#proposal_#{proposal.id}_votes") do within("#proposal_#{proposal.id}_votes") do
expect(page).to_not have_css(".supports")
expect(page).to have_content "This proposal has reached the required supports" expect(page).to have_content "This proposal has reached the required supports"
end end
end end
@@ -37,7 +36,6 @@ feature 'Proposal ballots' do
successfull_proposals.each do |proposal| successfull_proposals.each do |proposal|
visit proposal_path(proposal) visit proposal_path(proposal)
within("#proposal_#{proposal.id}_votes") do within("#proposal_#{proposal.id}_votes") do
expect(page).to_not have_css(".supports")
expect(page).to have_content "This proposal has reached the required supports" expect(page).to have_content "This proposal has reached the required supports"
end end
end end

View File

@@ -723,7 +723,6 @@ feature 'Proposals' do
within("#proposals-list") do within("#proposals-list") do
archived_proposals.each do |proposal| archived_proposals.each do |proposal|
within("#proposal_#{proposal.id}_votes") do within("#proposal_#{proposal.id}_votes") do
expect(page).to_not have_css(".supports")
expect(page).to have_content "This proposal has been archived and can't collect supports" expect(page).to have_content "This proposal has been archived and can't collect supports"
end end
end end
@@ -734,7 +733,6 @@ feature 'Proposals' do
archived_proposal = create(:proposal, :archived) archived_proposal = create(:proposal, :archived)
visit proposal_path(archived_proposal) visit proposal_path(archived_proposal)
expect(page).to_not have_css(".supports")
expect(page).to have_content "This proposal has been archived and can't collect supports" expect(page).to have_content "This proposal has been archived and can't collect supports"
end end

View File

@@ -52,7 +52,6 @@ feature 'Users' do
uid: '12345', uid: '12345',
info: {name: 'manuela', email: 'manuelacarmena@example.com', verified: '1'}} } info: {name: 'manuela', email: 'manuelacarmena@example.com', verified: '1'}} }
scenario 'Sign up when Oauth provider has a verified email' do scenario 'Sign up when Oauth provider has a verified email' do
OmniAuth.config.add_mock(:twitter, twitter_hash_with_verified_email) OmniAuth.config.add_mock(:twitter, twitter_hash_with_verified_email)

View File

@@ -98,4 +98,5 @@ feature 'Verification path' do
expect(page).to have_content 'Your account is already verified' expect(page).to have_content 'Your account is already verified'
end end
end end
end end

View File

@@ -85,7 +85,7 @@ describe EmailDigest do
user = create(:user) user = create(:user)
proposal_notification = create(:proposal_notification) proposal_notification = create(:proposal_notification)
notification = create(:notification, notifiable: proposal_notification, user: user, emailed_at: Time.now) create(:notification, notifiable: proposal_notification, user: user, emailed_at: Time.now)
reset_mailer reset_mailer
email_digest = EmailDigest.new(user) email_digest = EmailDigest.new(user)

View File

@@ -651,28 +651,28 @@ describe Proposal do
context "no results" do context "no results" do
it "no words match" do it "no words match" do
proposal = create(:proposal, title: 'save world') create(:proposal, title: 'save world')
results = Proposal.search('destroy planet') results = Proposal.search('destroy planet')
expect(results).to eq([]) expect(results).to eq([])
end end
it "too many typos" do it "too many typos" do
proposal = create(:proposal, title: 'fantastic') create(:proposal, title: 'fantastic')
results = Proposal.search('frantac') results = Proposal.search('frantac')
expect(results).to eq([]) expect(results).to eq([])
end end
it "too much stemming" do it "too much stemming" do
proposal = create(:proposal, title: 'reloj') create(:proposal, title: 'reloj')
results = Proposal.search('superrelojimetro') results = Proposal.search('superrelojimetro')
expect(results).to eq([]) expect(results).to eq([])
end end
it "empty" do it "empty" do
proposal = create(:proposal, title: 'great') create(:proposal, title: 'great')
results = Proposal.search('') results = Proposal.search('')
expect(results).to eq([]) expect(results).to eq([])

View File

@@ -174,7 +174,7 @@ describe SpendingProposal do
by_valuator = SpendingProposal.by_valuator(valuator1.id) by_valuator = SpendingProposal.by_valuator(valuator1.id)
expect(by_valuator.size).to eq(2) expect(by_valuator.size).to eq(2)
expect(by_valuator.sort).to eq([spending_proposal1,spending_proposal3].sort) expect(by_valuator.sort).to eq([spending_proposal1, spending_proposal3].sort)
end end
end end

View File

@@ -9,7 +9,7 @@ RSpec.configure do |config|
config.filter_run :focus config.filter_run :focus
config.run_all_when_everything_filtered = true config.run_all_when_everything_filtered = true
config.include Devise::TestHelpers, :type => :controller config.include Devise::TestHelpers, type: :controller
config.include FactoryGirl::Syntax::Methods config.include FactoryGirl::Syntax::Methods
config.include(EmailSpec::Helpers) config.include(EmailSpec::Helpers)
config.include(EmailSpec::Matchers) config.include(EmailSpec::Matchers)

View File

@@ -159,4 +159,5 @@ shared_examples_for "verifiable" do
expect(user.verification_letter_sent?).to eq(false) expect(user.verification_letter_sent?).to eq(false)
end end
end end
end end