Merge branch 'master' into tracking_user_verifications_and_others

Conflicts:
	app/controllers/admin/stats_controller.rb
	db/dev_seeds.rb
This commit is contained in:
palomahnhp
2016-04-20 11:44:33 +02:00
134 changed files with 2193 additions and 433 deletions

View File

@@ -19,7 +19,7 @@ gem 'jquery-ui-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks' gem 'turbolinks'
gem 'devise', '~> 3.5.6' gem 'devise', '~> 3.5.7'
# Use ActiveModel has_secure_password # Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7' # gem 'bcrypt', '~> 3.1.7'
gem 'omniauth' gem 'omniauth'
@@ -39,7 +39,7 @@ gem 'ckeditor', '~> 4.1.5'
gem 'cancancan' gem 'cancancan'
gem 'social-share-button', git: 'https://github.com/huacnlee/social-share-button.git', ref: 'e46a6a3e82b86023bc' gem 'social-share-button', git: 'https://github.com/huacnlee/social-share-button.git', ref: 'e46a6a3e82b86023bc'
gem 'initialjs-rails', '0.2.0.1' gem 'initialjs-rails', '0.2.0.1'
gem 'unicorn', '~> 5.0.1' gem 'unicorn', '~> 5.1.0'
gem 'paranoia' gem 'paranoia'
gem 'rinku', require: 'rails_rinku' gem 'rinku', require: 'rails_rinku'
gem 'savon' gem 'savon'
@@ -52,13 +52,14 @@ gem 'newrelic_rpm', '~> 3.14'
gem 'whenever', require: false gem 'whenever', require: false
gem 'pg_search' gem 'pg_search'
gem 'ahoy_matey', '~> 1.2.1' gem 'ahoy_matey', '~> 1.4.0'
gem 'groupdate' # group temporary data gem 'groupdate' # group temporary data
gem 'tolk' # Web interface for translations gem 'tolk' # Web interface for translations
gem 'browser' gem 'browser'
gem 'turnout' gem 'turnout'
gem 'redcarpet' gem 'redcarpet'
group :development, :test do group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console # Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug' gem 'byebug'
@@ -73,7 +74,7 @@ group :development, :test do
gem 'quiet_assets' gem 'quiet_assets'
gem 'letter_opener_web', '~> 1.3.0' gem 'letter_opener_web', '~> 1.3.0'
gem 'i18n-tasks' gem 'i18n-tasks'
gem 'capistrano', '3.4.0', require: false gem 'capistrano', '3.4.1', require: false
gem "capistrano-bundler", '1.1.4', require: false gem "capistrano-bundler", '1.1.4', require: false
gem "capistrano-rails", '1.1.6', require: false gem "capistrano-rails", '1.1.6', require: false
gem "capistrano-rvm", require: false gem "capistrano-rvm", require: false

View File

@@ -49,14 +49,15 @@ GEM
activerecord (>= 3.2, < 5) activerecord (>= 3.2, < 5)
acts_as_votable (0.10.0) acts_as_votable (0.10.0)
addressable (2.4.0) addressable (2.4.0)
ahoy_matey (1.2.1) ahoy_matey (1.4.0)
addressable addressable
browser (>= 0.4.0) browser (~> 2.0)
errbase
geocoder geocoder
rails rack-attack
railties
referer-parser (>= 0.3.0) referer-parser (>= 0.3.0)
request_store request_store
safely_block
user_agent_parser user_agent_parser
uuidtools uuidtools
akami (1.3.1) akami (1.3.1)
@@ -70,15 +71,15 @@ GEM
babel-transpiler (0.7.0) babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6) babel-source (>= 4.0, < 6)
execjs (~> 2.0) execjs (~> 2.0)
bcrypt (3.1.10) bcrypt (3.1.11)
browser (1.1.0) browser (2.0.3)
builder (3.2.2) builder (3.2.2)
bullet (5.0.0) bullet (5.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.9.0) uniform_notifier (~> 1.9.0)
byebug (8.2.2) byebug (8.2.4)
cancancan (1.13.1) cancancan (1.13.1)
capistrano (3.4.0) capistrano (3.4.1)
i18n i18n
rake (>= 10.0.0) rake (>= 10.0.0)
sshkit (~> 1.3) sshkit (~> 1.3)
@@ -91,9 +92,9 @@ GEM
capistrano-rvm (0.1.2) capistrano-rvm (0.1.2)
capistrano (~> 3.0) capistrano (~> 3.0)
sshkit (~> 1.2) sshkit (~> 1.2)
capistrano3-delayed-job (1.6.0) capistrano3-delayed-job (1.7.0)
capistrano (>= 3.0.0) capistrano (>= 3.0.0)
capybara (2.6.2) capybara (2.7.0)
addressable addressable
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
@@ -125,14 +126,14 @@ GEM
tins (~> 1.6.0) tins (~> 1.6.0)
daemons (1.2.3) daemons (1.2.3)
dalli (2.7.6) dalli (2.7.6)
database_cleaner (1.5.1) database_cleaner (1.5.2)
debug_inspector (0.0.2) debug_inspector (0.0.2)
delayed_job (4.1.1) delayed_job (4.1.1)
activesupport (>= 3.0, < 5.0) activesupport (>= 3.0, < 5.0)
delayed_job_active_record (4.1.0) delayed_job_active_record (4.1.0)
activerecord (>= 3.0, < 5) activerecord (>= 3.0, < 5)
delayed_job (>= 3.0, < 5) delayed_job (>= 3.0, < 5)
devise (3.5.6) devise (3.5.7)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5) railties (>= 3.2.6, < 5)
@@ -154,16 +155,16 @@ GEM
errbase (0.0.3) errbase (0.0.3)
erubis (2.7.0) erubis (2.7.0)
execjs (2.6.0) execjs (2.6.0)
factory_girl (4.5.0) factory_girl (4.7.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
factory_girl_rails (4.6.0) factory_girl_rails (4.7.0)
factory_girl (~> 4.5.0) factory_girl (~> 4.7.0)
railties (>= 3.0.0) railties (>= 3.0.0)
faker (1.6.3) faker (1.6.3)
i18n (~> 0.5) i18n (~> 0.5)
faraday (0.9.2) faraday (0.9.2)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
foundation-rails (6.2.0.1) foundation-rails (6.2.1.0)
railties (>= 3.1.0) railties (>= 3.1.0)
sass (>= 3.3.0, < 3.5) sass (>= 3.3.0, < 3.5)
sprockets-es6 (>= 0.9.0) sprockets-es6 (>= 0.9.0)
@@ -176,7 +177,7 @@ GEM
fuubar (2.0.0) fuubar (2.0.0)
rspec (~> 3.0) rspec (~> 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
geocoder (1.3.1) geocoder (1.3.4)
globalid (0.3.6) globalid (0.3.6)
activesupport (>= 4.1.0) activesupport (>= 4.1.0)
groupdate (2.5.2) groupdate (2.5.2)
@@ -208,7 +209,7 @@ GEM
jquery-ui-rails (5.0.5) jquery-ui-rails (5.0.5)
railties (>= 3.2.16) railties (>= 3.2.16)
json (1.8.3) json (1.8.3)
jwt (1.5.3) jwt (1.5.4)
kaminari (0.16.3) kaminari (0.16.3)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
@@ -223,9 +224,11 @@ GEM
railties (>= 3.2) railties (>= 3.2)
loofah (2.0.3) loofah (2.0.3)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
mail (2.6.3) mail (2.6.4)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 4)
mime-types (2.99.1) mime-types (3.0)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0221)
mini_portile2 (2.0.0) mini_portile2 (2.0.0)
minitest (5.8.4) minitest (5.8.4)
multi_json (1.11.2) multi_json (1.11.2)
@@ -233,8 +236,8 @@ GEM
multipart-post (2.0.0) multipart-post (2.0.0)
net-scp (1.2.1) net-scp (1.2.1)
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (3.0.2) net-ssh (3.1.1)
newrelic_rpm (3.15.0.314) newrelic_rpm (3.15.1.316)
nokogiri (1.6.7.2) nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2) mini_portile2 (~> 2.0.0.rc2)
nori (2.6.0) nori (2.6.0)
@@ -284,6 +287,8 @@ GEM
rack (1.6.4) rack (1.6.4)
rack-accept (0.4.5) rack-accept (0.4.5)
rack (>= 0.4) rack (>= 0.4)
rack-attack (4.4.1)
rack
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.2.6) rails (4.2.6)
@@ -310,12 +315,12 @@ GEM
activesupport (= 4.2.6) activesupport (= 4.2.6)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
raindrops (0.15.0) raindrops (0.16.0)
rake (11.1.1) rake (11.1.2)
redcarpet (3.3.4) redcarpet (3.3.4)
referer-parser (0.3.0) referer-parser (0.3.0)
request_store (1.3.0) request_store (1.3.1)
responders (2.1.1) responders (2.1.2)
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rinku (1.7.3) rinku (1.7.3)
rollbar (2.8.3) rollbar (2.8.3)
@@ -343,7 +348,9 @@ GEM
rspec-support (3.4.1) rspec-support (3.4.1)
ruby-progressbar (1.7.5) ruby-progressbar (1.7.5)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sass (3.4.21) safely_block (0.1.0)
errbase
sass (3.4.22)
sass-rails (5.0.4) sass-rails (5.0.4)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 5.0)
sass (~> 3.1) sass (~> 3.1)
@@ -365,10 +372,10 @@ GEM
json (~> 1.8) json (~> 1.8)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
simplecov-html (0.10.0) simplecov-html (0.10.0)
spring (1.6.4) spring (1.7.1)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
sprockets (3.5.2) sprockets (3.6.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-es6 (0.9.0) sprockets-es6 (0.9.0)
@@ -379,7 +386,7 @@ GEM
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sshkit (1.8.1) sshkit (1.9.0)
net-scp (>= 1.1.2) net-scp (>= 1.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
term-ansicolor (1.3.2) term-ansicolor (1.3.2)
@@ -395,17 +402,16 @@ GEM
safe_yaml (>= 0.8.6) safe_yaml (>= 0.8.6)
turbolinks (2.5.3) turbolinks (2.5.3)
coffee-rails coffee-rails
turnout (2.2.1) turnout (2.3.0)
rack (~> 1.3) rack (~> 1.3)
rack-accept (~> 0.4) rack-accept (~> 0.4)
tilt (>= 1.4, < 3)
tzinfo (1.2.2) tzinfo (1.2.2)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (2.7.2) uglifier (3.0.0)
execjs (>= 0.3.0) execjs (>= 0.3.0, < 3)
json (>= 1.8.0) unicorn (5.1.0)
unicorn (5.0.1)
kgio (~> 2.6) kgio (~> 2.6)
rack
raindrops (~> 0.7) raindrops (~> 0.7)
uniform_notifier (1.9.0) uniform_notifier (1.9.0)
user_agent_parser (2.3.0) user_agent_parser (2.3.0)
@@ -433,13 +439,13 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
acts-as-taggable-on acts-as-taggable-on
acts_as_votable acts_as_votable
ahoy_matey (~> 1.2.1) ahoy_matey (~> 1.4.0)
ancestry ancestry
browser browser
bullet bullet
byebug byebug
cancancan cancancan
capistrano (= 3.4.0) capistrano (= 3.4.1)
capistrano-bundler (= 1.1.4) capistrano-bundler (= 1.1.4)
capistrano-rails (= 1.1.6) capistrano-rails (= 1.1.6)
capistrano-rvm capistrano-rvm
@@ -452,7 +458,7 @@ DEPENDENCIES
dalli dalli
database_cleaner database_cleaner
delayed_job_active_record (~> 4.1.0) delayed_job_active_record (~> 4.1.0)
devise (~> 3.5.6) devise (~> 3.5.7)
devise-async devise-async
email_spec email_spec
factory_girl_rails factory_girl_rails
@@ -494,7 +500,7 @@ DEPENDENCIES
turbolinks turbolinks
turnout turnout
uglifier (>= 1.3.0) uglifier (>= 1.3.0)
unicorn (~> 5.0.1) unicorn (~> 5.1.0)
web-console (~> 3.0) web-console (~> 3.0)
whenever whenever

View File

@@ -48,7 +48,7 @@ bin/rails s
``` ```
Prerequisites for testing: install PhantomJS >= 2.0 Prerequisites for testing: install PhantomJS >= 1.9.8
Run the tests with: Run the tests with:
@@ -56,7 +56,23 @@ Run the tests with:
bin/rspec bin/rspec
``` ```
## Licence You can use the default admin user from the seeds file:
**user:** admin@madrid.es
**pass:** 12345678
But for some actions like voting, you will need a verified user, the seeds file also includes one:
**user:** verified@madrid.es
**pass:** 12345678
### OAuth
To test authentication services with external OAuth suppliers - right now Twitter, Facebook and Google - you'll need to create an "application" in each of the supported platforms and set the *key* and *secret* provided in your *secrets.yml*
In the case of Google, verify that the APIs *Contacts API* and *Google+ API* are enabled for the application.
## License
Code published under AFFERO GPL v3 (see [LICENSE-AGPLv3.txt](LICENSE-AGPLv3.txt)) Code published under AFFERO GPL v3 (see [LICENSE-AGPLv3.txt](LICENSE-AGPLv3.txt))

View File

@@ -47,7 +47,7 @@ Para ejecutar la aplicación en local:
bin/rails s bin/rails s
``` ```
Prerequisitos para los tests: tener instalado PhantomJS >= 2.0 Prerequisitos para los tests: tener instalado PhantomJS >= 1.9.8
Para ejecutar los tests: Para ejecutar los tests:
@@ -55,6 +55,17 @@ Para ejecutar los tests:
bin/rspec bin/rspec
``` ```
Puedes usar el usuario administrador por defecto del fichero seeds:
**user:** admin@madrid.es
**pass:** 12345678
Pero para ciertas acciones, como apoyar, necesitarás un usuario verificado, el fichero seeds proporciona uno:
**user:** verified@madrid.es
**pass:** 12345678
### OAuth ### OAuth
Para probar los servicios de autenticación mediante proveedores externos OAuth — en este momento Twitter, Facebook y Google —, necesitas crear una "aplicación" en cada una de las plataformas soportadas y configurar la *key* y el *secret* proporcionados en tu *secrets.yml* Para probar los servicios de autenticación mediante proveedores externos OAuth — en este momento Twitter, Facebook y Google —, necesitas crear una "aplicación" en cada una de las plataformas soportadas y configurar la *key* y el *secret* proporcionados en tu *secrets.yml*

Binary file not shown.

View File

@@ -48,4 +48,5 @@
<glyph glyph-name="budget" unicode="&#83;" d="M33 256l223 0 0 223c-5 1-11 1-16 1-115 0-208-93-208-208 0-5 0-11 1-16z m77-146c38-48 96-78 162-78 115 0 208 93 208 208 0 66-30 124-78 162-31 26-71 42-114 45l0-223-223 0c3-43 19-83 45-114z"/> <glyph glyph-name="budget" unicode="&#83;" d="M33 256l223 0 0 223c-5 1-11 1-16 1-115 0-208-93-208-208 0-5 0-11 1-16z m77-146c38-48 96-78 162-78 115 0 208 93 208 208 0 66-30 124-78 162-31 26-71 42-114 45l0-223-223 0c3-43 19-83 45-114z"/>
<glyph glyph-name="notification" unicode="&#110;" d="M256 48c23 0 41 19 41 42l-82 0c0-23 18-42 41-42z m135 125l0 114c0 64-45 118-104 131l0 15c0 17-13 31-31 31-18 0-31-14-31-31l0-15c-59-13-104-67-104-131l0-114-41-42 0-21 352 0 0 21z"/> <glyph glyph-name="notification" unicode="&#110;" d="M256 48c23 0 41 19 41 42l-82 0c0-23 18-42 41-42z m135 125l0 114c0 64-45 118-104 131l0 15c0 17-13 31-31 31-18 0-31-14-31-31l0-15c-59-13-104-67-104-131l0-114-41-42 0-21 352 0 0 21z"/>
<glyph glyph-name="no-notification" unicode="&#120;" d="M257 392c7 0 24-5 24-5 46-10 78-52 78-100l0-127 9-10 8-8-240 0 8 8 9 10 0 127c0 48 33 90 78 100 0 0 18 5 24 5m1 72c-18 0-31-14-31-31l0-15c-59-13-104-67-104-131l0-114-41-42 0-21 352 0 0 21-41 42 0 114c0 64-45 118-104 131l0 15c0 17-13 31-31 31z m41-374l-82 0c0-23 18-42 41-42 23 0 41 19 41 42z"/> <glyph glyph-name="no-notification" unicode="&#120;" d="M257 392c7 0 24-5 24-5 46-10 78-52 78-100l0-127 9-10 8-8-240 0 8 8 9 10 0 127c0 48 33 90 78 100 0 0 18 5 24 5m1 72c-18 0-31-14-31-31l0-15c-59-13-104-67-104-131l0-114-41-42 0-21 352 0 0 21-41 42 0 114c0 64-45 118-104 131l0 15c0 17-13 31-31 31z m41-374l-82 0c0-23 18-42 41-42 23 0 41 19 41 42z"/>
<glyph glyph-name="whatsapp" unicode="&#80;" d="M318 234c2 0 12-4 28-13 16-8 24-13 25-15 1-1 1-2 1-4 0-7-2-14-5-22-3-7-10-14-20-19-11-5-20-7-29-7-11 0-29 6-55 17-18 9-34 20-48 34-14 14-28 32-42 53-14 20-21 39-21 55l0 3c1 17 8 32 21 45 5 4 10 6 15 6 1 0 3 0 5 0 3-1 5-1 6-1 3 0 6 0 7-2 2-1 3-3 5-7 1-4 5-13 9-26 5-13 7-20 7-21 0-4-3-9-9-16-7-7-10-12-10-14 0-1 0-2 1-4 7-14 16-27 29-39 11-10 25-20 43-29 3-1 5-2 7-2 3 0 8 5 15 14 8 9 13 14 15 14z m-58-152c24 0 47 5 70 15 22 9 41 22 57 38 16 16 29 35 38 57 10 22 14 46 14 70 0 24-4 47-14 69-9 22-22 42-38 58-16 16-35 28-57 38-23 9-46 14-70 14-24 0-47-5-70-14-22-10-41-22-57-38-16-16-29-36-38-58-10-22-14-45-14-69 0-39 11-74 34-105l-23-67 69 22c31-20 63-30 99-30z m0 395c29 0 57-6 84-17 26-11 49-27 68-46 20-19 35-42 46-69 12-26 17-54 17-83 0-29-5-57-17-84-11-26-26-49-46-69-19-19-42-34-68-46-27-11-55-17-84-17-37 0-72 9-104 27l-119-38 38 116c-20 33-30 71-30 111 0 29 5 57 17 83 11 27 26 50 46 69 19 19 42 35 68 46 27 11 55 17 84 17z"/>
</font></defs></svg> </font></defs></svg>

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -43,6 +43,7 @@
//= require forms //= require forms
//= require tracks //= require tracks
//= require valuation_spending_proposal_form //= require valuation_spending_proposal_form
//= require embed_video
var initialize_modules = function() { var initialize_modules = function() {
App.Comments.initialize(); App.Comments.initialize();
@@ -61,6 +62,7 @@ var initialize_modules = function() {
App.Forms.initialize(); App.Forms.initialize();
App.Tracks.initialize(); App.Tracks.initialize();
App.ValuationSpendingProposalForm.initialize(); App.ValuationSpendingProposalForm.initialize();
App.EmbedVideo.initialize();
}; };
$(function(){ $(function(){

View File

@@ -0,0 +1,7 @@
App.EmbedVideo =
initialize: ->
$('#js-embedded-video').each ->
code = $(this).data("video-code")
$('#js-embedded-video').html(code)

View File

@@ -5,11 +5,13 @@ App.Votes =
$("div.anonymous-votes", votes).show(); $("div.anonymous-votes", votes).show();
$("div.organizations-votes", votes).show(); $("div.organizations-votes", votes).show();
$("div.not-logged", votes).show(); $("div.not-logged", votes).show();
$("div.no-supports-allowed", votes).show();
$("div.logged", votes).hide(); $("div.logged", votes).hide();
, -> , ->
$("div.anonymous-votes", votes).hide(); $("div.anonymous-votes", votes).hide();
$("div.organizations-votes", votes).hide(); $("div.organizations-votes", votes).hide();
$("div.not-logged", votes).hide(); $("div.not-logged", votes).hide();
$("div.no-supports-allowed", votes).hide();
$("div.logged", votes).show(); $("div.logged", votes).show();
initialize: -> initialize: ->

View File

@@ -116,7 +116,7 @@ body.admin {
[class^="icon-"] { [class^="icon-"] {
display: inline-block; display: inline-block;
font-size: rem-calc(24); font-size: rem-calc(24);
padding-right: rem-calc(24); padding-right: rem-calc(12);
padding-top: rem-calc(4); padding-top: rem-calc(4);
padding-left: 12px\9 !important; padding-left: 12px\9 !important;
padding-right: 12px\9 !important; padding-right: 12px\9 !important;
@@ -349,3 +349,22 @@ body.admin {
margin-bottom: 0; margin-bottom: 0;
} }
body.admin {
.investment-projects-list.medium-9 {
width: 100%;
}
}
.admin-content .select-geozone {
a {
display: block;
&.active {
color: $brand;
font-weight: bold;
text-decoration: underline;
}
}
}

View File

@@ -160,3 +160,6 @@
.icon-no-notification:before { .icon-no-notification:before {
content: "\78"; content: "\78";
} }
.icon-whatsapp:before {
content: "\50";
}

View File

@@ -164,10 +164,12 @@
.progress { .progress {
background-color: rgba(255,255,255,.8); background-color: rgba(255,255,255,.8);
height: rem-calc(12); height: $line-height/2;
.meter { .meter {
background: $votes-like; background: $votes-like;
display: block;
height: $line-height/2;
} }
} }
@@ -238,7 +240,7 @@
} }
} }
.anonymous-votes, .organizations-votes { .anonymous-votes, .organizations-votes, .no-supports-allowed {
background: $warning-bg; background: $warning-bg;
color: $warning-color; color: $warning-color;
height: 100%; height: 100%;
@@ -274,7 +276,7 @@
.debate-new, .debate-edit, .debate-new, .debate-edit,
.proposal-new, .proposal-edit, .proposal-new, .proposal-edit,
.spending-proposal-new, .spending-proposal-edit { .spending-proposal-new, .spending-proposal-edit {
.back { .back {
@include back; @include back;
@@ -335,13 +337,30 @@
// 03. Show participation // 03. Show participation
// - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - -
.debate-show, .proposal-show { .debate-show, .proposal-show, .investment-project-show {
p {
word-wrap: break-word;
}
.social-share-full .social-share-button {
display:inline;
}
.whatsapp:before {
background-color: #43d854;
color: white;
font-size: 1.7em;
margin-left: rem-calc(0.5);
padding: rem-calc(9.5) rem-calc(9.8);
vertical-align: rem-calc(10);
}
.edit-debate, .edit-proposal { .edit-debate, .edit-proposal {
margin-bottom: 0; margin-bottom: 0;
} }
.debate-info, .proposal-info { .debate-info, .proposal-info, .investment-project-info {
clear: both; clear: both;
color: $text-medium; color: $text-medium;
font-size: $small-font-size; font-size: $small-font-size;
@@ -532,7 +551,7 @@
} }
} }
.debate, .proposal { .debate, .proposal, .investment-project {
margin-bottom: 0; margin-bottom: 0;
margin-top: 0; margin-top: 0;
@@ -551,7 +570,7 @@
padding-bottom: rem-calc(12); padding-bottom: rem-calc(12);
} }
.label-debate, .label-proposal { .label-debate, .label-proposal, .label-investment-project {
background: none; background: none;
clear: both; clear: both;
display: block; display: block;
@@ -573,6 +592,10 @@
color: $proposals; color: $proposals;
} }
.label-investment-project {
color: $budget;
}
h3 { h3 {
font-weight: bold; font-weight: bold;
margin: 0; margin: 0;
@@ -582,7 +605,7 @@
} }
} }
.debate-content, .proposal-content { .debate-content, .proposal-content, .investment-project-content {
margin: 0; margin: 0;
min-height: rem-calc(180); min-height: rem-calc(180);
position: relative; position: relative;
@@ -592,24 +615,27 @@
} }
} }
.icon-debates, .icon-proposals { .icon-debates, .icon-proposals, .icon-budget {
font-size: rem-calc(18); font-size: rem-calc(18);
line-height: $line-height; line-height: $line-height;
position: absolute; margin-left: rem-calc(6);
top: 0; top: 0;
} }
.icon-debates { .icon-debates {
color: $debates; color: $debates;
left: rem-calc(48);
} }
.icon-proposals { .icon-proposals {
color: $proposals; color: $proposals;
left: rem-calc(72);
} }
.debate-info, .proposal-info { .icon-budget {
color: $budget;
font-size: $small-font-size;
}
.debate-info, .proposal-info, .investment-project-info {
color: $text-medium; color: $text-medium;
font-size: $small-font-size; font-size: $small-font-size;
margin: rem-calc(6) 0 0; margin: rem-calc(6) 0 0;
@@ -624,7 +650,7 @@
} }
} }
.debate-description, .proposal-description { .debate-description, .proposal-description, .investment-project-description {
color: $text; color: $text;
font-size: rem-calc(13); font-size: rem-calc(13);
height: rem-calc(72); height: rem-calc(72);
@@ -785,6 +811,62 @@
} }
} }
.investment-project, .investment-project-show {
.supports {
@include supports;
background: none;
border: 0;
border-left: 1px solid $border;
margin: 0 rem-calc(-12);
min-height: rem-calc(180);
padding-top: $line-height*2;
&:after {
content: none;
}
.button-support {
background: $budget;
color: white;
&:hover {
background: $budget-hover;
color: white;
cursor: pointer;
}
&:active {
opacity: .75;
}
}
.total-supports {
color: $budget;
font-size: $base-font-size;
font-weight: bold;
}
.supported {
color: $budget;
}
.no-supports-allowed {
background: rgba(69,67,114,.96);
color: white;
padding: rem-calc(12);
}
.no-supports-allowed p, .no-supports-allowed a {
color: white;
}
}
}
.investment-project-show .supports {
border: 0;
}
.proposals-summary { .proposals-summary {
.panel { .panel {
@@ -792,6 +874,12 @@
} }
} }
.investment-project .supports .total-supports.no-button,
.investment-project-show .supports .total-supports.no-button {
display: block;
margin-top: $line-height*1.5;
}
// 05. Featured // 05. Featured
// - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@@ -74,6 +74,7 @@ $proposals: #FFA42D;
$proposals-border: #CC8425; $proposals-border: #CC8425;
$budget: #454372; $budget: #454372;
$budget-hover: #7571BF;
$highlight: #E7F2FC; $highlight: #E7F2FC;
$featured: #FED900; $featured: #FED900;

View File

@@ -1,7 +1,9 @@
class Admin::Api::StatsController < Admin::Api::BaseController class Admin::Api::StatsController < Admin::Api::BaseController
def show def show
unless params[:events].present? || params[:visits].present? unless params[:events].present? ||
params[:visits].present? ||
params[:spending_proposals].present?
return render json: {}, status: :bad_request return render json: {}, status: :bad_request
end end
@@ -18,7 +20,10 @@ class Admin::Api::StatsController < Admin::Api::BaseController
ds.add "Visits", Visit.group_by_day(:started_at).count ds.add "Visits", Visit.group_by_day(:started_at).count
end end
if params[:spending_proposals].present?
ds.add "Spending proposals", SpendingProposal.group_by_day(:created_at).count
end
render json: ds.build render json: ds.build
end end
end end

View File

@@ -7,7 +7,7 @@ class Admin::SpendingProposalsController < Admin::BaseController
load_and_authorize_resource load_and_authorize_resource
def index def index
@spending_proposals = SpendingProposal.search(params, @current_filter).order(created_at: :desc).page(params[:page]) @spending_proposals = SpendingProposal.scoped_filter(params, @current_filter).order(created_at: :desc).page(params[:page])
end end
def show def show
@@ -21,10 +21,8 @@ class Admin::SpendingProposalsController < Admin::BaseController
def update def update
if @spending_proposal.update(spending_proposal_params) if @spending_proposal.update(spending_proposal_params)
path = admin_spending_proposal_path( @spending_proposal, redirect_to admin_spending_proposal_path(@spending_proposal, SpendingProposal.filter_params(params)),
{ anchor: 'classification' }.merge(SpendingProposal.filter_params(params))) notice: t("flash.actions.update.spending_proposal")
redirect_to path, notice: t("flash.actions.update.spending_proposal")
else else
render :edit render :edit
end end
@@ -33,7 +31,7 @@ class Admin::SpendingProposalsController < Admin::BaseController
private private
def spending_proposal_params def spending_proposal_params
params.require(:spending_proposal).permit(:administrator_id, :tag_list, valuator_ids: []) params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :association_name, :administrator_id, :tag_list, valuator_ids: [])
end end
end end

View File

@@ -18,10 +18,10 @@ class Admin::StatsController < Admin::BaseController
@verified_users = User.with_hidden.level_two_or_three_verified.count @verified_users = User.with_hidden.level_two_or_three_verified.count
@unverified_users = User.with_hidden.unverified.count @unverified_users = User.with_hidden.unverified.count
@users = User.with_hidden.count @users = User.with_hidden.count
@user_ids_who_voted_proposals = @user_ids_who_voted_proposals =
ActsAsVotable::Vote.where(votable_type: 'Proposal').pluck(:voter_id).uniq.count ActsAsVotable::Vote.where(votable_type: 'Proposal').pluck(:voter_id).uniq.count
@user_ids_who_didnt_vote_proposals = @verified_users - @user_ids_who_voted_proposals @user_ids_who_didnt_vote_proposals = @verified_users - @user_ids_who_voted_proposals
end @spending_proposals = SpendingProposal.count
end
end end

View File

@@ -77,6 +77,10 @@ class ApplicationController < ActionController::Base
@proposal_votes = current_user ? current_user.proposal_votes(proposals) : {} @proposal_votes = current_user ? current_user.proposal_votes(proposals) : {}
end end
def set_spending_proposal_votes(spending_proposals)
@spending_proposal_votes = current_user ? current_user.spending_proposal_votes(spending_proposals) : {}
end
def set_comment_flags(comments) def set_comment_flags(comments)
@comment_flags = current_user ? current_user.comment_flags(comments) : {} @comment_flags = current_user ? current_user.comment_flags(comments) : {}
end end

View File

@@ -65,8 +65,7 @@ module CommentableActions
end end
end end
def map
def map
@resource = resource_model.new @resource = resource_model.new
@tag_cloud = tag_cloud @tag_cloud = tag_cloud
end end

View File

@@ -0,0 +1,13 @@
class Management::AccountController < Management::BaseController
before_action :only_verified_users
def show
end
private
def only_verified_users
check_verified_user t("management.account.alert.unverified_user")
end
end

View File

@@ -20,6 +20,16 @@ class Management::BaseController < ActionController::Base
@managed_user ||= Verification::Management::ManagedUser.find(session[:document_type], session[:document_number]) @managed_user ||= Verification::Management::ManagedUser.find(session[:document_type], session[:document_number])
end end
def current_user
managed_user
end
def check_verified_user(alert_msg)
unless current_user.level_two_or_three_verified?
redirect_to management_document_verifications_path, alert: alert_msg
end
end
def set_locale def set_locale
if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym) if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
session[:locale] = params[:locale] session[:locale] = params[:locale]

View File

@@ -2,7 +2,7 @@ class Management::ProposalsController < Management::BaseController
include HasOrders include HasOrders
include CommentableActions include CommentableActions
before_action :check_verified_user, except: :print before_action :only_verified_users, except: :print
before_action :set_proposal, only: [:vote, :show] before_action :set_proposal, only: [:vote, :show]
before_action :parse_search_terms, only: :index before_action :parse_search_terms, only: :index
before_action :load_categories, only: [:new, :edit] before_action :load_categories, only: [:new, :edit]
@@ -40,14 +40,8 @@ class Management::ProposalsController < Management::BaseController
Proposal Proposal
end end
def check_verified_user def only_verified_users
unless current_user.level_two_or_three_verified? check_verified_user t("management.proposals.alert.unverified_user")
redirect_to management_document_verifications_path, alert: t("management.proposals.alert.unverified_user")
end
end
def current_user
managed_user
end end
### Duplicated in application_controller. Move to a concern. ### Duplicated in application_controller. Move to a concern.

View File

@@ -1,6 +1,12 @@
class Management::SpendingProposalsController < Management::BaseController class Management::SpendingProposalsController < Management::BaseController
before_action :check_verified_user before_action :only_verified_users, except: :print
before_action :set_spending_proposal, only: [:vote, :show]
def index
@spending_proposals = apply_filters_and_search(SpendingProposal).order(cached_votes_up: :desc).page(params[:page]).for_render
set_spending_proposal_votes(@spending_proposals)
end
def new def new
@spending_proposal = SpendingProposal.new @spending_proposal = SpendingProposal.new
@@ -18,23 +24,55 @@ class Management::SpendingProposalsController < Management::BaseController
end end
def show def show
@spending_proposal = SpendingProposal.find(params[:id]) set_spending_proposal_votes(@spending_proposal)
end
def vote
@spending_proposal.register_vote(current_user, 'yes')
set_spending_proposal_votes(@spending_proposal)
end
def print
params[:geozone] ||= 'all'
@spending_proposals = apply_filters_and_search(SpendingProposal).order(cached_votes_up: :desc).for_render.limit(15)
set_spending_proposal_votes(@spending_proposals)
end end
private private
def set_spending_proposal
@spending_proposal = SpendingProposal.find(params[:id])
end
def spending_proposal_params def spending_proposal_params
params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :terms_of_service, :captcha, :captcha_key) params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :terms_of_service, :captcha, :captcha_key)
end end
def check_verified_user def only_verified_users
unless current_user.level_two_or_three_verified? check_verified_user t("management.spending_proposals.alert.unverified_user")
redirect_to management_document_verifications_path, alert: t("management.spending_proposals.alert.unverified_user") end
# This should not be necessary. Maybe we could create a specific show view for managers.
def set_spending_proposal_votes(spending_proposals)
@spending_proposal_votes = current_user ? current_user.spending_proposal_votes(spending_proposals) : {}
end
def set_geozone_name
if params[:geozone] == 'all'
@geozone_name = t('geozones.none')
else
@geozone_name = Geozone.find(params[:geozone]).name
end end
end end
def current_user def apply_filters_and_search(target)
managed_user target = params[:unfeasible].present? ? target.unfeasible : target.not_unfeasible
if params[:geozone].present?
target = target.by_geozone(params[:geozone])
set_geozone_name
end
target = target.search(params[:search]) if params[:search].present?
target
end end
end end

View File

@@ -18,6 +18,12 @@ class Management::UsersController < Management::BaseController
end end
end end
def erase
managed_user.erase(t("management.users.erased_by_manager", manager: current_manager['login'])) if current_manager.present?
destroy_session
redirect_to management_document_verifications_path, notice: t("management.users.erased_notice")
end
def logout def logout
destroy_session destroy_session
redirect_to management_root_url, notice: t("management.sessions.signed_out_managed_user") redirect_to management_root_url, notice: t("management.sessions.signed_out_managed_user")

View File

@@ -1,21 +1,28 @@
class SpendingProposalsController < ApplicationController class SpendingProposalsController < ApplicationController
include FeatureFlags include FeatureFlags
load_and_authorize_resource
before_action :authenticate_user!, except: [:index] before_action :authenticate_user!, except: [:index]
before_action :verify_access, only: [:show] before_action -> { flash.now[:notice] = flash[:notice].html_safe if flash[:html_safe] && flash[:notice] }
before_filter -> { flash.now[:notice] = flash[:notice].html_safe if flash[:html_safe] && flash[:notice] }
load_and_authorize_resource
feature_flag :spending_proposals feature_flag :spending_proposals
respond_to :html, :js
def index def index
@spending_proposals = apply_filters_and_search(SpendingProposal).page(params[:page]).for_render
set_spending_proposal_votes(@spending_proposals)
end end
def new def new
@spending_proposal = SpendingProposal.new @spending_proposal = SpendingProposal.new
end end
def show
set_spending_proposal_votes(@spending_proposal)
end
def create def create
@spending_proposal = SpendingProposal.new(spending_proposal_params) @spending_proposal = SpendingProposal.new(spending_proposal_params)
@spending_proposal.author = current_user @spending_proposal.author = current_user
@@ -29,19 +36,38 @@ class SpendingProposalsController < ApplicationController
end end
def destroy def destroy
spending_proposal = current_user.spending_proposals.find(params[:id]) spending_proposal = SpendingProposal.find(params[:id])
spending_proposal.destroy spending_proposal.destroy
redirect_to user_path(current_user, filter: 'spending_proposals'), notice: t('flash.actions.destroy.spending_proposal') redirect_to user_path(current_user, filter: 'spending_proposals'), notice: t('flash.actions.destroy.spending_proposal')
end end
def vote
@spending_proposal.register_vote(current_user, 'yes')
set_spending_proposal_votes(@spending_proposal)
end
private private
def spending_proposal_params def spending_proposal_params
params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :association_name, :terms_of_service, :captcha, :captcha_key) params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :association_name, :terms_of_service, :captcha, :captcha_key)
end end
def verify_access def set_geozone_name
raise CanCan::AccessDenied unless current_user.try(:valuator?) || current_user.try(:administrator?) || @spending_proposal.author == current_user if params[:geozone] == 'all'
@geozone_name = t('geozones.none')
else
@geozone_name = Geozone.find(params[:geozone]).name
end
end
def apply_filters_and_search(target)
target = params[:unfeasible].present? ? target.unfeasible : target.not_unfeasible
if params[:geozone].present?
target = target.by_geozone(params[:geozone])
set_geozone_name
end
target = target.search(params[:search]) if params[:search].present?
target
end end
end end

View File

@@ -41,9 +41,7 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
end end
def save_user(user) def save_user(user)
@user.save || @user.save || @user.save_requiring_finish_signup
@user.save_requiring_finish_signup ||
@user.save_requiring_finish_signup_without_email
end end
end end

View File

@@ -9,8 +9,9 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
load_and_authorize_resource load_and_authorize_resource
def index def index
@geozone_filters = geozone_filters
if current_user.valuator? if current_user.valuator?
@spending_proposals = SpendingProposal.search(params_for_current_valuator, @current_filter).order(created_at: :desc).page(params[:page]) @spending_proposals = SpendingProposal.scoped_filter(params_for_current_valuator, @current_filter).order(cached_votes_up: :desc).page(params[:page])
else else
@spending_proposals = SpendingProposal.none.page(params[:page]) @spending_proposals = SpendingProposal.none.page(params[:page])
end end
@@ -18,6 +19,11 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
def valuate def valuate
if valid_price_params? && @spending_proposal.update(valuation_params) if valid_price_params? && @spending_proposal.update(valuation_params)
if @spending_proposal.unfeasible_email_pending?
@spending_proposal.send_unfeasible_email
end
redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate') redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate')
else else
render action: :edit render action: :edit
@@ -26,6 +32,25 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
private private
def geozone_filters
spending_proposals = SpendingProposal.by_valuator(current_user.valuator.try(:id)).valuation_open.all.to_a
[ { name: t('valuation.spending_proposals.index.geozone_filter_all'),
id: nil,
pending_count: spending_proposals.size
},
{ name: t('geozones.none'),
id: 'all',
pending_count: spending_proposals.count{|x| x.geozone_id.nil?}
}
] + Geozone.all.order(name: :asc).collect do |g|
{ name: g.name,
id: g.id,
pending_count: spending_proposals.count{|x| x.geozone_id == g.id}
}
end.select{ |x| x[:pending_count] > 0 }
end
def valuation_params def valuation_params
params[:spending_proposal][:feasible] = nil if params[:spending_proposal][:feasible] == 'nil' params[:spending_proposal][:feasible] = nil if params[:spending_proposal][:feasible] == 'nil'

View File

@@ -0,0 +1,30 @@
module EmbedVideosHelper
def embedded_video_code
link = @proposal.video_url
if link.match(/vimeo.*/)
server = "Vimeo"
elsif link.match(/youtu*.*/)
server = "YouTube"
end
if server == "Vimeo"
regExp = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
src = "https://player.vimeo.com/video/"
elsif server == "YouTube"
regExp = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
src = "https://www.youtube.com/embed/"
end
if regExp
match = link.match(regExp)
end
if match and match[2]
'<iframe src="' + src + match[2] + '" frameborder="0" allowfullscreen></iframe>'
else
''
end
end
end

View File

@@ -3,4 +3,14 @@ module SpendingProposalsHelper
def spending_proposal_tags_select_options def spending_proposal_tags_select_options
ActsAsTaggableOn::Tag.spending_proposal_tags.pluck(:name) ActsAsTaggableOn::Tag.spending_proposal_tags.pluck(:name)
end end
def namespaced_spending_proposal_path(spending_proposal, options={})
@namespace_spending_proposal_path ||= namespace
case @namespace_spending_proposal_path
when "management"
management_spending_proposal_path(spending_proposal, options)
else
spending_proposal_path(spending_proposal, options)
end
end
end end

View File

@@ -14,4 +14,10 @@ module StatsHelper
content_tag :div, "", opt content_tag :div, "", opt
end end
def spending_proposals_chart_tag(opt={})
events = events.join(',') if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(spending_proposals: true)
content_tag :div, "", opt
end
end end

View File

@@ -2,9 +2,9 @@ module ValuationHelper
def valuator_select_options(valuator=nil) def valuator_select_options(valuator=nil)
if valuator.present? if valuator.present?
Valuator.where.not(id: valuator.id).order('users.username asc').includes(:user).collect { |v| [ v.name, v.id ] }.prepend([valuator.name, valuator.id]) Valuator.where.not(id: valuator.id).order("description ASC").order("users.email ASC").includes(:user).collect { |v| [ v.description_or_email, v.id ] }.prepend([valuator.description_or_email, valuator.id])
else else
Valuator.all.order('users.username asc').includes(:user).collect { |v| [ v.name, v.id ] } Valuator.all.order("description ASC").order("users.email ASC").includes(:user).collect { |v| [ v.description_or_email, v.id ] }
end end
end end

View File

@@ -7,7 +7,7 @@ class Mailer < ApplicationMailer
@comment = comment @comment = comment
@commentable = comment.commentable @commentable = comment.commentable
with_user(@commentable.author) do with_user(@commentable.author) do
mail(to: @commentable.author.email, subject: t('mailers.comment.subject', commentable: t("activerecord.models.#{@commentable.class.name.downcase}", count: 1).downcase)) if @commentable.present? && @commentable.author.present? mail(to: @commentable.author.email, subject: t('mailers.comment.subject', commentable: t("activerecord.models.#{@commentable.class.name.underscore}", count: 1).downcase)) if @commentable.present? && @commentable.author.present?
end end
end end
@@ -33,6 +33,15 @@ class Mailer < ApplicationMailer
end end
end end
def unfeasible_spending_proposal(spending_proposal)
@spending_proposal = spending_proposal
@author = spending_proposal.author
with_user(@author) do
mail(to: @author.email, subject: t('mailers.unfeasible_spending_proposal.subject', code: @spending_proposal.code))
end
end
private private
def with_user(user, &block) def with_user(user, &block)

View File

@@ -37,7 +37,7 @@ module Abilities
can :manage, Annotation can :manage, Annotation
can [:read, :update], SpendingProposal can [:read, :update, :destroy], SpendingProposal
end end
end end
end end

View File

@@ -43,8 +43,8 @@ module Abilities
if user.level_two_or_three_verified? if user.level_two_or_three_verified?
can :vote, Proposal can :vote, Proposal
can :vote_featured, Proposal can :vote_featured, Proposal
can :vote, SpendingProposal
can :create, SpendingProposal can :create, SpendingProposal
can :destroy, SpendingProposal, author_id: user.id
end end
can :create, Annotation can :create, Annotation

View File

@@ -2,8 +2,10 @@ class SpendingProposal < ActiveRecord::Base
include Measurable include Measurable
include Sanitizable include Sanitizable
include Taggable include Taggable
include Searchable
apply_simple_captcha apply_simple_captcha
acts_as_votable
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :geozone belongs_to :geozone
@@ -24,12 +26,17 @@ class SpendingProposal < ActiveRecord::Base
scope :managed, -> { valuation_open.where(valuation_assignments_count: 0).where("administrator_id IS NOT ?", nil) } scope :managed, -> { valuation_open.where(valuation_assignments_count: 0).where("administrator_id IS NOT ?", nil) }
scope :valuating, -> { valuation_open.where("valuation_assignments_count > 0 AND valuation_finished = ?", false) } scope :valuating, -> { valuation_open.where("valuation_assignments_count > 0 AND valuation_finished = ?", false) }
scope :valuation_finished, -> { where(valuation_finished: true) } scope :valuation_finished, -> { where(valuation_finished: true) }
scope :feasible, -> { where(feasible: true) }
scope :unfeasible, -> { where(feasible: false) }
scope :not_unfeasible, -> { where("feasible IS ? OR feasible = ?", nil, true) }
scope :by_admin, -> (admin) { where(administrator_id: admin.presence) } scope :by_admin, -> (admin) { where(administrator_id: admin.presence) }
scope :by_tag, -> (tag_name) { tagged_with(tag_name) } scope :by_tag, -> (tag_name) { tagged_with(tag_name) }
scope :by_valuator, -> (valuator) { where("valuation_assignments.valuator_id = ?", valuator.presence).joins(:valuation_assignments) } scope :by_valuator, -> (valuator) { where("valuation_assignments.valuator_id = ?", valuator.presence).joins(:valuation_assignments) }
scope :for_render, -> { includes(:geozone, administrator: :user, valuators: :user) } scope :for_render, -> { includes(:geozone) }
before_validation :set_responsible_name
def description def description
super.try :html_safe super.try :html_safe
@@ -39,14 +46,26 @@ class SpendingProposal < ActiveRecord::Base
params.select{|x,_| %w{geozone_id administrator_id tag_name valuator_id}.include? x.to_s } params.select{|x,_| %w{geozone_id administrator_id tag_name valuator_id}.include? x.to_s }
end end
def self.search(params, current_filter) def self.scoped_filter(params, current_filter)
results = self results = self
results = results.by_geozone(params[:geozone_id]) if params[:geozone_id].present? results = results.by_geozone(params[:geozone_id]) if params[:geozone_id].present?
results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present? results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present?
results = results.by_tag(params[:tag_name]) if params[:tag_name].present? results = results.by_tag(params[:tag_name]) if params[:tag_name].present?
results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present? results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present?
results = results.send(current_filter) if current_filter.present? results = results.send(current_filter) if current_filter.present?
results.for_render results.includes(:geozone, administrator: :user, valuators: :user)
end
def searchable_values
{ title => 'A',
author.username => 'B',
geozone.try(:name) => 'B',
description => 'C'
}
end
def self.search(terms)
self.pg_search(terms)
end end
def self.by_geozone(geozone) def self.by_geozone(geozone)
@@ -68,4 +87,51 @@ class SpendingProposal < ActiveRecord::Base
end end
end end
def unfeasible_email_pending?
unfeasible_email_sent_at.blank? && unfeasible? && valuation_finished?
end
def unfeasible?
feasible == false
end
def valuation_finished?
valuation_finished
end
def total_votes
cached_votes_up + physical_votes
end
def code
"#{created_at.strftime('%Y')}-#{id}" + (administrator.present? ? "-A#{administrator.id}" : "")
end
def send_unfeasible_email
Mailer.unfeasible_spending_proposal(self).deliver_later
update(unfeasible_email_sent_at: Time.now)
end
def reason_for_not_being_votable_by(user)
return :not_voting_allowed if Setting["feature.spending_proposal_features.voting_allowed"].blank?
return :not_logged_in unless user
return :not_verified unless user.can?(:vote, SpendingProposal)
return :unfeasible if unfeasible?
return :organization if user.organization?
end
def votable_by?(user)
reason_for_not_being_votable_by(user).blank?
end
def register_vote(user, vote_value)
if votable_by?(user)
vote_by(voter: user, vote: vote_value)
end
end
def set_responsible_name
self.responsible_name = author.try(:document_number) if author.try(:document_number).present?
end
end end

View File

@@ -26,7 +26,7 @@ class User < ActiveRecord::Base
belongs_to :geozone belongs_to :geozone
validates :username, presence: true, if: :username_required? validates :username, presence: true, if: :username_required?
validates :username, uniqueness: true, if: :username_required? validates :username, uniqueness: { scope: :registering_with_oauth }, if: :username_required?
validates :document_number, uniqueness: { scope: :document_type }, allow_nil: true validates :document_number, uniqueness: { scope: :document_type }, allow_nil: true
validate :validate_username_length validate :validate_username_length
@@ -83,6 +83,11 @@ class User < ActiveRecord::Base
voted.each_with_object({}) { |v, h| h[v.votable_id] = v.value } voted.each_with_object({}) { |v, h| h[v.votable_id] = v.value }
end end
def spending_proposal_votes(spending_proposals)
voted = votes.for_spending_proposals(spending_proposals)
voted.each_with_object({}) { |v, h| h[v.votable_id] = v.value }
end
def comment_flags(comments) def comment_flags(comments)
comment_flags = flags.for_comments(comments) comment_flags = flags.for_comments(comments)
comment_flags.each_with_object({}){ |f, h| h[f.flaggable_id] = true } comment_flags.each_with_object({}){ |f, h| h[f.flaggable_id] = true }
@@ -149,6 +154,7 @@ class User < ActiveRecord::Base
confirmed_phone: nil, confirmed_phone: nil,
unconfirmed_phone: nil unconfirmed_phone: nil
) )
self.identities.destroy_all
end end
def erased? def erased?
@@ -177,11 +183,11 @@ class User < ActiveRecord::Base
end end
def username_required? def username_required?
!organization? && !erased? && !registering_with_oauth !organization? && !erased?
end end
def email_required? def email_required?
!erased? && !registering_with_oauth !erased?
end end
def has_official_email? def has_official_email?
@@ -210,12 +216,21 @@ class User < ActiveRecord::Base
end end
def save_requiring_finish_signup def save_requiring_finish_signup
self.update(registering_with_oauth: true) begin
self.registering_with_oauth = true
self.save(validate: false)
# Devise puts unique constraints for the email the db, so we must detect & handle that
rescue ActiveRecord::RecordNotUnique
self.email = nil
self.save(validate: false)
end
true
end end
def save_requiring_finish_signup_without_email def ability
self.update(registering_with_oauth: true, email: nil) @ability ||= Ability.new(self)
end end
delegate :can?, :cannot?, to: :ability
private private
def clean_document_number def clean_document_number

View File

@@ -32,7 +32,7 @@ class Verification::Management::Document
end end
def under_sixteen?(response) def under_sixteen?(response)
16.years.ago < string_to_date(response.date_of_birth) 16.years.ago.beginning_of_day < response.date_of_birth.beginning_of_day
end end
def verified? def verified?

View File

@@ -31,6 +31,8 @@ class Verification::Residence
user.update(document_number: document_number, user.update(document_number: document_number,
document_type: document_type, document_type: document_type,
geozone: self.geozone, geozone: self.geozone,
date_of_birth: date_of_birth.to_datetime,
gender: gender,
residence_verified_at: Time.now) residence_verified_at: Time.now)
end end
@@ -75,6 +77,10 @@ class Verification::Residence
@census_api_response.district_code @census_api_response.district_code
end end
def gender
@census_api_response.gender
end
private private
def call_census_api def call_census_api
@@ -84,7 +90,7 @@ class Verification::Residence
def residency_valid? def residency_valid?
@census_api_response.valid? && @census_api_response.valid? &&
@census_api_response.postal_code == postal_code && @census_api_response.postal_code == postal_code &&
@census_api_response.date_of_birth == date_to_string(date_of_birth) @census_api_response.date_of_birth == date_of_birth
end end
def clean_document_number def clean_document_number

View File

@@ -4,14 +4,9 @@ class Verification::Sms
attr_accessor :user, :phone, :confirmation_code attr_accessor :user, :phone, :confirmation_code
validates_presence_of :phone validates_presence_of :phone
validates :phone, length: { is: 9 } validates :phone, format: { with: /\A[\d \+]+\z/ }
validate :spanish_phone
validate :uniqness_phone validate :uniqness_phone
def spanish_phone
errors.add(:phone, :invalid) unless phone.start_with?('6', '7')
end
def uniqness_phone def uniqness_phone
errors.add(:phone, :taken) if User.where(confirmed_phone: phone).any? errors.add(:phone, :taken) if User.where(confirmed_phone: phone).any?
end end

View File

@@ -0,0 +1,10 @@
<%= form_for(SpendingProposal.new, url: url, as: :spending_proposal, method: :get) do |f| %>
<div class="row">
<div class="small-12 medium-6 column">
<%= text_field_tag :search, "", placeholder: t("admin.shared.spending_proposal_search.placeholder") %>
</div>
<div class="form-inline small-12 medium-3 column end">
<%= f.submit t("admin.shared.spending_proposal_search.button"), class: "button success expanded" %>
</div>
</div>
<% end %>

View File

@@ -2,43 +2,71 @@
<span class="icon-angle-left"></span> <%= t("admin.spending_proposals.show.back") %> <span class="icon-angle-left"></span> <%= t("admin.spending_proposals.show.back") %>
<% end %> <% end %>
<%= render 'written_by_author' %>
<h2 id="form"><%= t("admin.spending_proposals.edit.classification") %></h2>
<%= form_for @spending_proposal, <%= form_for @spending_proposal,
url: admin_spending_proposal_path(@spending_proposal) do |f| %> url: admin_spending_proposal_path(@spending_proposal) do |f| %>
<% SpendingProposal.filter_params(params).each do |filter_name, filter_value| %> <% SpendingProposal.filter_params(params).each do |filter_name, filter_value| %>
<%= hidden_field_tag filter_name, filter_value %> <%= hidden_field_tag filter_name, filter_value %>
<% end %> <% end %>
<%= f.select(:administrator_id, <div class="row">
@admins.collect{ |a| [a.name_and_email, a.id ] }, <div class="small-12 column">
{ include_blank: t("admin.spending_proposals.edit.undefined") }, <%= f.text_field :title, maxlength: SpendingProposal.title_max_length %>
class: "small-12 medium-6") %> </div>
<%= f.label :tag_list, t("admin.spending_proposals.edit.tags") %> <div class="ckeditor small-12 column">
<div class="tags"> <%= f.cktext_area :description, maxlength: SpendingProposal.description_max_length, ckeditor: { language: I18n.locale } %>
<% @tags.each do |tag| %> </div>
<a class="js-add-tag-link"><%= tag.name %></a>
<% end %> <div class="small-12 column">
<%= f.text_field :external_url %>
</div>
<div class="small-12 column">
<%= f.select :geozone_id, geozone_select_options, include_blank: t("geozones.none") %>
</div>
<div class="small-12 column">
<%= f.text_field :association_name, placeholder: t("spending_proposals.form.association_name") %>
</div>
</div> </div>
<%= f.text_field :tag_list, value: @spending_proposal.tag_list.to_s,
label: false,
placeholder: t("admin.spending_proposals.edit.tags_placeholder"),
class: 'js-tag-list' %>
<%= f.label :valuator_ids, t("admin.spending_proposals.edit.assigned_valuators") %> <h2 id="classification"><%= t("admin.spending_proposals.edit.classification") %></h2>
<%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> <div class="row">
<%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
<% end %> <div class="small-12 column">
<%= f.select(:administrator_id,
@admins.collect{ |a| [a.name_and_email, a.id ] },
{ include_blank: t("admin.spending_proposals.edit.undefined") }) %>
</div>
<div class="small-12 column">
<%= f.label :tag_list, t("admin.spending_proposals.edit.tags") %>
<div class="tags">
<% @tags.each do |tag| %>
<a class="js-add-tag-link"><%= tag.name %></a>
<% end %>
</div>
<%= f.text_field :tag_list, value: @spending_proposal.tag_list.to_s,
label: false,
placeholder: t("admin.spending_proposals.edit.tags_placeholder"),
class: 'js-tag-list' %>
</div>
<div class="small-12 column">
<%= f.label :valuator_ids, t("admin.spending_proposals.edit.assigned_valuators") %>
<%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %>
<%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
<% end %>
</div>
</div>
<p class="clear"> <p class="clear">
<%= f.submit(class: "button", value: t("admin.spending_proposals.edit.submit_button")) %> <%= f.submit(class: "button", value: t("admin.spending_proposals.edit.submit_button")) %>
</p> </p>
<% end %> <% end %>
<hr> <hr>

View File

@@ -2,21 +2,30 @@
<div class="row margin"> <div class="row margin">
<%= form_tag admin_spending_proposals_path, method: :get, enforce_utf8: false do %> <%= form_tag admin_spending_proposals_path, method: :get, enforce_utf8: false do %>
<div class="small-12 medium-4 column"> <div class="small-12 medium-3 column">
<%= select_tag :administrator_id, <%= select_tag :administrator_id,
options_for_select(admin_select_options, params[:administrator_id]), options_for_select(admin_select_options, params[:administrator_id]),
{ prompt: t("admin.spending_proposals.index.administrator_filter_all"), { prompt: t("admin.spending_proposals.index.administrator_filter_all"),
label: false, label: false,
class: "js-submit-on-change" } %> class: "js-submit-on-change" } %>
</div> </div>
<div class="small-12 medium-4 column">
<div class="small-12 medium-3 column">
<%= select_tag :valuator_id,
options_for_select(valuator_select_options, params[:valuator_id]),
{ prompt: t("admin.spending_proposals.index.valuator_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :geozone_id, <%= select_tag :geozone_id,
options_for_select(geozone_select_options.unshift([t("geozones.none"), "all"]), params[:geozone_id]), options_for_select(geozone_select_options.unshift([t("geozones.none"), "all"]), params[:geozone_id]),
{ prompt: t("admin.spending_proposals.index.geozone_filter_all"), { prompt: t("admin.spending_proposals.index.geozone_filter_all"),
label: false, label: false,
class: "js-submit-on-change" } %> class: "js-submit-on-change" } %>
</div> </div>
<div class="small-12 medium-4 column"> <div class="small-12 medium-3 column">
<%= select_tag :tag_name, <%= select_tag :tag_name,
options_for_select(spending_proposal_tags_select_options, params[:tag_name]), options_for_select(spending_proposal_tags_select_options, params[:tag_name]),
{ prompt: t("admin.spending_proposals.index.tags_filter_all"), { prompt: t("admin.spending_proposals.index.tags_filter_all"),

View File

@@ -1,16 +1,16 @@
<%= link_to admin_spending_proposals_path(SpendingProposal.filter_params(params)) do %> <%= link_to admin_spending_proposals_path(SpendingProposal.filter_params(params)), data: {no_turbolink: true} do %>
<span class="icon-angle-left"></span> <%= t("admin.spending_proposals.show.back") %> <span class="icon-angle-left"></span> <%= t("admin.spending_proposals.show.back") %>
<% end %> <% end %>
<%= render 'written_by_author' %> <%= render 'written_by_author' %>
<h2 id="classification"><%= t("admin.spending_proposals.show.classification") %></h2> <%= link_to t("admin.spending_proposals.show.edit"),
edit_admin_spending_proposal_path(@spending_proposal,
SpendingProposal.filter_params(params)) %>
<p> <hr>
<%= link_to t("admin.spending_proposals.show.edit_classification"),
edit_admin_spending_proposal_path(@spending_proposal, <h2 id="classification"><%= t("admin.spending_proposals.show.classification") %></h2>
{anchor: 'form'}.merge(SpendingProposal.filter_params(params))) %>
</p>
<p><strong><%= t("admin.spending_proposals.show.assigned_admin") %>:</strong> <p><strong><%= t("admin.spending_proposals.show.assigned_admin") %>:</strong>
<%= @spending_proposal.administrator.try(:name_and_email) || t("admin.spending_proposals.show.undefined") %> <%= @spending_proposal.administrator.try(:name_and_email) || t("admin.spending_proposals.show.undefined") %>
@@ -31,12 +31,19 @@
<% end %> <% end %>
</p> </p>
<p>
<%= link_to t("admin.spending_proposals.show.edit_classification"),
edit_admin_spending_proposal_path(@spending_proposal,
{anchor: 'classification'}.merge(SpendingProposal.filter_params(params))) %>
</p>
<hr> <hr>
<h2><%= t("admin.spending_proposals.show.dossier") %></h2> <h2><%= t("admin.spending_proposals.show.dossier") %></h2>
<%= render 'valuation/spending_proposals/written_by_valuators' %>
<p> <p>
<%= link_to t("admin.spending_proposals.show.edit_dossier"), edit_valuation_spending_proposal_path(@spending_proposal) %> <%= link_to t("admin.spending_proposals.show.edit_dossier"), edit_valuation_spending_proposal_path(@spending_proposal) %>
</p> </p>
<%= render 'valuation/spending_proposals/written_by_valuators' %>

View File

@@ -84,6 +84,13 @@
</span> </span>
</p> </p>
</div> </div>
<div class="small-12 medium-3 column">
<p class="featured">
<%= t "admin.stats.show.summary.spending_proposals" %><br>
<span class="number"><%= number_with_delimiter(@spending_proposals) %></span>
</p>
</div>
</div> </div>
<div class="small-12 column"> <div class="small-12 column">
@@ -97,6 +104,12 @@
<%= events_chart_tag event %> <%= events_chart_tag event %>
<% end %> <% end %>
</div> </div>
<div class="small-12 column">
<h2><%= t "admin.stats.show.spending_proposals_title" %></h2>
<%= spending_proposals_chart_tag id: "spending_proposals" %>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -54,8 +54,14 @@
</div> </div>
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h3><%= t("debates.show.share") %></h3> <h3><%= t("debates.show.share") %></h3>
<%= social_share_button_tag(@debate.title) %> <div class="social-share-full">
</aside> <%= social_share_button_tag("#{@debate.title} #{setting['twitter_hashtag']}") %>
<% if browser.device.mobile? %>
<a href="whatsapp://send?text=<%= @debate.title %> <%= debate_url(@debate) %>" data-action="share/whatsapp/share">
<span class="icon-whatsapp whatsapp"></span>
</a>
<% end %>
</div>
</div> </div>
</section> </section>
<% end %> <% end %>

View File

@@ -44,7 +44,7 @@
</div> </div>
</div> </div>
<div class="subnavigation row expanded"> <div class="subnavigation expanded">
<div class="row"> <div class="row">
<div class="hide-for-small-only"> <div class="hide-for-small-only">
<%= render "shared/subnavigation" %> <%= render "shared/subnavigation" %>

View File

@@ -16,55 +16,65 @@
<body class="admin"> <body class="admin">
<header> <header>
<div class="top-links"> <section class="top-links">
<div class="row"> <div class="row">
<%= render 'shared/locale_switcher' %> <%= render 'shared/locale_switcher' %>
</div> </div>
</div> </section>
<div class="contain-to-grid clear"> <div class="row">
<nav class="top-bar" data-topbar> <div class="top-bar">
<ul class="title-area">
<li class="name"> <%= link_to Setting['org_name'], management_root_path, class: "logo show-for-small-only" %>
<%= link_to management_root_path do %>
<%= image_tag('header_logo_madrid.png', class: 'float-left', size: '96x96') %> <span data-responsive-toggle="responsive-menu" data-hide-for="medium" class="float-right">
<%= Setting['org_name'] %> <span>|</span> <span class="logo-site"><%= t("management.dashboard.index.title") %></span> <span class="menu-icon dark" data-toggle></span>
<%= t("application.menu")%>
</span>
<div id="responsive-menu">
<div class="top-bar-title">
<%= link_to management_root_path, class: "hide-for-small-only" do %>
<%= image_tag('header_logo_madrid.png', class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %>
<%= Setting['org_name'] %>
&nbsp;|&nbsp;<%= t("management.dashboard.index.title") %>
<% end %> <% end %>
</li> </div>
<li class="toggle-topbar menu-icon"><a href="#"><span></span></a></li> </div>
</ul> </div>
</nav>
</div> </div>
</header> </header>
<div class="row">
<div class="small-12 medium-3 column"> <div class="row expanded">
<%= render "/management/menu" %> <main>
</div> <div class="small-12 medium-3 column">
<%= render "/management/menu" %>
</div>
<%= render "management/account_info" %> <%= render "management/account_info" %>
<div class="admin-content small-12 medium-9 column"> <div class="admin-content small-12 medium-9 column">
<% if notice %> <% if notice %>
<div data-alert class="callout success" data-closable> <div data-alert class="callout success" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close> <button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<%= notice %> <%= notice %>
</div> </div>
<% end %> <% end %>
<% if alert %> <% if alert %>
<div data-alert class="callout alert" data-closable> <div data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close> <button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<%= alert %> <%= alert %>
</div> </div>
<% end %> <% end %>
<%= yield %> <%= yield %>
</div> </div>
</main>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,35 @@
<td style="padding-bottom: 20px; padding-left: 10px;">
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.hi") %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.unfeasible_html",
title: @spending_proposal.title) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px; padding-left: 12px; border-left: 2px solid #ccc;">
<%= @spending_proposal.feasible_explanation %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.new_html",
url: link_to(t("mailers.unfeasible_spending_proposal.new_href"),
new_spending_proposal_url, style: "color: #2895F1; text-decoration: underline;")) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.reconsider_html", code: @spending_proposal.code) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.sorry") %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.unfeasible_spending_proposal.sincerely") %><br>
<span style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 12px;font-weight: normal;line-height: 24px; color: #ccc;">
<%= t("mailers.unfeasible_spending_proposal.signatory") %></span>
</p>
</td>

View File

@@ -1,5 +1,5 @@
<% if managed_user.document_number.present? %> <% if managed_user.document_number.present? %>
<section class="small-12 medium-9 column margin-top"> <section class="small-12 medium-9 column">
<div class="account-info"> <div class="account-info">
<%= link_to(t("management.account_info.change_user"), logout_management_users_path, method: :delete, class: 'float-right change-user') %> <%= link_to(t("management.account_info.change_user"), logout_management_users_path, method: :delete, class: 'float-right change-user') %>

View File

@@ -13,6 +13,13 @@
<% end %> <% end %>
</li> </li>
<li <%= "class=active" if controller_name == "account" %>>
<%= link_to management_account_path do %>
<span class="icon-user"></span>
<%= t("management.menu.edit_user_accounts") %>
<% end %>
</li>
<li <%= "class=active" if controller_name == "proposals" and action_name == "new" %>> <li <%= "class=active" if controller_name == "proposals" and action_name == "new" %>>
<%= link_to new_management_proposal_path do %> <%= link_to new_management_proposal_path do %>
<span class="icon-proposals"></span> <span class="icon-proposals"></span>
@@ -34,11 +41,25 @@
<% end %> <% end %>
</li> </li>
<li <%= "class=active" if controller_name == "spending_proposals" and action_name == "index" %>>
<%= link_to management_spending_proposals_path do %>
<span class="icon-like"></span>
<%= t("management.menu.support_spending_proposals") %>
<% end %>
</li>
<li <%= "class=active" if controller_name == "proposals" and action_name == "print" %>> <li <%= "class=active" if controller_name == "proposals" and action_name == "print" %>>
<%= link_to print_management_proposals_path do %> <%= link_to print_management_proposals_path do %>
<span class="icon-print"></span> <span class="icon-print"></span>
<%= t("management.menu.print_proposals") %> <%= t("management.menu.print_proposals") %>
<% end %> <% end %>
</li> </li>
<li <%= "class=active" if controller_name == "spending_proposals" and action_name == "print" %>>
<%= link_to print_management_spending_proposals_path do %>
<span class="icon-print"></span>
<%= t("management.menu.print_spending_proposals") %>
<% end %>
</li>
</ul> </ul>
</div> </div>

View File

@@ -0,0 +1,3 @@
<h2><%= t("management.account.show.title") %></h2>
<%= render 'management/users/erase_user_account' %>

View File

@@ -1,14 +1,6 @@
<div class="dashboard"> <div class="dashboard">
<h2><%= t("management.dashboard.index.title") %></h2> <h2><%= t("management.dashboard.index.title") %></h2>
<p>Desde aquí puedes gestionar usuarios a través de las siguientes acciones:</p> <p><%= t("management.dashboard.index.info") %></p>
<h3>Usuarios</h3>
<h3>Crear propuesta</h3>
<h3>Apoyar propuesta</h3>
<h3>Imprimir propuestas</h3>
</div> </div>

View File

@@ -13,3 +13,5 @@
<%= f.hidden_field :document_number %> <%= f.hidden_field :document_number %>
<%= f.submit t("management.document_verifications.verify"), class: "button success" %> <%= f.submit t("management.document_verifications.verify"), class: "button success" %>
<% end %> <% end %>
<%= render 'management/users/erase_user_account' %>

View File

@@ -7,7 +7,7 @@
<div class="filters"> <div class="filters">
<div class="small-12 medium-7 float-left"> <div class="small-12 medium-7 float-left">
<% if @search_terms %> <% if @search_terms %>
<h2 class="margin-top"> <h2>
<%= page_entries_info @proposals %> <%= page_entries_info @proposals %>
<%= t("proposals.index.search_results", count: @proposals.size, search_term: @search_terms) %> <%= t("proposals.index.search_results", count: @proposals.size, search_term: @search_terms) %>
</h2> </h2>

View File

@@ -20,8 +20,8 @@
<%= render @proposals %> <%= render @proposals %>
<div class="for-print-only"> <div class="for-print-only">
<p><strong><%= t("management.print.info") %></strong><br> <p><strong><%= t("management.print.proposals_info") %></strong><br>
<%= t("management.print.note") %></p> <%= t("management.print.proposals_note") %></p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1 @@
<%= render partial: 'spending_proposals/spending_proposal', locals: {spending_proposal: spending_proposal} %>

View File

@@ -0,0 +1,2 @@
<%= render 'spending_proposals/votes',
{ spending_proposal: spending_proposal, vote_url: vote_management_spending_proposal_path(spending_proposal, value: 'yes') } %>

View File

@@ -0,0 +1,25 @@
<main>
<span class="not-print">
<%= render 'admin/shared/spending_proposal_search', url: management_spending_proposals_path %>
</span>
<div class="wrap row">
<div id="investment-projects" class="investment-projects-list small-12 medium-9 column">
<div class="small-12 search-results">
<%= content_tag(:h2, t("management.spending_proposals.filters.unfeasible")) if params[:unfeasible].present? %>
<%= content_tag(:h2, t("management.spending_proposals.filters.by_geozone", geozone: @geozone_name)) if @geozone_name.present? %>
<% if params[:search].present? %>
<h2>
<%= page_entries_info @spending_proposals %>
<%= t("management.spending_proposals.search_results", count: @spending_proposals.size, search_term: params[:search]) %>
</h2>
<% end %>
</div>
<%= render @spending_proposals %>
<%= paginate @spending_proposals %>
</div>
</div>
</main>

View File

@@ -0,0 +1,34 @@
<main>
<div class="row">
<div id="investment-projects" class="investment-projects-list small-12 column">
<div class="not-print">
<%= form_tag print_management_spending_proposals_path, method: :get, enforce_utf8: false do %>
<div class="small-12 medium-4 column float-left">
<%= select_tag :geozone,
options_for_select(geozone_select_options.unshift([t("geozones.none"), "all"]), params[:geozone]),
{ label: false,
class: "js-submit-on-change" } %>
</div>
<% end %>
<a id="print_link" href="javascript:window.print();" class="button warning float-right">
<%= t('management.spending_proposals.print.print_button') %>
</a>
</div>
<div class="small-12 search-results">
<%= content_tag(:h2, t("management.spending_proposals.filters.unfeasible"), class: "inline-block") if params[:unfeasible].present? %>
<%= content_tag(:h2, t("management.spending_proposals.filters.by_geozone", geozone: @geozone_name), class: "inline-block") if @geozone_name.present? %>
<%= content_tag(:h2, t("management.spending_proposals.search_results", count: @spending_proposals.size, search_term: params[:search]), class: "inline-block") if params[:search].present? %>
</div>
<%= render @spending_proposals %>
<div class="for-print-only">
<p><strong><%= t("management.print.spending_proposals_info") %></strong><br>
<%= t("management.print.spending_proposals_note") %></p>
</div>
</div>
</div>
</main>

View File

@@ -0,0 +1 @@
<%= render template: 'spending_proposals/vote' %>

View File

@@ -0,0 +1,9 @@
<%= link_to t("management.users.erase_account_link"), "#", class: "delete js-toggle-link", data: { "toggle-selector" => "#erase-account-form" } %>
<div id="erase-account-form" style="display:none">
<div class="callout alert medium-6">
<%= t("management.users.erase_warning") %>
</div>
<%= link_to t("management.users.erase_submit"), erase_management_users_path, method: :delete, class: "button alert", data: { confirm: t("management.users.erase_account_confirm") } %>
</div>

View File

@@ -2,7 +2,6 @@
<section class="row-full comments"> <section class="row-full comments">
<div class="row"> <div class="row">
<div id="comments" class="small-12 column"> <div id="comments" class="small-12 column">
<h2> <h2>
<%= t("proposals.show.comments_title") %> <%= t("proposals.show.comments_title") %>
<span class="js-comments-count">(<%= @proposal.comments_count %>)</span> <span class="js-comments-count">(<%= @proposal.comments_count %>)</span>

View File

@@ -37,7 +37,7 @@
<% if voted_for?(@featured_proposals_votes, proposal) %> <% if voted_for?(@featured_proposals_votes, proposal) %>
<% if setting['twitter_handle'] %> <% if setting['twitter_handle'] %>
<div class="share-supported"> <div class="share-supported">
<%= social_share_button_tag(proposal.title, 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 %>
<% end %> <% end %>

View File

@@ -53,7 +53,7 @@
<% 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, 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> </div>

View File

@@ -50,6 +50,14 @@
<blockquote><%= @proposal.summary %></blockquote> <blockquote><%= @proposal.summary %></blockquote>
<% if @proposal.video_url.present? %>
<div class="small-12 medium-7 small-centered">
<div class="flex-video">
<div id="js-embedded-video" data-video-code="<%= embedded_video_code %>"></div>
</div>
</div>
<% end %>
<%= safe_html_with_links @proposal.description %> <%= safe_html_with_links @proposal.description %>
<% if @proposal.external_url.present? %> <% if @proposal.external_url.present? %>
@@ -86,7 +94,14 @@
</div> </div>
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>
<h3><%= t("proposals.show.share") %></h3> <h3><%= t("proposals.show.share") %></h3>
<%= social_share_button_tag(@proposal.title) %> <div class="social-share-full">
<%= social_share_button_tag("#{@proposal.title} #{setting['twitter_hashtag']}") %>
<% if browser.device.mobile? %>
<a href="whatsapp://send?text=<%= @proposal.title %> <%= proposal_url(@proposal) %>" data-action="share/whatsapp/share">
<span class="icon-whatsapp whatsapp"></span>
</a>
<% end %>
</div>
</aside> </aside>
</div> </div>
</section> </section>

View File

@@ -1,6 +1,6 @@
<main> <main>
<div class="wrap row proposals-summary"> <div class="wrap row proposals-summary">
<div id="proposals" class="proposals-list small-12 medium-9 column margin-top"> <div id="proposals" class="proposals-list small-12 medium-9 column">
<%= link_to :back, class: 'back left' do %> <%= link_to :back, class: 'back left' do %>
<span class="icon-angle-left left"></span> <span class="icon-angle-left left"></span>

View File

@@ -0,0 +1,15 @@
<div class="sidebar-divider"></div>
<h3 class="sidebar-title"><%= t("spending_proposals.index.sidebar.geozones") %></h3>
<br>
<div class="geozone">
<%= link_to t('geozones.all'), spending_proposals_path(geozone: nil) %>
<%= link_to t('geozones.none'), spending_proposals_path(geozone: 'all') %>
<% Geozone.all.each do |geozone| %>
<%= link_to geozone.name, spending_proposals_path(geozone: geozone.id) %>
<% end %>
</div>
<div class="sidebar-divider"></div>
<h3 class="sidebar-title"><%= t("spending_proposals.index.sidebar.feasibility") %></h3>
<br>
<%= link_to t('spending_proposals.index.sidebar.unfeasible'), spending_proposals_path(unfeasible: '1') %>

View File

@@ -0,0 +1,59 @@
<div id="<%= dom_id(spending_proposal) %>" class="investment-project clear">
<div class="panel">
<div class="row">
<div class="small-12 medium-9 column">
<div class="investment-project-content">
<% cache [locale_and_user_status(spending_proposal), 'index', spending_proposal, spending_proposal.author] do %>
<span class="label-investment-project float-left"><%= t("spending_proposals.spending_proposal.spending_proposal") %></span>
<span class="icon-budget"></span>
<h3><%= link_to spending_proposal.title, namespaced_spending_proposal_path(spending_proposal) %></h3>
<p class="investment-project-info">
<%= l spending_proposal.created_at.to_date %>
<% if spending_proposal.author.hidden? || spending_proposal.author.erased? %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<span class="author">
<%= t("spending_proposals.show.author_deleted") %>
</span>
<% else %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<span class="author">
<%= spending_proposal.author.name %>
</span>
<% if spending_proposal.author.official? %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<span class="label round level-<%= spending_proposal.author.official_level %>">
<%= spending_proposal.author.official_position %>
</span>
<% end %>
<% end %>
<% if spending_proposal.author.verified_organization? %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<span class="label round is-association">
<%= t("shared.collective") %>
</span>
<% end %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<%= geozone_name(spending_proposal) %>
</p>
<div class="investment-project-description">
<p><%= link_to spending_proposal.description, namespaced_spending_proposal_path(spending_proposal) %></p>
<div class="truncate"></div>
</div>
<% end %>
</div>
</div>
<div id="<%= dom_id(spending_proposal) %>_votes" class="small-12 medium-3 column text-center">
<%= render 'votes',
{ spending_proposal: spending_proposal, vote_url: vote_spending_proposal_path(spending_proposal, value: 'yes') } %>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,42 @@
<div class="supports">
<% reason = spending_proposal.reason_for_not_being_votable_by(current_user) %>
<% voting_allowed = true unless reason.presence == :not_voting_allowed %>
<% user_voted_for = voted_for?(@spending_proposal_votes, spending_proposal) %>
<span class="total-supports <%= 'no-button' unless voting_allowed || user_voted_for %>">
<%= t("spending_proposals.spending_proposal.supports", count: spending_proposal.total_votes) %>
</span>
<div class="in-favor">
<% if user_voted_for %>
<div class="supported">
<%= t("spending_proposals.spending_proposal.already_supported") %>
</div>
<% elsif voting_allowed %>
<%= link_to vote_url,
class: "button button-support small expanded",
title: t('spending_proposals.spending_proposal.support_title'), method: "post", remote: true do %>
<%= t("spending_proposals.spending_proposal.support") %>
<% end %>
<% end %>
</div>
<% if reason.present? && !user_voted_for %>
<div class="no-supports-allowed" style='display:none'>
<p>
<%= t("votes.spending_proposals.#{reason}",
verify_account: link_to(t("votes.verify_account"), verification_path),
signin: link_to(t("votes.signin"), new_user_session_path),
signup: link_to(t("votes.signup"), new_user_registration_path)
).html_safe %>
</p>
</div>
<% end %>
<% if user_voted_for && setting['twitter_handle'] %>
<div class="share-supported">
<%= social_share_button_tag("#{spending_proposal.title} #{setting['twitter_hashtag']}", url: spending_proposal_url(spending_proposal), via: setting['twitter_handle']) %>
</div>
<% end %>
</div>

View File

@@ -1,16 +1,37 @@
<% provide :title do %><%= t('spending_proposals.index.title') %><% end %> <% provide :title do %><%= t('spending_proposals.index.title') %><% end %>
<div class="page row-full"> <% content_for :header_addon do %>
<div class="row"> <%= render "shared/search_form",
<div class="more-information text small-12 medium-8 column"> search_path: spending_proposals_path(page: 1),
<h1><%= t('spending_proposals.index.title') %></h1> i18n_namespace: "spending_proposals.index.search_form" %>
<% end %>
<p><%= t('spending_proposals.index.text_html') %></p> <main>
<div class="wrap row">
<div id="investment-projects" class="investment-projects-list small-12 medium-9 column">
<% if can? :create, SpendingProposal %> <div class="small-12 search-results">
<%= link_to t('spending_proposals.index.create_link'), new_spending_proposal_path, class: 'button' %> <%= content_tag(:h2, t("spending_proposals.index.unfeasible")) if params[:unfeasible].present? %>
<% else %> <%= content_tag(:h2, t("spending_proposals.index.by_geozone", geozone: @geozone_name)) if @geozone_name.present? %>
<p><%= t('spending_proposals.index.verified_only', verify_account: link_to(t('spending_proposals.index.verify_account'), verification_path)).html_safe %></p> <% if params[:search].present? %>
<% end %> <h2>
<%= page_entries_info @spending_proposals %>
<%= t("spending_proposals.index.search_results", count: @spending_proposals.size, search_term: params[:search]) %>
</h2>
<% end %>
</div>
<div class="show-for-small-only">
<%= link_to t("spending_proposals.index.start_spending_proposal"), new_spending_proposal_path, class: 'button expanded' %>
</div>
<%= render partial: 'spending_proposals/spending_proposal', collection: @spending_proposals %>
<%= paginate @spending_proposals %>
</div> </div>
<div class="small-12 medium-3 column">
<aside id="sidebar" class="margin-bottom">
<%= render 'sidebar' %>
</aside>
</div>
</div> </div>
</div> </main>

View File

@@ -1,12 +1,12 @@
<% provide :title do %><%= @spending_proposal.title %><% end %> <% provide :title do %><%= @spending_proposal.title %><% end %>
<section class="proposal-show"> <section class="investment-project-show">
<div id="<%= dom_id(@spending_proposal) %>" class="row"> <div id="<%= dom_id(@spending_proposal) %>" class="row">
<div class="small-12 medium-9 column"> <div class="small-12 medium-9 column">
<h1><%= @spending_proposal.title %></h1> <h1><%= @spending_proposal.title %></h1>
<div class="spending-proposal-info"> <div class="investment-project-info">
<%= render '/shared/author_info', resource: @spending_proposal %> <%= render '/shared/author_info', resource: @spending_proposal %>
<span class="bullet">&nbsp;&bull;&nbsp;</span> <span class="bullet">&nbsp;&bull;&nbsp;</span>
@@ -15,6 +15,12 @@
<%= geozone_name(@spending_proposal) %> <%= geozone_name(@spending_proposal) %>
</div> </div>
<br>
<p id="spending_proposal_code">
<%= t("spending_proposals.show.code") %>
<strong><%= @spending_proposal.id %></strong>
</p>
<%= safe_html_with_links @spending_proposal.description.html_safe %> <%= safe_html_with_links @spending_proposal.description.html_safe %>
<% if @spending_proposal.external_url.present? %> <% if @spending_proposal.external_url.present? %>
@@ -25,5 +31,26 @@
</div> </div>
<aside class="small-12 medium-3 column">
<div class="sidebar-divider"></div>
<h3><%= t("votes.supports") %></h3>
<div class="text-center">
<div id="<%= dom_id(@spending_proposal) %>_votes">
<%= render 'votes',
{ spending_proposal: @spending_proposal, vote_url: vote_spending_proposal_path(@spending_proposal, value: 'yes') } %>
</div>
</div>
<div class="sidebar-divider"></div>
<h3><%= t("spending_proposals.show.share") %></h3>
<div class="social-share-full">
<%= social_share_button_tag("#{@spending_proposal.title} #{setting['twitter_hashtag']}") %>
<% if browser.device.mobile? %>
<a href="whatsapp://send?text=<%= @spending_proposal.title %> <%= spending_proposal_url(@spending_proposal) %>" data-action="share/whatsapp/share">
<span class="icon-whatsapp whatsapp"></span>
</a>
<% end %>
</div>
</aside>
</div> </div>
</section> </section>

View File

@@ -0,0 +1 @@
$("#<%= dom_id(@spending_proposal) %>_votes").html('<%= j render("spending_proposals/votes", spending_proposal: @spending_proposal, vote_url: vote_spending_proposal_path(@spending_proposal, value: "yes")) %>');

View File

@@ -3,6 +3,10 @@
<%= form_for current_user, as: :user, url: do_finish_signup_path, html: { role: 'form'} do |f| %> <%= form_for current_user, as: :user, url: do_finish_signup_path, html: { role: 'form'} do |f| %>
<%= render 'shared/errors', resource: current_user %> <%= render 'shared/errors', resource: current_user %>
<div class='callout primary'>
<%= t("omniauth.finish_signup.username_warning") %>
</div>
<% if current_user.errors.include? :username %> <% if current_user.errors.include? :username %>
<%= f.text_field :username, placeholder: t("devise_views.users.registrations.new.username_label") %> <%= f.text_field :username, placeholder: t("devise_views.users.registrations.new.username_label") %>
<% else %> <% else %>

View File

@@ -1,13 +1,14 @@
<h2><%= t("valuation.spending_proposals.index.title") %></h2> <h2><%= t("valuation.spending_proposals.index.title") %></h2>
<div> <div class="row collapse">
<%= form_tag valuation_spending_proposals_path, method: :get, enforce_utf8: false do %> <% @geozone_filters.each_slice(8) do |slice| %>
<div class="small-12 medium-4 column float-right"> <div class="small-12 medium-4 column select-geozone">
<%= select_tag :geozone_id, <% slice.each do |filter| %>
options_for_select(geozone_select_options.unshift([t("geozones.none"), "all"]), params[:geozone_id]), <%= link_to valuation_spending_proposals_path(geozone_id: filter[:id]),
{ prompt: t("valuation.spending_proposals.index.geozone_filter_all"), class: "#{'active' if params[:geozone_id].to_s == filter[:id].to_s}" do %>
label: false, <%= filter[:name] %>&nbsp;(<%= filter[:pending_count] %>)
class: "js-submit-on-change" } %> <% end %>
<% end %>
</div> </div>
<% end %> <% end %>
</div> </div>

View File

@@ -29,9 +29,10 @@
<%= render "shared/errors", resource: @sms %> <%= render "shared/errors", resource: @sms %>
<div class="small-12 medium-6"> <div class="small-12 medium-6">
<%= f.label t("verification.sms.new.phone") %> <%= f.label :phone, t("verification.sms.new.phone"), class: "inline-block" %>
<span class="inline-block"><%= t("verification.sms.new.phone_format_html") %></span>
<p class="note"><%= t("verification.sms.new.phone_note") %></p> <p class="note"><%= t("verification.sms.new.phone_note") %></p>
<%= f.text_field :phone, label: false %> <%= f.text_field :phone, label: false, placeholder: t("verification.sms.new.phone_placeholder") %>
</div> </div>
<%= f.submit t("verification.sms.new.submit_button"), class: "button success" %> <%= f.submit t("verification.sms.new.submit_button"), class: "button success" %>

View File

@@ -131,6 +131,7 @@ ignore_unused:
- 'proposals.index.select_order' - 'proposals.index.select_order'
- 'proposals.index.orders.*' - 'proposals.index.orders.*'
- 'proposals.index.search_form.*' - 'proposals.index.search_form.*'
- 'spending_proposals.index.search_form.*'
- 'notifications.index.comments_on*' - 'notifications.index.comments_on*'
- 'notifications.index.replies_to*' - 'notifications.index.replies_to*'
- 'helpers.page_entries_info.*' # kaminari - 'helpers.page_entries_info.*' # kaminari

View File

@@ -7,6 +7,10 @@ ActsAsVotable::Vote.class_eval do
where(votable_type: 'Proposal', votable_id: proposals) where(votable_type: 'Proposal', votable_id: proposals)
end end
def self.for_spending_proposals(spending_proposals)
where(votable_type: 'SpendingProposal', votable_id: spending_proposals)
end
def value def value
vote_flag vote_flag
end end

View File

@@ -67,6 +67,13 @@ en:
organization: organization:
name: "Name of organisation" name: "Name of organisation"
responsible_name: "Person responsible for the group" responsible_name: "Person responsible for the group"
spending_proposal:
administrator_id: "Administrador"
association_name: "Association name"
description: "Description"
external_url: "Link to additional documentation"
geozone_id: "Scope of operation"
title: "Title"
errors: errors:
models: models:
debate: debate:
@@ -77,5 +84,3 @@ en:
attributes: attributes:
tag_list: tag_list:
less_than_or_equal_to: "tags must be less than or equal to %{count}" less_than_or_equal_to: "tags must be less than or equal to %{count}"
spending_proposal:
administrator_id: "Administrator"

View File

@@ -38,8 +38,8 @@ es:
one: "Propuesta ciudadana" one: "Propuesta ciudadana"
other: "Propuestas ciudadanas" other: "Propuestas ciudadanas"
spending_proposal: spending_proposal:
one: "Propuesta de gasto" one: "Propuesta de inversión"
other: "Propuestas de gasto" other: "Propuestas de inversión"
attributes: attributes:
comment: comment:
body: "Comentario" body: "Comentario"
@@ -69,6 +69,11 @@ es:
responsible_name: "Persona responsable del colectivo" responsible_name: "Persona responsable del colectivo"
spending_proposal: spending_proposal:
administrator_id: "Administrador" administrator_id: "Administrador"
association_name: "Nombre de la asociación"
description: "Descripción"
external_url: "Enlace a documentación adicional"
geozone_id: "Ámbito de actuación"
title: "Título"
errors: errors:
models: models:
debate: debate:

View File

@@ -145,6 +145,9 @@ en:
proposal_search: proposal_search:
button: Search button: Search
placeholder: Search proposals by title, code, description or question placeholder: Search proposals by title, code, description or question
spending_proposal_search:
button: Search
placeholder: Search spending proposals by title or description
user_search: user_search:
button: Search button: Search
placeholder: Search user by name or email' placeholder: Search user by name or email'
@@ -152,6 +155,7 @@ en:
index: index:
geozone_filter_all: All zones geozone_filter_all: All zones
administrator_filter_all: All administrators administrator_filter_all: All administrators
valuator_filter_all: All valuators
tags_filter_all: All tags tags_filter_all: All tags
filters: filters:
valuation_open: Open valuation_open: Open
@@ -169,6 +173,7 @@ en:
back: Back back: Back
classification: Clasification classification: Clasification
heading: "Investment project %{id}" heading: "Investment project %{id}"
edit: Edit
edit_classification: Edit classification edit_classification: Edit classification
association_name: Association association_name: Association
by: By by: By
@@ -195,6 +200,7 @@ en:
debates: Debates debates: Debates
proposal_votes: Proposal votes proposal_votes: Proposal votes
proposals: Proposals proposals: Proposals
spending_proposals: Spending Proposals
unverified_users: Unverified users unverified_users: Unverified users
user_level_three: Level three users user_level_three: Level three users
user_level_two: Level two users user_level_two: Level two users
@@ -203,6 +209,7 @@ en:
verified_users_who_didnt_vote_proposals: Verified users who didn't votes proposals verified_users_who_didnt_vote_proposals: Verified users who didn't votes proposals
visits: Visits visits: Visits
votes: Total votes votes: Total votes
spending_proposals_title: Spending Proposals
visits_title: Visits visits_title: Visits
tags: tags:
create: Create Topic create: Create Topic

View File

@@ -145,6 +145,9 @@ es:
proposal_search: proposal_search:
button: Buscar button: Buscar
placeholder: Buscar propuestas por título, código, descripción o pregunta placeholder: Buscar propuestas por título, código, descripción o pregunta
spending_proposal_search:
button: Buscar
placeholder: Buscar propuestas por título o descripción
user_search: user_search:
button: Buscar button: Buscar
placeholder: Buscar usuario por nombre o email placeholder: Buscar usuario por nombre o email
@@ -152,6 +155,7 @@ es:
index: index:
geozone_filter_all: Todos los ámbitos de actuación geozone_filter_all: Todos los ámbitos de actuación
administrator_filter_all: Todos los administradores administrator_filter_all: Todos los administradores
valuator_filter_all: Todos los evaluadores
tags_filter_all: Todas las etiquetas tags_filter_all: Todas las etiquetas
filters: filters:
valuation_open: Abiertas valuation_open: Abiertas
@@ -169,6 +173,7 @@ es:
back: Volver back: Volver
classification: Clasificación classification: Clasificación
heading: Propuesta de inversión %{id} heading: Propuesta de inversión %{id}
edit: Editar
edit_classification: Editar clasificación edit_classification: Editar clasificación
association_name: Asociación association_name: Asociación
by: Autor by: Autor
@@ -195,6 +200,7 @@ es:
debates: Debates debates: Debates
proposal_votes: Votos en propuestas proposal_votes: Votos en propuestas
proposals: Propuestas proposals: Propuestas
spending_proposals: Propuestas de inversión
unverified_users: Usuarios sin verificar unverified_users: Usuarios sin verificar
user_level_three: Usuarios de nivel tres user_level_three: Usuarios de nivel tres
user_level_two: Usuarios de nivel dos user_level_two: Usuarios de nivel dos
@@ -203,6 +209,7 @@ es:
verified_users_who_didnt_vote_proposals: Usuarios verificados que no han votado propuestas verified_users_who_didnt_vote_proposals: Usuarios verificados que no han votado propuestas
visits: Visitas visits: Visitas
votes: Votos votes: Votos
spending_proposals_title: Propuestas de inversión
visits_title: Visitas visits_title: Visitas
tags: tags:
create: Crear Tema create: Crear Tema

View File

@@ -154,6 +154,7 @@ en:
verification/sms: phone verification/sms: phone
geozones: geozones:
none: All city none: All city
all: All scopes
layouts: layouts:
application: application:
chrome: Google Chrome chrome: Google Chrome
@@ -412,20 +413,43 @@ en:
new: Create new: Create
title: Spending proposal title title: Spending proposal title
index: index:
create_link: Create spending proposal
text_html: Here you can send spending proposals to be considered in the frame of the annual participatory budgeting.
title: Participatory budgeting title: Participatory budgeting
verified_only: Only verified users can create spending proposals, %{verify_account}. unfeasible: Unfeasible investment projects
verify_account: verify your account by_geozone: "Investment projects with scope: %{geozone}"
search_form:
button: Search
placeholder: Investment projects...
title: Search
search_results:
one: " containing the term '%{search_term}'"
other: " containing the term '%{search_term}'"
sidebar:
geozones: Scope of operation
feasibility: Feasibility
unfeasible: Unfeasible
start_spending_proposal: Create an investment project
new: new:
back_link: Back
more_info: How do participatory budgeting works? more_info: How do participatory budgeting works?
recommendation_one: It's mandatory that the proposal makes reference to a budgetable action. recommendation_one: It's mandatory that the proposal makes reference to a budgetable action.
recommendation_three: Try to go into details when describing your spending proposal so the reviewing team undertands your points. recommendation_three: Try to go into details when describing your spending proposal so the reviewing team undertands your points.
recommendation_two: Any proposal or comment suggesting illegal action will be deleted. recommendation_two: Any proposal or comment suggesting illegal action will be deleted.
recommendations_title: How to create a spending proposal recommendations_title: How to create a spending proposal
start_new: Create spending proposal start_new: Create spending proposal
back_link: Back
show:
author_deleted: User deleted
code: 'Proposal code:'
share: Share
wrong_price_format: Only integer numbers wrong_price_format: Only integer numbers
spending_proposal:
spending_proposal: Investment project
already_supported: You have already supported this. Share it!
support: Support
support_title: Support this project
supports:
one: 1 support
other: "%{count} supports"
zero: No supports
stats: stats:
index: index:
visits: Visits visits: Visits
@@ -476,6 +500,12 @@ en:
unauthenticated: You must %{signin} or %{signup} to continue. unauthenticated: You must %{signin} or %{signup} to continue.
verified_only: Only verified users can vote on proposals; %{verify_account}. verified_only: Only verified users can vote on proposals; %{verify_account}.
verify_account: verify your account verify_account: verify your account
spending_proposals:
not_logged_in: You must %{signin} or %{signup} to continue.
not_verified: Only verified users can vote on proposals; %{verify_account}.
organization: Organisations are not permitted to vote
unfeasible: Unfeasible investment projects can not be supported
not_voting_allowed: Voting phase is closed
welcome: welcome:
debates: debates:
alt: Icon debates alt: Icon debates
@@ -512,6 +542,7 @@ en:
omniauth: omniauth:
finish_signup: finish_signup:
title: "Additional details" title: "Additional details"
username_warning: "Due to a change in the way we interact with social networks, it is possible that your username now appears as 'already in use'. If that is your case, please choose a different username."
twitter: twitter:
sign_in: "Sign in with Twitter" sign_in: "Sign in with Twitter"
sign_up: "Sign up with Twitter" sign_up: "Sign up with Twitter"

View File

@@ -154,6 +154,7 @@ es:
verification/sms: el teléfono verification/sms: el teléfono
geozones: geozones:
none: Toda la ciudad none: Toda la ciudad
all: Todos los ámbitos
layouts: layouts:
application: application:
chrome: Google Chrome chrome: Google Chrome
@@ -412,20 +413,43 @@ es:
new: Crear new: Crear
title: Título de la propuesta de gasto title: Título de la propuesta de gasto
index: index:
create_link: Enviar propuesta de gasto
text_html: Desde esta sección podrás sugerir propuestas de gasto que irán asociadas a las partidas de presupuestos ciudadanos.<br>El requisito principal es que sean propuestas presupuestables.
title: Presupuestos participativos title: Presupuestos participativos
verified_only: Sólo los usuarios verificados pueden crear propuestas de gasto, %{verify_account}. unfeasible: Propuestas de inversión no viables
verify_account: verifica tu cuenta by_geozone: "Propuestas de inversión con ámbito: %{geozone}"
search_form:
button: Buscar
placeholder: Propuestas de inversión...
title: Buscar
search_results:
one: " que contiene '%{search_term}'"
other: " que contienen '%{search_term}'"
sidebar:
geozones: Ámbitos de actuación
feasibility: Viabilidad
unfeasible: No viables
start_spending_proposal: Crea una propuesta de inversión
new: new:
back_link: Volver
more_info: "¿Cómo funcionan los presupuestos participativos?" more_info: "¿Cómo funcionan los presupuestos participativos?"
recommendation_one: Es fundamental que haga referencia a una actuación presupuestable. recommendation_one: Es fundamental que haga referencia a una actuación presupuestable.
recommendation_three: Intenta detallar lo máximo posible la propuesta para que el equipo de gobierno encargado de estudiarla tenga las menor dudas posibles. recommendation_three: Intenta detallar lo máximo posible la propuesta para que el equipo de gobierno encargado de estudiarla tenga las menor dudas posibles.
recommendation_two: Cualquier propuesta o comentario que implique acciones ilegales será eliminada. recommendation_two: Cualquier propuesta o comentario que implique acciones ilegales será eliminada.
recommendations_title: Cómo crear una propuesta de gasto recommendations_title: Cómo crear una propuesta de gasto
start_new: Crear una propuesta de gasto start_new: Crear una propuesta de gasto
back_link: Volver
show:
author_deleted: Usuario eliminado
code: 'Código de la propuesta:'
share: Compartir
wrong_price_format: Solo puede incluir caracteres numéricos wrong_price_format: Solo puede incluir caracteres numéricos
spending_proposal:
spending_proposal: Propuesta de inversión
already_supported: Ya has apoyado este proyecto. ¡Compártelo!
support: Apoyar
support_title: Apoyar este proyecto
supports:
one: 1 apoyo
other: "%{count} apoyos"
zero: Sin apoyos
stats: stats:
index: index:
visits: Visitas visits: Visitas
@@ -476,6 +500,12 @@ es:
unauthenticated: Necesitas %{signin} o %{signup} para continuar. unauthenticated: Necesitas %{signin} o %{signup} para continuar.
verified_only: Las propuestas sólo pueden ser votadas por usuarios verificados, %{verify_account}. verified_only: Las propuestas sólo pueden ser votadas por usuarios verificados, %{verify_account}.
verify_account: verifica tu cuenta verify_account: verifica tu cuenta
spending_proposals:
not_logged_in: Necesitas %{signin} o %{signup} para continuar.
not_verified: Las propuestas de inversión sólo pueden ser apoyadas por usuarios verificados, %{verify_account}.
organization: Las organizaciones no pueden votar.
unfeasible: No se pueden votar propuestas inviables.
not_voting_allowed: El periodo de votación está cerrado.
welcome: welcome:
debates: debates:
alt: Icono debates alt: Icono debates
@@ -512,6 +542,7 @@ es:
omniauth: omniauth:
finish_signup: finish_signup:
title: "Detalles adicionales de tu cuenta" title: "Detalles adicionales de tu cuenta"
username_warning: "Debido a que hemos cambiado la forma en la que nos conectamos con redes sociales y es posible que tu nombre de usuario aparezca como 'ya en uso', incluso si antes podías acceder con él. Si es tu caso, por favor elige un nombre de usuario distinto."
twitter: twitter:
sign_in: "Entra con Twitter" sign_in: "Entra con Twitter"
sign_up: "Regístrate con Twitter" sign_up: "Regístrate con Twitter"

View File

@@ -20,3 +20,13 @@ en:
new_reply_by_html: There is a new response from <b>%{commenter}</b> to your comment on new_reply_by_html: There is a new response from <b>%{commenter}</b> to your comment on
subject: Someone has responded to your comment subject: Someone has responded to your comment
title: New response to your comment title: New response to your comment
unfeasible_spending_proposal:
hi: "Dear user,"
new_html: "For all these, we invite you to elaborate a <strong>new proposal</strong> that ajusts to the conditions of this process. You can do it following this link: %{url}."
new_href: "new investment project"
reconsider_html: "If you believe that the rejected proposal meets the requirements to be an investment proposal, you can communicate this, within 48 hours, responding to the email address preparticipativos@madrid.es. Including the code %{code} in the subject of the email."
sincerely: "Sincerely"
signatory: "DEPARTMENT OF PUBLIC PARTICIPATION"
sorry: "Sorry for the inconvenience and we again thank you for your invaluable participation."
subject: "Your investment project '%{code}' has been marked as unfeasible"
unfeasible_html: "From the Madrid City Council we want to thank you for your participation in the <strong>participatory budgets of the city of Madrid</strong>. We regret to inform you that your proposal <strong>'%{title}'</strong> will be excluded from this participatory process for the following reason:"

View File

@@ -20,3 +20,13 @@ es:
new_reply_by_html: Hay una nueva respuesta de <b>%{commenter}</b> a tu comentario en new_reply_by_html: Hay una nueva respuesta de <b>%{commenter}</b> a tu comentario en
subject: Alguien ha respondido a tu comentario subject: Alguien ha respondido a tu comentario
title: Nueva respuesta a tu comentario title: Nueva respuesta a tu comentario
unfeasible_spending_proposal:
hi: "Estimado usuario,"
new_html: "Por todo ello, te invitamos a que elabores una <strong>nueva propuesta</strong> que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}."
new_href: "nueva propuesta de inversión"
reconsider_html: "Si consideras que la propuesta rechazada cumple los requisitos para mantenerla como propuesta de inversión, podrás comunicarlo, en el plazo de 48 horas, al correo preparticipativos@madrid.es, indicando necesariamente para su tramitación el código %{code} como asunto del correo, correspondiente a tu propuesta."
sincerely: "Atentamente"
signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA"
sorry: "Sentimos las molestias ocasionadas y volvemos a darte las gracias por tu inestimable participación."
subject: "Tu propuesta de inversión '%{code}' ha sido marcada como inviable"
unfeasible_html: "Desde el Ayuntamiento de Madrid queremos agradecer tu participación en los <strong>Presupuestos Participativos de la ciudad de Madrid</strong>. Lamentamos informarte de que tu propuesta <strong>'%{title}'</strong> quedará excluida de este proceso participativo por el siguiente motivo:"

View File

@@ -1,6 +1,11 @@
--- ---
en: en:
management: management:
account:
alert:
unverified_user: No verified user logged in yet
show:
title: User account
account_info: account_info:
change_user: Change user change_user: Change user
document_number_label: 'Document number:' document_number_label: 'Document number:'
@@ -12,6 +17,7 @@ en:
dashboard: dashboard:
index: index:
title: Management title: Management
info: Here you can manage users through all actions listed in the left menu.
document_number: Document number document_number: Document number
document_type_label: Document type document_type_label: Document type
document_verifications: document_verifications:
@@ -41,17 +47,22 @@ en:
print_proposals: Print proposals print_proposals: Print proposals
support_proposals: Support proposals support_proposals: Support proposals
create_spending_proposal: Create spending proposal create_spending_proposal: Create spending proposal
print_spending_proposals: Print spending proposals
support_spending_proposals: Support spending proposals
title: Management title: Management
users: Users users: Users
edit_user_accounts: Edit user account
permissions: permissions:
create_proposals: Create proposals create_proposals: Create proposals
debates: Engage in debates debates: Engage in debates
support_proposals: Support proposals support_proposals: Support proposals
vote_proposals: Vote proposals vote_proposals: Vote proposals
print: print:
info: Create yor proposal on http://decide.madrid.es proposals_info: Create yor proposal on http://decide.madrid.es
note: The proposals more supported will be voted. If are accepted by a majority, the city Council shall be carried out. proposals_note: The proposals more supported will be voted. If are accepted by a majority, the city Council shall be carried out.
proposals_title: 'Proposals:' proposals_title: 'Proposals:'
spending_proposals_info: Participate at http://decide.madrid.es
spending_proposals_note: Participatory budget will be assigned to the most votes spending proposals.
print_info: Print this info print_info: Print this info
proposals: proposals:
alert: alert:
@@ -63,6 +74,14 @@ en:
alert: alert:
unverified_user: User is not verified unverified_user: User is not verified
create: Create spending proposal create: Create spending proposal
filters:
unfeasible: Unfeasible investment projects
by_geozone: "Investment projects with scope: %{geozone}"
print:
print_button: Print
search_results:
one: " containing the term '%{search_term}'"
other: " containing the term '%{search_term}'"
sessions: sessions:
signed_out: Signed out successfully. signed_out: Signed out successfully.
signed_out_managed_user: User session signed out successfully. signed_out_managed_user: User session signed out successfully.
@@ -72,3 +91,9 @@ en:
create_user_info: 'We will create an account with the following data:' create_user_info: 'We will create an account with the following data:'
create_user_submit: Create user create_user_submit: Create user
create_user_success_html: We have sent an email to the email address <b>%{email}</b> in order to verify that it belongs to this user. It contains a link they have to click. Then they will have to set their access password before being able to log in to the website create_user_success_html: We have sent an email to the email address <b>%{email}</b> in order to verify that it belongs to this user. It contains a link they have to click. Then they will have to set their access password before being able to log in to the website
erased_notice: User account deleted.
erased_by_manager: "Deleted by manager: %{manager}"
erase_account_link: Delete user
erase_account_confirm: Are you sure you want to erase the account? This action can not be undone
erase_warning: This action can not be undone. Please make sure you want to erase this account.
erase_submit: Delete account

View File

@@ -1,6 +1,11 @@
--- ---
es: es:
management: management:
account:
alert:
unverified_user: Solo se pueden editar cuentas de usuarios verificados
show:
title: Cuenta de usuario
account_info: account_info:
change_user: Cambiar usuario change_user: Cambiar usuario
document_number_label: 'Número de documento:' document_number_label: 'Número de documento:'
@@ -12,6 +17,7 @@ es:
dashboard: dashboard:
index: index:
title: Gestión title: Gestión
info: Desde aquí puedes gestionar usuarios a través de las acciones listadas en el menú de la izquierda.
document_number: Número de documento document_number: Número de documento
document_type_label: Tipo de documento document_type_label: Tipo de documento
document_verifications: document_verifications:
@@ -40,18 +46,23 @@ es:
create_proposal: Crear propuesta create_proposal: Crear propuesta
print_proposals: Imprimir propuestas print_proposals: Imprimir propuestas
support_proposals: Apoyar propuestas support_proposals: Apoyar propuestas
create_spending_proposal: Crear propuesta de gasto create_spending_proposal: Crear propuesta de inversión
print_spending_proposals: Imprimir propts. de inversión
support_spending_proposals: Apoyar propts. de inversión
title: Gestión title: Gestión
users: Usuarios users: Usuarios
edit_user_accounts: Editar cuenta de usuario
permissions: permissions:
create_proposals: Crear nuevas propuestas create_proposals: Crear nuevas propuestas
debates: Participar en debates debates: Participar en debates
support_proposals: Apoyar propuestas support_proposals: Apoyar propuestas
vote_proposals: Participar en las votaciones finales vote_proposals: Participar en las votaciones finales
print: print:
info: Haz tu propuesta en http://decide.madrid.es proposals_info: Haz tu propuesta en http://decide.madrid.es
note: Las propuestas más apoyadas serán llevadas a votación. Y si las acepta una mayoría, el Ayuntamiento las llevará a cabo. proposals_note: Las propuestas más apoyadas serán llevadas a votación. Y si las acepta una mayoría, el Ayuntamiento las llevará a cabo.
proposals_title: 'Propuestas:' proposals_title: 'Propuestas:'
spending_proposals_info: Participa en http://decide.madrid.es
spending_proposals_note: Los presupuestos participativos se invertirán en las propuestas de inversión más apoyadas.
print_info: Imprimir esta información print_info: Imprimir esta información
proposals: proposals:
alert: alert:
@@ -62,7 +73,15 @@ es:
spending_proposals: spending_proposals:
alert: alert:
unverified_user: Este usuario no está verificado unverified_user: Este usuario no está verificado
create: Crear propuesta de gasto create: Crear propuesta de inversión
filters:
unfeasible: Propuestas de inversión no viables
by_geozone: "Propuestas de inversión con ámbito: %{geozone}"
print:
print_button: Imprimir
search_results:
one: " que contiene '%{search_term}'"
other: " que contienen '%{search_term}'"
sessions: sessions:
signed_out: Has cerrado la sesión correctamente. signed_out: Has cerrado la sesión correctamente.
signed_out_managed_user: Se ha cerrado correctamente la sesión del usuario. signed_out_managed_user: Se ha cerrado correctamente la sesión del usuario.
@@ -72,3 +91,9 @@ es:
create_user_info: 'Procedemos a crear un usuario con la siguiente información:' create_user_info: 'Procedemos a crear un usuario con la siguiente información:'
create_user_submit: Crear usuario create_user_submit: Crear usuario
create_user_success_html: Hemos enviado un correo electrónico a <b>%{email}</b> para verificar que es suya. El correo enviado contiene un link que el usuario deberá pulsar. Entonces podrá seleccionar una clave de acceso, y entrar en la web de participación. create_user_success_html: Hemos enviado un correo electrónico a <b>%{email}</b> para verificar que es suya. El correo enviado contiene un link que el usuario deberá pulsar. Entonces podrá seleccionar una clave de acceso, y entrar en la web de participación.
erased_notice: Cuenta de usuario borrada.
erased_by_manager: "Borrada por el manager: %{manager}"
erase_account_link: Borrar cuenta
erase_account_confirm: ¿Seguro que quieres borrar a este usuario? Esta acción no se puede deshacer
erase_warning: Esta acción no se puede deshacer. Por favor asegurese de que quiere eliminar esta cuenta.
erase_submit: Borrar cuenta

View File

@@ -15,4 +15,6 @@ en:
per_page_code: "Code to be included on every page" per_page_code: "Code to be included on every page"
feature: feature:
debates: Debates debates: Debates
spending_proposals: Spending proposals spending_proposals: Investment projects
spending_proposal_features:
voting_allowed: Voting on investment projects

View File

@@ -15,4 +15,6 @@ es:
per_page_code: "Código a incluir en cada página" per_page_code: "Código a incluir en cada página"
feature: feature:
debates: Debates debates: Debates
spending_proposals: Propuestas de gasto spending_proposals: Propuestas de inversión
spending_proposal_features:
voting_allowed: Votaciones sobre propuestas de inversión.

View File

@@ -83,7 +83,9 @@ en:
title: Security code confirmation title: Security code confirmation
new: new:
phone: Enter your mobile phone number to receive the code phone: Enter your mobile phone number to receive the code
phone_format_html: "<strong><em>(Example: 612345678 or +34612345678)</em></strong>"
phone_note: We only user your phone for send to you a code, we never contact to you. phone_note: We only user your phone for send to you a code, we never contact to you.
phone_placeholder: "Example: 612345678 or +34612345678"
submit_button: Send submit_button: Send
title: Send confirmation code title: Send confirmation code
update: update:

View File

@@ -83,7 +83,9 @@ es:
title: SMS de confirmación title: SMS de confirmación
new: new:
phone: Introduce tu teléfono móvil para recibir el código phone: Introduce tu teléfono móvil para recibir el código
phone_format_html: "<strong><em>(Ejemplo: 612345678 ó +34612345678)</em></strong>"
phone_note: Sólo usaremos tu teléfono para enviarte un código, nunca te contactaremos. phone_note: Sólo usaremos tu teléfono para enviarte un código, nunca te contactaremos.
phone_placeholder: "Ejemplo: 612345678 ó +34612345678"
submit_button: Enviar submit_button: Enviar
title: SMS de confirmación title: SMS de confirmación
update: update:

View File

@@ -66,7 +66,9 @@ Rails.application.routes.draw do
end end
scope '/participatory_budget' do scope '/participatory_budget' do
resources :spending_proposals, only: [:index, :new, :create, :show, :destroy], path: 'investment_projects' resources :spending_proposals, only: [:index, :new, :create, :show, :destroy], path: 'investment_projects' do
post :vote, on: :member
end
end end
resources :stats, only: [:index] resources :stats, only: [:index]
@@ -74,19 +76,17 @@ Rails.application.routes.draw do
resources :legislations, only: [:show] resources :legislations, only: [:show]
resources :annotations do resources :annotations do
collection do get :search, on: :collection
get :search
end
end end
resources :users, only: [:show] resources :users, only: [:show]
resource :account, controller: "account", only: [:show, :update, :delete] do resource :account, controller: "account", only: [:show, :update, :delete] do
collection { get :erase } get :erase, on: :collection
end end
resources :notifications, only: [:index, :show] do resources :notifications, only: [:index, :show] do
collection { put :mark_all_as_read } put :mark_all_as_read, on: :collection
end end
resource :verification, controller: "verification", only: [:show] resource :verification, controller: "verification", only: [:show]
@@ -102,7 +102,7 @@ Rails.application.routes.draw do
namespace :admin do namespace :admin do
root to: "dashboard#index" root to: "dashboard#index"
resources :organizations, only: :index do resources :organizations, only: :index do
collection { get :search } get :search, on: :collection
member do member do
put :verify put :verify
put :reject put :reject
@@ -146,20 +146,20 @@ Rails.application.routes.draw do
resources :tags, only: [:index, :create, :update, :destroy] resources :tags, only: [:index, :create, :update, :destroy]
resources :officials, only: [:index, :edit, :update, :destroy] do resources :officials, only: [:index, :edit, :update, :destroy] do
collection { get :search} get :search, on: :collection
end end
resources :settings, only: [:index, :update] resources :settings, only: [:index, :update]
resources :moderators, only: [:index, :create, :destroy] do resources :moderators, only: [:index, :create, :destroy] do
collection { get :search } get :search, on: :collection
end end
resources :valuators, only: [:index, :create] do resources :valuators, only: [:index, :create] do
collection { get :search } get :search, on: :collection
end end
resources :verifications, controller: :verifications, only: :index do resources :verifications, controller: :verifications, only: :index do
collection { get :search} get :search, on: :collection
end end
resource :activity, controller: :activity, only: :show resource :activity, controller: :activity, only: :show
@@ -181,30 +181,18 @@ Rails.application.routes.draw do
end end
resources :debates, only: :index do resources :debates, only: :index do
member do put :hide, on: :member
put :hide put :moderate, on: :collection
end
collection do
put :moderate
end
end end
resources :proposals, only: :index do resources :proposals, only: :index do
member do put :hide, on: :member
put :hide put :moderate, on: :collection
end
collection do
put :moderate
end
end end
resources :comments, only: :index do resources :comments, only: :index do
member do put :hide, on: :member
put :hide put :moderate, on: :collection
end
collection do
put :moderate
end
end end
end end
@@ -212,9 +200,7 @@ Rails.application.routes.draw do
root to: "spending_proposals#index" root to: "spending_proposals#index"
resources :spending_proposals, only: [:index, :show, :edit] do resources :spending_proposals, only: [:index, :show, :edit] do
member do patch :valuate, on: :member
patch :valuate
end
end end
end end
@@ -222,9 +208,7 @@ Rails.application.routes.draw do
root to: "dashboard#index" root to: "dashboard#index"
resources :document_verifications, only: [:index, :new, :create] do resources :document_verifications, only: [:index, :new, :create] do
collection do post :check, on: :collection
post :check
end
end end
resources :email_verifications, only: [:new, :create] resources :email_verifications, only: [:new, :create]
@@ -232,23 +216,24 @@ Rails.application.routes.draw do
resources :users, only: [:new, :create] do resources :users, only: [:new, :create] do
collection do collection do
delete :logout delete :logout
delete :erase
end end
end end
resource :account, controller: "account", only: [:show]
get 'sign_in', to: 'sessions#create' get 'sign_in', to: 'sessions#create'
resource :session, only: [:create, :destroy] resource :session, only: [:create, :destroy]
resources :proposals, only: [:index, :new, :create, :show] do resources :proposals, only: [:index, :new, :create, :show] do
member do post :vote, on: :member
post :vote get :print, on: :collection
end
collection do
get :print
end
end end
resources :spending_proposals, only: [:new, :create, :show] resources :spending_proposals, only: [:index, :new, :create, :show] do
post :vote, on: :member
get :print, on: :collection
end
end end
if Rails.env.development? if Rails.env.development?

View File

@@ -13,6 +13,7 @@ Setting.create(key: 'max_votes_for_debate_edit', value: '1000')
Setting.create(key: 'max_votes_for_proposal_edit', value: '1000') Setting.create(key: 'max_votes_for_proposal_edit', value: '1000')
Setting.create(key: 'proposal_code_prefix', value: 'MAD') Setting.create(key: 'proposal_code_prefix', value: 'MAD')
Setting.create(key: 'votes_for_proposal_success', value: '100') Setting.create(key: 'votes_for_proposal_success', value: '100')
Setting.create(key: 'comments_body_max_length', value: '1000')
Setting.create(key: 'blog_url', value: '/blog') Setting.create(key: 'blog_url', value: '/blog')
Setting.create(key: 'url', value: 'http://localhost:3000') Setting.create(key: 'url', value: 'http://localhost:3000')
@@ -20,6 +21,7 @@ Setting.create(key: 'org_name', value: 'Consul')
Setting.create(key: 'place_name', value: 'City') Setting.create(key: 'place_name', value: 'City')
Setting.create(key: 'feature.debates', value: "true") Setting.create(key: 'feature.debates', value: "true")
Setting.create(key: 'feature.spending_proposals', value: "true") Setting.create(key: 'feature.spending_proposals', value: "true")
Setting.create(key: 'feature.spending_proposal_features.voting_allowed', value: "true")
Setting.create(key: 'feature.twitter_login', value: "true") Setting.create(key: 'feature.twitter_login', value: "true")
Setting.create(key: 'feature.facebook_login', value: "true") Setting.create(key: 'feature.facebook_login', value: "true")
Setting.create(key: 'feature.google_login', value: "true") Setting.create(key: 'feature.google_login', value: "true")
@@ -46,6 +48,12 @@ moderator.create_moderator
valuator = create_user('valuator@madrid.es', 'valuator') valuator = create_user('valuator@madrid.es', 'valuator')
valuator.create_valuator valuator.create_valuator
level_2 = create_user('leveltwo@madrid.es', 'level 2')
level_2.update(residence_verified_at: Time.now, confirmed_phone: Faker::PhoneNumber.phone_number, document_number: "2222222222", document_type: "1" )
verified = create_user('verified@madrid.es', 'verified')
verified.update(residence_verified_at: Time.now, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.now, document_number: "3333333333")
(1..10).each do |i| (1..10).each do |i|
org_name = Faker::Company.name org_name = Faker::Company.name
org_user = create_user("org#{i}@madrid.es", org_name) org_user = create_user("org#{i}@madrid.es", org_name)

View File

@@ -0,0 +1,5 @@
class AddUnfeasibleEmailSentAtToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :unfeasible_email_sent_at, :datetime, default: nil
end
end

View File

@@ -0,0 +1,5 @@
class AddVotesUpToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :cached_votes_up, :integer, default: 0
end
end

View File

@@ -0,0 +1,8 @@
class AddTsvectorToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :tsv, :tsvector
add_index :spending_proposals, :tsv, using: "gin"
end
end

View File

@@ -0,0 +1,5 @@
class AddResponsibleNameToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :responsible_name, :string, limit: 60
end
end

View File

@@ -0,0 +1,6 @@
class AddGenreAndDobToUsers < ActiveRecord::Migration
def change
add_column :users, :genre, :string, index: true, limit: 10
add_column :users, :date_of_birth, :datetime, index: true
end
end

View File

@@ -0,0 +1,5 @@
class RenameGenreToGender < ActiveRecord::Migration
def change
rename_column :users, :genre, :gender
end
end

Some files were not shown because too many files have changed in this diff Show More