fixes conflicts with master

This commit is contained in:
rgarcia
2016-03-08 14:31:18 +01:00
47 changed files with 1430 additions and 244 deletions

View File

@@ -168,7 +168,7 @@ body.admin {
clear: both;
.checkbox {
font-size: rem-calc(12);
font-size: $small-font-size;
}
}

View File

@@ -378,39 +378,59 @@ header {
padding-bottom: 0;
}
a {
color: white;
display: inline-block;
line-height: rem-calc(46);
position: relative;
text-align: left;
width: 100%;
@media (min-width: $small-breakpoint) {
color: $text;
font-weight: bold;
margin-right: $line-height*1.5;
margin-right: 12px\9;
width: auto;
&:hover {
color: $link;
}
}
&.active {
color: white;
ul {
list-style-type: none;
margin: 0;
li {
@media (min-width: $small-breakpoint) {
border-bottom: 2px solid $brand;
color: $brand;
display: inline-block;
margin-right: rem-calc(36);
}
a {
color: white;
display: inline-block;
line-height: $line-height*2;
position: relative;
text-align: left;
width: 100%;
@media (min-width: $small-breakpoint) {
color: $text;
display: block;
font-weight: bold;
margin-left: 18px\9;
margin-right: 18px\9;
width: auto;
&:hover {
color: $link;
}
}
&.active {
color: white;
@media (min-width: $small-breakpoint) {
border-bottom: 2px solid $brand;
color: $brand;
}
}
}
}
}
span {
color: $border;
}
.input-group {
margin-bottom: 0;
padding-top: $line-height/4;
@media (min-width: $small-breakpoint) {
margin-bottom: 0;
}
}
.input-group-field {
@@ -606,6 +626,12 @@ form.locale-form {
display: inline-block;
position: relative;
label {
color: white;
font-size: $small-font-size;
font-weight: normal;
}
select {
background-image: image-url("language_select.png");
background-origin: border-box;
@@ -628,6 +654,7 @@ form.locale-form {
outline: none;
padding-left: rem-calc(3);
padding-right: $line-height;
width: auto;
}
}
}
@@ -641,6 +668,10 @@ form {
line-height: $line-height;
}
fieldset legend {
font-weight: bold;
}
input, textarea {
height: 48px\9;
line-height: 48px\9;
@@ -648,13 +679,28 @@ form {
width: 100%\9;
}
input[type="checkbox"] {
input[type="checkbox"],
input[type="radio"] {
height: auto\9;
line-height: inherit\9;
width: auto\9;
}
input[type]:not([type=submit]):not([type=file]):not([type=checkbox]) {
input[type="radio"] {
height: $line-height !important;
vertical-align: top;
width: 18px\9;
+ label {
font-weight: normal;
}
&:checked + label {
font-weight: bold;
}
}
input[type]:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]) {
background: $input-bg;
height: $line-height*2;
margin-bottom: rem-calc(16);
@@ -1035,10 +1081,15 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar {
// - - - - - - - - - - - - - - - - - - - - - - - - -
table {
border: $border;
border-collapse: collapse;
border-spacing: 0;
width: 100%;
th {
background: #f8f9fb;
}
tr {
td {
@@ -1047,7 +1098,11 @@ table {
}
&:nth-child(odd) {
background: #F0F2F6;
background: white;
}
&:nth-child(even) {
background: #fafcfb;
}
}

View File

@@ -0,0 +1,15 @@
class Valuation::BaseController < ApplicationController
layout 'admin'
before_action :authenticate_user!
before_action :verify_valuator
skip_authorization_check
private
def verify_valuator
raise CanCan::AccessDenied unless current_user.try(:valuator?) || current_user.try(:administrator?)
end
end

View File

@@ -0,0 +1,38 @@
class Valuation::SpendingProposalsController < Valuation::BaseController
include FeatureFlags
feature_flag :spending_proposals
before_action :restrict_access_to_assigned_items, only: [:show, :edit, :valuate]
has_filters %w{valuating valuation_finished}, only: :index
load_and_authorize_resource
def index
if current_user.valuator?
@spending_proposals = SpendingProposal.search(params_for_current_valuator, @current_filter).order(created_at: :desc).page(params[:page])
else
@spending_proposals = SpendingProposal.none.page(params[:page])
end
end
def valuate
@spending_proposal.update_attributes(valuation_params)
redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate')
end
private
def valuation_params
params.require(:spending_proposal).permit(:price, :price_first_year, :price_explanation, :feasible, :feasible_explanation, :time_scope, :valuation_finished, :internal_comments)
end
def params_for_current_valuator
params.merge({valuator_id: current_user.valuator.id})
end
def restrict_access_to_assigned_items
raise ActionController::RoutingError.new('Not Found') unless current_user.administrator? || ValuationAssignment.exists?(spending_proposal_id: params[:id], valuator_id: current_user.valuator.id)
end
end

View File

@@ -11,4 +11,8 @@ module TextWithLinksHelper
Rinku.auto_link(html, :all, 'target="_blank" rel="nofollow"').html_safe
end
def simple_format_no_tags_no_sanitize(html)
simple_format(html, {}, sanitize: false)
end
end

View File

@@ -0,0 +1,30 @@
module ValuationHelper
def valuator_select_options(valuator=nil)
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])
else
Valuator.all.order('users.username asc').includes(:user).collect { |v| [ v.name, v.id ] }
end
end
def assigned_valuators_info(valuators)
case valuators.size
when 0
t("valuation.spending_proposals.index.no_valuators_assigned")
when 1
"<span title=\"#{t('valuation.spending_proposals.index.valuators_assigned', count: 1)}\">".html_safe +
valuators.first.name +
"</span>".html_safe
else
"<span title=\"".html_safe + valuators.map(&:name).join(', ') + "\">".html_safe +
t('valuation.spending_proposals.index.valuators_assigned', count: valuators.size) +
"</span>".html_safe
end
end
def explanation_field(field)
simple_format_no_tags_no_sanitize(safe_html_with_links(field.html_safe)) if field.present?
end
end

View File

@@ -4,6 +4,7 @@ module Abilities
def initialize(user)
self.merge Abilities::Moderation.new(user)
self.merge Abilities::Valuator.new(user)
can :restore, Comment
cannot :restore, Comment, hidden_at: nil

View File

@@ -36,6 +36,7 @@ class SpendingProposal < ActiveRecord::Base
results = results.by_geozone(params[:geozone_id]) if params[:geozone_id].present?
results = results.by_administrator(params[:administrator_id]) if params[:administrator_id].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.send(current_filter) if current_filter.present?
results.for_render
end
@@ -52,10 +53,15 @@ class SpendingProposal < ActiveRecord::Base
where(administrator_id: administrator.presence)
end
def self.by_tag(tag_name)
tagged_with(tag_name)
end
def self.by_valuator(valuator)
joins(:valuation_assignments).includes(:valuators).where("valuation_assignments.valuator_id = ?", valuator.presence)
end
def feasibility
case feasible
when true

View File

@@ -76,6 +76,10 @@
<p><strong><%= t("admin.spending_proposals.show.price") %> (<%= t("admin.spending_proposals.show.currency") %>):</strong>
<%= @spending_proposal.price.present? ? @spending_proposal.price : t("admin.spending_proposals.show.undefined") %>
</p>
<p><strong><%= t("admin.spending_proposals.show.price_first_year") %> (<%= t("admin.spending_proposals.show.currency") %>):</strong>
<%= @spending_proposal.price_first_year.present? ? @spending_proposal.price_first_year : t("admin.spending_proposals.show.undefined") %>
</p>
<%= simple_format(safe_html_with_links(@spending_proposal.price_explanation.html_safe), {}, sanitize: false) if @spending_proposal.price_explanation.present? %>
<p><strong><%= t("admin.spending_proposals.show.feasibility") %>:</strong>

View File

@@ -43,7 +43,7 @@
<div class="small-12 medium-3 column">
<aside class="margin-bottom" role="complementary">
<aside class="margin-bottom">
<%= link_to t("debates.index.start_debate"), new_debate_path, class: 'button expanded' %>
<%= render "shared/tag_cloud", taggable: 'debate' %>
</aside>

View File

@@ -1,20 +1,20 @@
<% if user_signed_in? %>
<li>
<%= link_to notifications_path, class: "notifications" do %>
<%= link_to notifications_path, class: "notifications", accesskey: "n" do %>
<% if current_user.notifications_count > 0 %>
<i class="icon-circle"></i>
<i class="icon-notification" title="<%= t('layouts.header.new_notifications', count: current_user.notifications_count).html_safe %>">
<i class="icon-circle" aria-hidden="true"></i>
<i class="icon-notification" aria-hidden="true" title="<%= t('layouts.header.new_notifications', count: current_user.notifications_count).html_safe %>">
</i>
<% else %>
<i class="icon-no-notification" title="<%= t('layouts.header.no_notifications') %>"></i>
<i class="icon-no-notification" aria-hidden="true" title="<%= t('layouts.header.no_notifications') %>"></i>
<% end %>
<% end %>
</li>
<li>
<%= link_to(t("layouts.header.my_activity_link"), user_path(current_user)) %>
<%= link_to(t("layouts.header.my_activity_link"), user_path(current_user), accesskey: "a") %>
</li>
<li>
<%= link_to(t("layouts.header.my_account_link"), account_path) %>
<%= link_to(t("layouts.header.my_account_link"), account_path, accesskey: "m") %>
</li>
<li>
<%= link_to(t("devise_views.menu.login_items.logout"), destroy_user_session_path, method: :delete) %>

View File

@@ -1,82 +1,91 @@
<footer>
<div class="row-full">
<div class="row">
<div class="row">
<div class="small-12 large-4 column">
<h1 class="logo">
<%= link_to t("layouts.header.open_gov", open: "#{t('layouts.header.open')}").html_safe %>
</h1>
<div class="small-12 large-4 column">
<h1 class="logo">
<%= link_to t("layouts.header.open_gov", open: "#{t('layouts.header.open')}").html_safe %>
</h1>
<p class="info">
<%= t("layouts.footer.description",
open_source: link_to(t("layouts.footer.open_source"), t("layouts.footer.open_source_url"), target: "blank"),
consul: link_to(t("layouts.footer.consul"), t("layouts.footer.consul_url"), target: "blank")).html_safe
%>
<%= t("layouts.footer.contact_us") %>
<%= link_to t("layouts.footer.faq"), page_path('faq') %>
</p>
</div>
<div class="footer-sections small-12 large-8 column">
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.participation_title"), root_path %>
</h2>
<p><%= t("layouts.footer.participation_text") %></p>
</div>
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.transparency_title"), t("layouts.footer.transparency_url") %>
</h2>
<p><%= t("layouts.footer.transparency_text") %></p>
</div>
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.open_data_title"), "/opendata" %>
</h2>
<p><%= t("layouts.footer.open_data_text") %></p>
</div>
</div>
<p class="info">
<%= t("layouts.footer.description",
open_source: link_to(t("layouts.footer.open_source"), t("layouts.footer.open_source_url"), target: "blank"),
consul: link_to(t("layouts.footer.consul"), t("layouts.footer.consul_url"), target: "blank")).html_safe
%>
<%= t("layouts.footer.contact_us") %>
<%= link_to t("layouts.footer.faq"), page_path('faq') %>
</p>
</div>
<div class="subfooter row">
<div class="small-12 medium-9 column">
<p>
<%= t("layouts.footer.copyright", year: Time.now.year) %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.more_info"), page_path('more_information') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.privacy"), page_path('privacy') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.conditions"), page_path('conditions') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.accessibility"), page_path('accessibility') %>
</p>
<div class="footer-sections small-12 large-8 column">
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.participation_title"), root_path %>
</h2>
<p><%= t("layouts.footer.participation_text") %></p>
</div>
<div class="small-12 medium-3 column social">
<% if setting['twitter_handle'] %>
<%= link_to "https://twitter.com/#{setting['twitter_handle']}", target: "_blank", title: t("social.twitter") do %>
<span class="sr-only"><%= t("social.twitter") %></span>
<i class="icon-twitter"></i>
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.transparency_title"), t("layouts.footer.transparency_url") %>
</h2>
<p><%= t("layouts.footer.transparency_text") %></p>
</div>
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.open_data_title"), "/opendata" %>
</h2>
<p><%= t("layouts.footer.open_data_text") %></p>
</div>
</div>
</div>
<div class="subfooter row">
<div class="small-12 medium-8 column">
<p>
<%= t("layouts.footer.copyright", year: Time.now.year) %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.more_info"), page_path('more_information') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.privacy"), page_path('privacy') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.conditions"), page_path('conditions') %>&nbsp;|&nbsp;
<%= link_to t("layouts.footer.accessibility"), page_path('accessibility') %>
</p>
</div>
<div class="small-12 medium-4 column social">
<div class="text-right">
<ul>
<% if setting['twitter_handle'] %>
<li class="inline-block">
<%= link_to "https://twitter.com/#{setting['twitter_handle']}", target: "_blank", title: t("social.twitter") do %>
<span class="sr-only"><%= t("social.twitter") %></span>
<i class="icon-twitter" aria-hidden="true"></i>
<% end %>
</li>
<% end %>
<% end %>
<% if setting['facebook_handle'] %>
<%= link_to "https://www.facebook.com/#{setting['facebook_handle']}/", target: "_blank", title: t("social.facebook") do %>
<span class="sr-only"><%= t("social.facebook") %></span>
<i class="icon-facebook"></i>
<% if setting['facebook_handle'] %>
<li class="inline-block">
<%= link_to "https://www.facebook.com/#{setting['facebook_handle']}/", target: "_blank", title: t("social.facebook") do %>
<span class="sr-only"><%= t("social.facebook") %></span>
<i class="icon-facebook" aria-hidden="true"></i>
<% end %>
</li>
<% end %>
<% end %>
<% if setting['blog_url'] %>
<%= link_to setting['blog_url'], target: "_blank", title: t("social.blog") do %>
<span class="sr-only"><%= t("social.blog") %></span>
<i class="icon-blog"></i>
<% if setting['blog_url'] %>
<li class="inline-block">
<%= link_to setting['blog_url'], target: "_blank", title: t("social.blog") do %>
<span class="sr-only"><%= t("social.blog") %></span>
<i class="icon-blog" aria-hidden="true"></i>
<% end %>
</li>
<% end %>
<% end %>
<% if setting['youtube_handle'] %>
<%= link_to "https://www.youtube.com/#{setting['youtube_handle']}", target: "_blank", title: t("social.youtube") do %>
<span class="sr-only"><%= t("social.youtube") %></span>
<i class="icon-youtube"></i>
<% if setting['youtube_handle'] %>
<li class="inline-block">
<%= link_to "https://www.youtube.com/#{setting['youtube_handle']}", target: "_blank", title: t("social.youtube") do %>
<span class="sr-only"><%= t("social.youtube") %></span>
<i class="icon-youtube" aria-hidden="true"></i>
<% end %>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>
</div>

View File

@@ -14,7 +14,7 @@
<div id="responsive-menu">
<div class="top-bar-title">
<%= link_to root_path, class: "hide-for-small-only" do %>
<%= link_to root_path, class: "hide-for-small-only", accesskey: "/" do %>
<%= image_tag('header_logo_madrid.png', class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %>
<% if opendata_page? %>
<%= t("layouts.header.open_gov", open: "#{t('layouts.header.open')}") %> <span>|</span>
@@ -34,6 +34,9 @@
<div class="show-for-small-only">
<div class="subnavigation row">
<%= render "shared/subnavigation" %>
<div class="small-12 medium-3 column">
<%= yield :header_addon %>
</div>
</div>
</div>
</div>
@@ -45,9 +48,9 @@
<div class="row">
<div class="hide-for-small-only">
<%= render "shared/subnavigation" %>
</div>
<div class="small-12 medium-3 column">
<%= yield :header_addon %>
<div class="small-12 medium-3 column">
<%= yield :header_addon %>
</div>
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<div class="row">
<div class="small-12 column">
<h1 class="float-left margin-top"><%= t("notifications.index.title") %></h1>
<h1 class="float-left"><%= t("notifications.index.title") %></h1>
<% if @notifications.empty? %>
<div data-alert class="callout primary margin-top clear">

View File

@@ -1,18 +1,148 @@
<% provide :title do %><%= t('pages.titles.accessibility') %><% end %>
<div class="page row-full">
<div class="row">
<div class="text small-12 column">
<h1>Accesibilidad</h1>
<p>La accesibilidad web se refiere a la posibilidad de acceso a la web y a sus contenidos por todas las personas, independientemente de las discapacidades (físicas, intelectuales o técnicas) que puedan presentar o de las que se deriven del contexto de uso (tecnológicas o ambientales).</p>
<div class="row">
<div class="small-12 column">
<h1>Accesibilidad</h1>
<p>La accesibilidad web se refiere a la posibilidad de acceso a la web y a sus contenidos por todas las personas, independientemente de las discapacidades (físicas, intelectuales o técnicas) que puedan presentar o de las que se deriven del contexto de uso (tecnológicas o ambientales).</p>
<p>Cuando los sitios web están diseñados pensando en la accesibilidad, todos los usuarios pueden acceder en condiciones de igualdad a los contenidos, por ejemplo:</p>
<p>Cuando los sitios web están diseñados pensando en la accesibilidad, todos los usuarios pueden acceder en condiciones de igualdad a los contenidos, por ejemplo:</p>
<ul>
<li>Proporcionando un texto alternativo a las imágenes, los usuarios invidentes o con problemas de visión pueden utilizar lectores especiales para acceder a la información. </li>
<li>Cuando los vídeos disponen de subtítulos, los usuarios con dificultades auditivas pueden entenderlos plenamente. </li>
<li>Si los contenidos están escritos en un lenguaje sencillo e ilustrados, los usuarios con problemas de aprendizaje están en mejores condiciones de entenderlos.</li>
<li>Si el usuario tiene problemas de movilidad y le cuesta usar el ratón, las alternativas con el teclado le ayudan en la navegación.</li>
</ul>
<h2>"Atajos" de teclado</h2>
<p>Para poder navegar por este sitio web de forma accesible, se han programado un grupo de teclas de acceso rápido que recogen las principales secciones de interés general en los que está organizado el sitio.</p>
<div class="small-12 medium-6">
<table>
<thead>
<tr>
<th class="text-center">Tecla</th>
<th>Página</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">/</td>
<td>Inicio</td>
</tr>
<tr>
<td class="text-center">D</td>
<td>Debates</td>
</tr>
<tr>
<td class="text-center">P</td>
<td>Propuestas</td>
</tr>
<tr>
<td class="text-center">S</td>
<td>Presupuestos ciudadanos</td>
</tr>
<tr>
<td class="text-center">I</td>
<td>Más información</td>
</tr>
<tr>
<td class="text-center">N</td>
<td>Notificaciones</td>
</tr>
<tr>
<td class="text-center">A</td>
<td>Mi actividad</td>
</tr>
<tr>
<td class="text-center">M</td>
<td>Mi cuenta</td>
</tr>
</tbody>
</table>
</div>
<p>Dependiendo del sistema operativo y del navegador que se utilice, la combinación de teclas será la siguiente:</p>
<div class="small-12 medium-6">
<table>
<thead>
<tr>
<th>Navegador</th>
<th>Combinación de teclas</th>
</tr>
</thead>
<tbody>
<tr>
<td>Explorer</td>
<td>ALT + atajo y luego ENTER</td>
</tr>
<tr>
<td>Firefox</td>
<td>ALT + MAYÚSCULAS + atajo</td>
</tr>
<tr>
<td>Chrome</td>
<td>ALT + atajo (si es un MAC, CTRL + ALT + atajo)</td>
</tr>
<tr>
<td>Safari</td>
<td>ALT + atajo (si es un MAC, CMD + atajo)</td>
</tr>
<tr>
<td>Opera</td>
<td>MAYÚSCULAS + ESC + atajo</td>
</tr>
</tbody>
</table>
</div>
<h2>Tamaño del texto</h2>
<p>El diseño accesible de este sitio web permite que el usuario pueda elegir el tamaño del texto que le convenga. Esta acción puede llevarse a cabo de diferentes maneras según el navegador que se utilice.</p>
<div class="small-12 medium-6">
<table>
<thead>
<tr>
<th>Navegador</th>
<th>Acción a realizar </th>
</tr>
</thead>
<tbody>
<tr>
<td>Explorer</td>
<td>Ver > Tamaño del texto</td>
</tr>
<tr>
<td>Firefox</td>
<td>Ver > Tamaño</td>
</tr>
<tr>
<td>Chrome</td>
<td>Ajustes (icono) > Opciones > Avanzada > Contenido web > Tamaño fuente</td>
</tr>
<tr>
<td>Safari</td>
<td>Visualización > ampliar/reducir</td>
</tr>
<tr>
<td>Opera</td>
<td>Ver > escala</td>
</tr>
</tbody>
</table>
</div>
<p>Otra forma de modificar el tamaño de texto es utilizar los atajos de teclado definidos en los navegadores, en particular la combinación de teclas:</p>
<ul>
<li><code>CTRL y + (CMD y + en MAC)</code> para aumentar el tamaño del texto</li>
<li><code> CTRL y - (CMD y - en MAC)</code> para reducir el tamaño del texto</li>
</ul>
<h2>Compatibilidad con estándares y diseño visual</h2>
<p>Todas las páginas de este sitio web cumplen con&nbsp; las <strong>Pautas de Accesibilidad</strong> o Principios Generales de Diseño Accesible establecidas por el Grupo de Trabajo&nbsp;<abbr title="Web Accessibility Initiative" lang="en">WAI</abbr> perteneciente al W3C.</p>
<ul>
<li>Proporcionando un texto alternativo a las imágenes, los usuarios invidentes o con problemas de visión pueden utilizar lectores especiales para acceder a la información. </li>
<li>Cuando los vídeos disponen de subtítulos, los usuarios con dificultades auditivas pueden entenderlos plenamente. </li>
<li>Si los contenidos están escritos en un lenguaje sencillo e ilustrados, los usuarios con problemas de aprendizaje están en mejores condiciones de entenderlos.</li>
<li>Si el usuario tiene problemas de movilidad y le cuesta usar el ratón, las alternativas con el teclado le ayudan en la navegación.</li>
</ul>
</div>
</div>
</div>

View File

@@ -1,73 +1,71 @@
<% provide :title do %><%= t('pages.titles.more_information') %><% end %>
<div class="page row-full">
<div class="row">
<div class="more-information margin-top small-12 medium-7 column">
<h1><%= t('pages.titles.more_information') %></h1>
<ul class="no-bullet">
<li>
<%= link_to page_path('how_it_works') do %>
<%= t('pages.more_information.titles.how_it_works') %>
<br>
<span><%= t('pages.more_information.description.how_it_works') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('how_to_use') do %>
<%= t('pages.more_information.titles.how_to_use') %>
<br>
<span><%= t('pages.more_information.description.how_to_use') %></span>
<div class="row">
<div class="more-information small-12 medium-7 column">
<h1><%= t('pages.titles.more_information') %></h1>
<ul class="no-bullet">
<li>
<%= link_to page_path('how_it_works') do %>
<%= t('pages.more_information.titles.how_it_works') %>
<br>
<span><%= t('pages.more_information.description.how_it_works') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation') do %>
<%= t('pages.more_information.titles.participation') %>
<br>
<span><%= t('pages.more_information.description.participation') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('proposals_info') do %>
<%= t('pages.more_information.titles.proposals_info') %>
<br>
<span><%= t('pages.more_information.description.proposals_info') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('spending_proposals_info') do %>
<%= t('pages.more_information.titles.spending_proposals_info') %>
<br>
<span><%= t('pages.more_information.description.spending_proposals_info') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation_world') do %>
<%= t('pages.more_information.titles.participation_world') %>
<br>
<span><%= t('pages.more_information.description.participation_world') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation_facts') do %>
<%= t('pages.more_information.titles.participation_facts') %>
<br>
<span><%= t('pages.more_information.description.participation_facts') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('faq') do %>
<%= t('pages.more_information.titles.faq') %>
<br>
<span><%= t('pages.more_information.description.faq') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('proposals_info', :anchor => "iii") do %>
<%= t('pages.more_information.titles.signature_sheet') %>
<br>
<span><%= t('pages.more_information.description.signature_sheet') %></span>
<% end %>
</li>
</ul>
</div>
</li>
<li>
<%= link_to page_path('how_to_use') do %>
<%= t('pages.more_information.titles.how_to_use') %>
<br>
<span><%= t('pages.more_information.description.how_to_use') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation') do %>
<%= t('pages.more_information.titles.participation') %>
<br>
<span><%= t('pages.more_information.description.participation') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('proposals_info') do %>
<%= t('pages.more_information.titles.proposals_info') %>
<br>
<span><%= t('pages.more_information.description.proposals_info') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('spending_proposals_info') do %>
<%= t('pages.more_information.titles.spending_proposals_info') %>
<br>
<span><%= t('pages.more_information.description.spending_proposals_info') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation_world') do %>
<%= t('pages.more_information.titles.participation_world') %>
<br>
<span><%= t('pages.more_information.description.participation_world') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('participation_facts') do %>
<%= t('pages.more_information.titles.participation_facts') %>
<br>
<span><%= t('pages.more_information.description.participation_facts') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('faq') do %>
<%= t('pages.more_information.titles.faq') %>
<br>
<span><%= t('pages.more_information.description.faq') %></span>
<% end %>
</li>
<li>
<%= link_to page_path('proposals_info', :anchor => "iii") do %>
<%= t('pages.more_information.titles.signature_sheet') %>
<br>
<span><%= t('pages.more_information.description.signature_sheet') %></span>
<% end %>
</li>
</ul>
</div>
</div>

View File

@@ -51,7 +51,7 @@
</div>
<div class="small-12 medium-3 column">
<aside class="margin-bottom" role="complementary">
<aside class="margin-bottom">
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button expanded' %>
<%= render "shared/tag_cloud", taggable: 'proposal' %>
<%= render 'categories' %>

View File

@@ -46,7 +46,7 @@
</div>
<div class="small-12 medium-3 column">
<aside class="sidebar" role="complementary">
<aside class="sidebar">
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button radius expand' %>
<%= render "shared/tag_cloud", taggable: 'proposal' %>
<%= render 'categories' %>

View File

@@ -10,4 +10,10 @@
<%= link_to t("layouts.header.moderation"), moderation_root_path %>
</li>
<% end %>
<% if current_user.valuator? || current_user.administrator? %>
<li>
<%= link_to t("layouts.header.valuation"), valuation_root_path %>
</li>
<% end %>
<% end %>

View File

@@ -1,10 +1,10 @@
<% if I18n.available_locales.size > 1 %>
<div class="locale" id="js-locale" data-current-local="<%= I18n.locale %>">
<span class="inline-block">
<%= t("layouts.header.locale") %>
</span>
<form class="locale-form">
<select class="js-location-changer locale-switcher" name="locale-switcher">
<label class="inline-block" for="locale-switcher">
<%= t("layouts.header.locale") %>
</label>
<select class="js-location-changer locale-switcher inline-block" name="locale-switcher" id="locale-switcher">
<% I18n.available_locales.map do |loc| %>
<option <%= "selected" if loc == I18n.locale %>
value="<%= current_path_with_query_params(locale: loc) %>">

View File

@@ -43,7 +43,7 @@
</div>
<div class="small-12 medium-3 column">
<aside class="sidebar" role="complementary">
<aside class="sidebar">
<%= link_to t("map.start_proposal"),
new_proposal_path, class: 'button radius expand' %>
<%= render "shared/tag_cloud", taggable: 'proposal' %>

View File

@@ -1,10 +1,20 @@
<div class="small-12 medium-9 column">
<% if feature?(:debates) %>
<%= link_to t("layouts.header.debates"), debates_path, class: ("active" if controller_name == "debates") %>
<% end %>
<%= link_to t("layouts.header.proposals"), proposals_path, class: ("active" if controller_name == "proposals") %>
<% if feature?(:spending_proposals) %>
<%= link_to t("layouts.header.spending_proposals"), spending_proposals_path, class: ("active" if controller_name == "spending_proposals") %>
<% end %>
<%= link_to t("layouts.header.more_information"), page_path('more_information'), class: ("active" if current_page?("/more_information")) %>
<ul>
<% if feature?(:debates) %>
<li>
<%= link_to t("layouts.header.debates"), debates_path, class: ("active" if controller_name == "debates"), accesskey: "d" %>
</li>
<% end %>
<li>
<%= link_to t("layouts.header.proposals"), proposals_path, class: ("active" if controller_name == "proposals"), accesskey: "p" %>
</li>
<% if feature?(:spending_proposals) %>
<li>
<%= link_to t("layouts.header.spending_proposals"), spending_proposals_path, class: ("active" if controller_name == "spending_proposals"), accesskey: "s" %>
</li>
<% end %>
<li>
<%= link_to t("layouts.header.more_information"), page_path('more_information'), class: ("active" if current_page?("/more_information")), accesskey: "i" %>
</li>
</ul>
</div>

View File

@@ -0,0 +1,17 @@
<nav class="admin-sidebar">
<ul id="valuation_menu">
<li>
<%= link_to t("valuation.menu.title"), valuation_root_path %>
</li>
<% if feature?(:spending_proposals) %>
<li <%= "class=active" if controller_name == "spending_proposals" %>>
<%= link_to valuation_spending_proposals_path do %>
<i class="icon-budget"></i>
<%= t("valuation.menu.spending_proposals") %>
<% end %>
</li>
<% end %>
</ul>
</nav>

View File

@@ -0,0 +1,132 @@
<%= link_to "#{t('valuation.spending_proposals.show.heading')} #{@spending_proposal.id}", valuation_spending_proposal_path(@spending_proposal), class: 'back' %>
<h2><%= t("valuation.spending_proposals.edit.dossier") %></h2>
<%= form_for(@spending_proposal, url: valuate_valuation_spending_proposal_path(@spending_proposal)) do |f| %>
<%= render 'shared/errors', resource: @spending_proposal %>
<div class="row">
<div class="small-12 medium-4 column">
<%= f.label :price, "#{t('valuation.spending_proposals.edit.price')} (#{t('valuation.spending_proposals.edit.currency')})" %>
<%= f.number_field :price, label: false %>
</div>
<div class="small-12 medium-4 column end">
<%= f.label :price_first_year, "#{t('valuation.spending_proposals.edit.price_first_year')} ( #{t('valuation.spending_proposals.edit.currency')})" %>
<%= f.number_field :price_first_year, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :price_explanation, t("valuation.spending_proposals.edit.price_explanation") %>
<%= f.text_area :price_explanation, label: false, rows: 3 %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<fieldset class="fieldset">
<legend><%= t('valuation.spending_proposals.edit.feasibility') %></legend>
<div class="small-6 column">
<span class="checkbox">
<%= f.radio_button :feasible, true, value: true, label: false %>
<%= f.label :feasible_true, t('valuation.spending_proposals.edit.feasible') %>
</span>
</div>
<div class="small-6 column">
<span class="checkbox">
<%= f.radio_button :feasible, false, value: false, label: false %>
<%= f.label :feasible_false, t('valuation.spending_proposals.edit.not_feasible') %>
</span>
</div>
</fieldset>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :feasible_explanation, t("valuation.spending_proposals.edit.feasible_explanation") %>
<%= f.text_area :feasible_explanation, label: false, rows: 3 %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :time_scope, t("valuation.spending_proposals.edit.time_scope") %>
<%= f.text_field :time_scope, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :valuation_finished do %>
<%= f.check_box :valuation_finished, label: false %>
<span class="checkbox"><%= t("valuation.spending_proposals.edit.valuation_finished") %></span>
<% end %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :internal_comments, t("valuation.spending_proposals.edit.internal_comments") %>
<%= f.text_area :internal_comments, label: false, rows: 3 %>
</div>
</div>
<div class="row">
<div class="actions small-12 medium-4 column">
<%= f.submit(class: "button expanded large", value: t("valuation.spending_proposals.edit.save")) %>
</div>
</div>
<% end %>
<h1><%= @spending_proposal.title %></h1>
<%= safe_html_with_links @spending_proposal.description %>
<% if @spending_proposal.external_url.present? %>
<p><%= text_with_links @spending_proposal.external_url %></p>
<% end %>
<h2><%= t("valuation.spending_proposals.show.info") %></h2>
<p><strong><%= t("valuation.spending_proposals.show.by") %>:</strong>
<%= link_to @spending_proposal.author.name, user_path(@spending_proposal.author) %>
</p>
<% if @spending_proposal.association_name.present? %>
<p><strong><%= t("valuation.spending_proposals.show.association_name") %>:</strong>
<%= @spending_proposal.association_name %>
</p>
<% end %>
<p><strong><%= t("valuation.spending_proposals.show.geozone") %>:</strong>
<%= geozone_name(@spending_proposal) %>
</p>
<p><strong><%= t("valuation.spending_proposals.show.sent") %>:</strong>
<%= l @spending_proposal.created_at, format: :datetime %>
</p>
<h2><%= t("valuation.spending_proposals.show.responsibles") %></h2>
<p><strong><%= t("valuation.spending_proposals.show.assigned_admin") %>:</strong>
<% if @spending_proposal.administrator.present? %>
<%= @spending_proposal.administrator.name %> (<%= @spending_proposal.administrator.email %>)
<% else %>
<%= t("valuation.spending_proposals.show.undefined") %></li>
<% end %>
</p>
<p><strong><%= t("valuation.spending_proposals.show.assigned_valuators") %>:</strong></p>
<div id="assigned_valuators">
<ul>
<% @spending_proposal.valuators.each do |valuator| %>
<li><%= valuator.name %> (<%= valuator.email %>)</li>
<% end %>
<% if @spending_proposal.valuators.empty? %>
<li><%= t("valuation.spending_proposals.show.undefined") %></li>
<% end %>
</ul>
</div>

View File

@@ -0,0 +1,41 @@
<h2><%= t("valuation.spending_proposals.index.title") %></h2>
<div>
<%= form_tag valuation_spending_proposals_path, method: :get, enforce_utf8: false do %>
<div class="small-12 medium-4 column float-right">
<%= select_tag :geozone_id,
options_for_select(geozone_select_options.unshift([t("geozones.none"), "all"]), params[:geozone_id]),
{ prompt: t("valuation.spending_proposals.index.geozone_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<% end %>
</div>
<%= render 'shared/filter_subnav', i18n_namespace: "valuation.spending_proposals.index" %>
<h3><%= page_entries_info @spending_proposals %></h3>
<table>
<% @spending_proposals.each do |spending_proposal| %>
<tr id="<%= dom_id(spending_proposal) %>">
<td>
<strong><%= spending_proposal.id %></strong>
</td>
<td>
<%= link_to spending_proposal.title, valuation_spending_proposal_path(spending_proposal) %>
</td>
<td class="small">
<%= link_to t("valuation.spending_proposals.index.edit"), edit_valuation_spending_proposal_path(spending_proposal) %>
</td>
<td class="small">
<%= assigned_valuators_info(spending_proposal.valuators) %>
</td>
<td class="small">
<%= geozone_name(spending_proposal) %>
</td>
</tr>
<% end %>
</table>
<%= paginate @spending_proposals %>

View File

@@ -0,0 +1,92 @@
<%= link_to t("valuation.spending_proposals.show.back"), :back, class: 'back' %>
<h2><%= t("valuation.spending_proposals.show.heading") %> <%= @spending_proposal.id %> </h2>
<h1><%= @spending_proposal.title %></h1>
<%= safe_html_with_links @spending_proposal.description %>
<% if @spending_proposal.external_url.present? %>
<p><%= text_with_links @spending_proposal.external_url %></p>
<% end %>
<h2><%= t("valuation.spending_proposals.show.info") %></h2>
<p><strong><%= t("valuation.spending_proposals.show.by") %>:</strong>
<%= link_to @spending_proposal.author.name, user_path(@spending_proposal.author) %>
</p>
<% if @spending_proposal.association_name.present? %>
<p><strong><%= t("valuation.spending_proposals.show.association_name") %>:</strong>
<%= @spending_proposal.association_name %>
</p>
<% end %>
<p><strong><%= t("valuation.spending_proposals.show.geozone") %>:</strong>
<%= geozone_name(@spending_proposal) %>
</p>
<p><strong><%= t("valuation.spending_proposals.show.sent") %>:</strong>
<%= l @spending_proposal.created_at, format: :datetime %>
</p>
<h2><%= t("valuation.spending_proposals.show.responsibles") %></h2>
<p><strong><%= t("valuation.spending_proposals.show.assigned_admin") %>:</strong>
<% if @spending_proposal.administrator.present? %>
<%= @spending_proposal.administrator.name %> (<%= @spending_proposal.administrator.email %>)
<% else %>
<%= t("valuation.spending_proposals.show.undefined") %></li>
<% end %>
</p>
<p><strong><%= t("valuation.spending_proposals.show.assigned_valuators") %>:</strong></p>
<div id="assigned_valuators">
<ul>
<% @spending_proposal.valuators.each do |valuator| %>
<li><%= valuator.name %> (<%= valuator.email %>)</li>
<% end %>
<% if @spending_proposal.valuators.empty? %>
<li><%= t("valuation.spending_proposals.show.undefined") %></li>
<% end %>
</ul>
</div>
<h2><%= t("valuation.spending_proposals.show.dossier") %></h2>
<p>
<%= link_to t("valuation.spending_proposals.show.edit_dossier"), edit_valuation_spending_proposal_path(@spending_proposal) %>
</p>
<p id="price">
<strong><%= t("valuation.spending_proposals.show.price") %> (<%= t("valuation.spending_proposals.show.currency") %>):</strong>
<%= @spending_proposal.price.presence or t("valuation.spending_proposals.show.undefined") %>
</p>
<p id="price_first_year">
<strong><%= t("valuation.spending_proposals.show.price_first_year") %> (<%= t("valuation.spending_proposals.show.currency") %>):</strong>
<%= @spending_proposal.price_first_year.presence or t("valuation.spending_proposals.show.undefined") %>
</p>
<%= explanation_field @spending_proposal.price_explanation %>
<p id="time_scope">
<strong><%= t("valuation.spending_proposals.show.time_scope") %>:</strong>
<%= @spending_proposal.time_scope.presence or t("valuation.spending_proposals.show.undefined") %>
</p>
<p id="feasibility">
<strong><%= t("valuation.spending_proposals.show.feasibility") %>:</strong>
<%= t("valuation.spending_proposals.show.#{@spending_proposal.feasibility}") %>
</p>
<%= explanation_field @spending_proposal.feasible_explanation %>
<% if @spending_proposal.valuation_finished %>
<p>
<strong><%= t("valuation.spending_proposals.show.valuation_finished") %></strong>
</p>
<% end %>
<% if @spending_proposal.internal_comments.present? %>
<h2><%= t("valuation.spending_proposals.show.internal_comments") %></h2>
<%= simple_format_no_tags_no_sanitize(safe_html_with_links(@spending_proposal.internal_comments.html_safe)) %>
<% end %>

View File

@@ -24,6 +24,7 @@ data:
- config/locales/%{locale}.yml
- config/locales/admin.%{locale}.yml
- config/locales/moderation.%{locale}.yml
- config/locales/valuation.%{locale}.yml
- config/locales/management.%{locale}.yml
- config/locales/verification.%{locale}.yml
- config/locales/mailers.%{locale}.yml
@@ -122,6 +123,7 @@ ignore_unused:
- 'moderation.proposals.index.order*'
- 'moderation.debates.index.filter*'
- 'moderation.debates.index.order*'
- 'valuation.spending_proposals.index.filter*'
- 'users.show.filters.*'
- 'debates.index.select_order'
- 'debates.index.orders.*'

View File

@@ -174,6 +174,7 @@ en:
geozone: Scope
dossier: Dossier
price: Price
price_first_year: Cost during the first year
currency: "€"
feasibility: Feasibility
feasible: Feasible

View File

@@ -174,6 +174,7 @@ es:
geozone: Ámbito
dossier: Informe
price: Coste
price_first_year: Coste en el primer año
currency: "€"
feasibility: Viabilidad
feasible: Viable

View File

@@ -190,6 +190,7 @@ en:
locale: 'Language:'
logo: Madrid
moderation: Moderation
valuation: Valuation
more_information: More information
my_account_link: My account
my_activity_link: My activity

View File

@@ -190,6 +190,7 @@ es:
locale: 'Idioma:'
logo: Madrid
moderation: Moderar
valuation: Evaluación
more_information: Más información
my_account_link: Mi cuenta
my_activity_link: Mi actividad
@@ -198,7 +199,7 @@ es:
other: Tienes %{count} notificaciones nuevas
no_notifications: No tienes notificaciones nuevas
open: abierto
open_city_slogan_html: Existen ciudades gobernadas directamente por sus habitantes, que <b>debaten</b> sobre temas que les preocupan, <b>proponen</b> ideas para mejorar sus vidas y <b>deciden</b> entre todas y todos las que se llevan a cabo. Madrid ya es una de ellas.
open_city_slogan_html: Existen ciudades gobernadas directamente por sus habitantes, que <strong>debaten</strong> sobre temas que les preocupan, <strong>proponen</strong> ideas para mejorar sus vidas y <strong>deciden</strong> entre todas y todos las que se llevan a cabo. Madrid ya es una de ellas.
open_city_title: La ciudad que quieres será la ciudad que quieras.
open_data: Datos abiertos
open_gov: Gobierno %{open}

View File

@@ -0,0 +1,60 @@
---
en:
valuation:
menu:
title: Valuation
spending_proposals: Spending proposals
spending_proposals:
index:
geozone_filter_all: All zones
filters:
valuation_open: Open
valuating: Under valuation
valuation_finished: Valuation finished
title: Investment projects for participatory budgeting
edit: Edit
valuators_assigned:
one: Assigned valuator
other: "%{count} valuators assigned"
no_valuators_assigned: No valuators assigned
show:
back: Back
heading: Investment project
info: Author info
association_name: Asociación
by: Sent by
sent: Sent at
geozone: Scope
dossier: Dossier
edit_dossier: Edit dossier
price: Price
price_first_year: Cost during the first year
currency: "€"
feasibility: Feasibility
feasible: Feasible
not_feasible: Not feasible
undefined: Undefined
valuation_finished: Valuation finished
time_scope: Time scope
internal_comments: Internal comments
responsibles: Responsibles
assigned_admin: Assigned admin
assigned_valuators: Assigned valuators
edit:
dossier: Dossier
price: Price
price_first_year: Cost during the first year
currency: "€"
price_explanation: Price explanation
feasibility: Feasibility
feasible: Feasible
not_feasible: Not feasible
feasible_explanation: Feasibility explanation
valuation_finished: Valuation finished
time_scope: Time scope
internal_comments: Internal comments
save: Save changes
notice:
valuate: "Dossier updated"

View File

@@ -0,0 +1,58 @@
---
es:
valuation:
menu:
title: Evaluación
spending_proposals: Propuestas de inversión
spending_proposals:
index:
geozone_filter_all: Todos los ámbitos de actuación
filters:
valuation_open: Abiertas
valuating: En evaluación
valuation_finished: Evaluación finalizada
title: Propuestas de inversión para presupuestos participativos
edit: Editar
valuators_assigned:
one: Evaluador asignado
other: "%{count} evaluadores asignados"
no_valuators_assigned: Sin evaluador
show:
back: Volver
heading: Propuesta de inversión
info: Datos de envío
association_name: Asociación
by: Enviada por
sent: Fecha de creación
geozone: Ámbito
dossier: Informe
edit_dossier: Editar informe
price: Coste
price_first_year: Coste en el primer año
currency: "€"
feasibility: Viabilidad
feasible: Viable
not_feasible: No viable
undefined: Sin definir
valuation_finished: Informe finalizado
time_scope: Plazo de ejecución
internal_comments: Comentarios internos
responsibles: Responsables
assigned_admin: Administrador asignado
assigned_valuators: Evaluadores asignados
edit:
dossier: Informe
price: Coste
price_first_year: Coste en el primer año
currency: "€"
price_explanation: Justificación del precio
feasibility: Viabilidad
feasible: Viable
not_feasible: No viable
feasible_explanation: Justificación de la viabilidad
valuation_finished: Informe finalizado
time_scope: Plazo de ejecución
internal_comments: Comentarios internos
save: Guardar cambios
notice:
valuate: "Informe actualizado"

View File

@@ -208,6 +208,16 @@ Rails.application.routes.draw do
end
end
namespace :valuation do
root to: "spending_proposals#index"
resources :spending_proposals, only: [:index, :show, :edit] do
member do
patch :valuate
end
end
end
namespace :management do
root to: "dashboard#index"

View File

@@ -0,0 +1,5 @@
class AddPriceFieldsToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :price_first_year, :float
end
end

View File

@@ -0,0 +1,5 @@
class AddTimeScopeToSpendingProposals < ActiveRecord::Migration
def change
add_column :spending_proposals, :time_scope, :string
end
end

View File

@@ -0,0 +1,11 @@
class ChangePriceFieldsInSpendingProposals < ActiveRecord::Migration
def up
change_column :spending_proposals, :price, :integer
change_column :spending_proposals, :price_first_year, :integer
end
def down
change_column :spending_proposals, :price, :float
change_column :spending_proposals, :price_first_year, :float
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160225171916) do
ActiveRecord::Schema.define(version: 20160308103548) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -299,7 +299,7 @@ ActiveRecord::Schema.define(version: 20160225171916) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "geozone_id"
t.float "price"
t.integer "price"
t.boolean "feasible"
t.string "association_name"
t.text "price_explanation"
@@ -309,6 +309,8 @@ ActiveRecord::Schema.define(version: 20160225171916) do
t.text "explanations_log"
t.integer "administrator_id"
t.integer "valuation_assignments_count", default: 0
t.integer "price_first_year"
t.string "time_scope"
end
add_index "spending_proposals", ["author_id"], name: "index_spending_proposals_on_author_id", using: :btree

View File

@@ -188,7 +188,8 @@ feature 'Admin spending proposals' do
spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
association_name: 'People of the neighbourhood',
price: 1234.56,
price: 1234,
price_first_year: 1000,
feasible: false,
feasible_explanation: 'It is impossible',
administrator: administrator)
@@ -203,7 +204,8 @@ feature 'Admin spending proposals' do
expect(page).to have_content(spending_proposal.author.name)
expect(page).to have_content(spending_proposal.association_name)
expect(page).to have_content(spending_proposal.geozone.name)
expect(page).to have_content('1234.56')
expect(page).to have_content('1234')
expect(page).to have_content('1000')
expect(page).to have_content('Not feasible')
expect(page).to have_content('It is impossible')
expect(page).to have_content('Ana (ana@admins.org)')

View File

@@ -6,10 +6,6 @@ feature 'Admin' do
create(:administrator, user: user)
user
end
let(:moderator) do
create(:moderator, user: user)
user
end
scenario 'Access as regular user is not authorized' do
login_as(user)
@@ -21,7 +17,18 @@ feature 'Admin' do
end
scenario 'Access as a moderator is not authorized' do
login_as(moderator)
create(:moderator, user: user)
login_as(user)
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
expect(current_path).to eq(proposals_path)
expect(page).to have_content "You do not have permission to access this page"
end
scenario 'Access as a valuator is not authorized' do
create(:valuator, user: user)
login_as(user)
visit admin_root_path
expect(current_path).not_to eq(admin_root_path)
@@ -42,15 +49,8 @@ feature 'Admin' do
visit root_path
expect(page).to have_link('Administration')
expect(page).to_not have_link('Moderator')
end
scenario "Moderation access links" do
login_as(moderator)
visit root_path
expect(page).to have_link('Moderation')
expect(page).to_not have_link('Administration')
expect(page).to have_link('Valuation')
end
scenario 'Admin dashboard' do
@@ -62,17 +62,7 @@ feature 'Admin' do
expect(current_path).to eq(admin_root_path)
expect(page).to have_css('#admin_menu')
expect(page).to_not have_css('#moderation_menu')
end
scenario 'Moderation dashboard' do
login_as(moderator)
visit root_path
click_link 'Moderation'
expect(current_path).to eq(moderation_root_path)
expect(page).to have_css('#moderation_menu')
expect(page).to_not have_css('#admin_menu')
expect(page).to_not have_css('#valuation_menu')
end
context 'Tags' do

View File

@@ -465,7 +465,7 @@ feature 'Debates' do
visit debates_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: "Schwifty"
click_button "Search"
end
@@ -482,7 +482,7 @@ feature 'Debates' do
scenario "Maintain search criteria" do
visit debates_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: "Schwifty"
click_button "Search"
end
@@ -843,7 +843,7 @@ feature 'Debates' do
debate = create(:debate, title: "Abcdefghi")
visit debates_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: debate.title
click_button "Search"
end

View File

@@ -1,6 +1,6 @@
require 'rails_helper'
feature 'Admin' do
feature 'Moderation' do
let(:user) { create(:user) }
scenario 'Access as regular user is not authorized' do
@@ -15,6 +15,20 @@ feature 'Admin' do
expect(page).to have_content "You do not have permission to access this page"
end
scenario 'Access as valuator is not authorized' do
create(:valuator, user: user)
login_as(user)
visit root_path
expect(page).to_not have_link("Moderation")
visit moderation_root_path
expect(current_path).not_to eq(moderation_root_path)
expect(current_path).to eq(proposals_path)
expect(page).to have_content "You do not have permission to access this page"
end
scenario 'Access as a moderator is authorized' do
create(:moderator, user: user)
@@ -41,4 +55,27 @@ feature 'Admin' do
expect(page).to_not have_content "You do not have permission to access this page"
end
scenario "Moderation access links" do
create(:moderator, user: user)
login_as(user)
visit root_path
expect(page).to have_link('Moderation')
expect(page).to_not have_link('Administration')
expect(page).to_not have_link('Valuation')
end
scenario 'Moderation dashboard' do
create(:moderator, user: user)
login_as(user)
visit root_path
click_link 'Moderation'
expect(current_path).to eq(moderation_root_path)
expect(page).to have_css('#moderation_menu')
expect(page).to_not have_css('#admin_menu')
expect(page).to_not have_css('#valuation_menu')
end
end

View File

@@ -583,7 +583,7 @@ feature 'Proposals' do
visit proposals_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: "Schwifty"
click_button "Search"
end
@@ -603,7 +603,7 @@ feature 'Proposals' do
visit proposals_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: proposal1.code
click_button "Search"
end
@@ -619,7 +619,7 @@ feature 'Proposals' do
scenario "Maintain search criteria" do
visit proposals_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: "Schwifty"
click_button "Search"
end
@@ -986,7 +986,7 @@ feature 'Proposals' do
proposal = create(:proposal, title: "Abcdefghi")
visit proposals_path
within "#search_form" do
within(".expanded #search_form") do
fill_in "search", with: proposal.title
click_button "Search"
end

View File

@@ -0,0 +1,289 @@
require 'rails_helper'
feature 'Valuation spending proposals' do
background do
@valuator = create(:valuator, user: create(:user, username: 'Rachel', email: 'rachel@valuators.org'))
login_as(@valuator.user)
end
scenario 'Disabled with a feature flag' do
Setting['feature.spending_proposals'] = nil
expect{ visit valuation_spending_proposals_path }.to raise_exception(FeatureFlags::FeatureDisabled)
end
scenario 'Index shows spending proposals assigned to current valuator' do
spending_proposal1 = create(:spending_proposal)
spending_proposal2 = create(:spending_proposal)
spending_proposal1.valuators << @valuator
visit valuation_spending_proposals_path
expect(page).to have_content(spending_proposal1.title)
expect(page).to_not have_content(spending_proposal2.title)
end
scenario 'Index shows no spending proposals to admins no valuators' do
spending_proposal1 = create(:spending_proposal)
spending_proposal2 = create(:spending_proposal)
spending_proposal1.valuators << @valuator
logout
login_as create(:administrator).user
visit valuation_spending_proposals_path
expect(page).to_not have_content(spending_proposal1.title)
expect(page).to_not have_content(spending_proposal2.title)
end
scenario 'Index shows assignments info' do
spending_proposal1 = create(:spending_proposal)
spending_proposal2 = create(:spending_proposal)
spending_proposal3 = create(:spending_proposal)
valuator1 = create(:valuator, user: create(:user))
valuator2 = create(:valuator, user: create(:user))
valuator3 = create(:valuator, user: create(:user))
spending_proposal1.valuator_ids = [@valuator.id]
spending_proposal2.valuator_ids = [@valuator.id, valuator1.id, valuator2.id]
spending_proposal3.valuator_ids = [@valuator.id, valuator3.id]
visit valuation_spending_proposals_path
within("#spending_proposal_#{spending_proposal1.id}") do
expect(page).to have_content("Rachel")
end
within("#spending_proposal_#{spending_proposal2.id}") do
expect(page).to have_content("3 valuators assigned")
end
within("#spending_proposal_#{spending_proposal3.id}") do
expect(page).to have_content("2 valuators assigned")
end
end
scenario "Index filtering by geozone", :js do
geozone = create(:geozone, name: "District 9")
spending_proposal1 = create(:spending_proposal, title: "Realocate visitors", geozone: geozone)
spending_proposal2 = create(:spending_proposal, title: "Destroy the city")
spending_proposal1.valuators << @valuator
spending_proposal2.valuators << @valuator
visit valuation_spending_proposals_path
expect(page).to have_link("Realocate visitors")
expect(page).to have_link("Destroy the city")
select "District 9", from: "geozone_id"
expect(page).to have_link("Realocate visitors")
expect(page).to_not have_link("Destroy the city")
select "All city", from: "geozone_id"
expect(page).to have_link("Destroy the city")
expect(page).to_not have_link("Realocate visitors")
select "All zones", from: "geozone_id"
expect(page).to have_link("Realocate visitors")
expect(page).to have_link("Destroy the city")
end
scenario "Current filter is properly highlighted" do
filters_links = {'valuating' => 'Under valuation',
'valuation_finished' => 'Valuation finished'}
visit valuation_spending_proposals_path
expect(page).to_not have_link(filters_links.values.first)
filters_links.keys.drop(1).each { |filter| expect(page).to have_link(filters_links[filter]) }
filters_links.each_pair do |current_filter, link|
visit valuation_spending_proposals_path(filter: current_filter)
expect(page).to_not have_link(link)
(filters_links.keys - [current_filter]).each do |filter|
expect(page).to have_link(filters_links[filter])
end
end
end
scenario "Index filtering by valuation status" do
valuating = create(:spending_proposal, title: "Ongoing valuation")
valuated = create(:spending_proposal, title: "Old idea", valuation_finished: true)
valuating.valuators << @valuator
valuated.valuators << @valuator
visit valuation_spending_proposals_path(filter: 'valuation_open')
expect(page).to have_content("Ongoing valuation")
expect(page).to_not have_content("Old idea")
visit valuation_spending_proposals_path(filter: 'valuating')
expect(page).to have_content("Ongoing valuation")
expect(page).to_not have_content("Old idea")
visit valuation_spending_proposals_path(filter: 'valuation_finished')
expect(page).to_not have_content("Ongoing valuation")
expect(page).to have_content("Old idea")
end
feature 'Show' do
scenario 'visible for assigned valuators' do
administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
association_name: 'People of the neighbourhood',
price: 1234,
feasible: false,
feasible_explanation: 'It is impossible',
administrator: administrator)
spending_proposal.valuators << [@valuator, valuator2]
visit valuation_spending_proposals_path
click_link spending_proposal.title
expect(page).to have_content(spending_proposal.title)
expect(page).to have_content(spending_proposal.description)
expect(page).to have_content(spending_proposal.author.name)
expect(page).to have_content(spending_proposal.association_name)
expect(page).to have_content(spending_proposal.geozone.name)
expect(page).to have_content('1234')
expect(page).to have_content('Not feasible')
expect(page).to have_content('It is impossible')
expect(page).to have_content('Ana (ana@admins.org)')
within('#assigned_valuators') do
expect(page).to have_content('Rachel (rachel@valuators.org)')
expect(page).to have_content('Rick (rick@valuators.org)')
end
end
scenario 'visible for admins' do
logout
login_as create(:administrator).user
administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
association_name: 'People of the neighbourhood',
price: 1234,
feasible: false,
feasible_explanation: 'It is impossible',
administrator: administrator)
spending_proposal.valuators << [@valuator, valuator2]
visit valuation_spending_proposal_path(spending_proposal)
expect(page).to have_content(spending_proposal.title)
expect(page).to have_content(spending_proposal.description)
expect(page).to have_content(spending_proposal.author.name)
expect(page).to have_content(spending_proposal.association_name)
expect(page).to have_content(spending_proposal.geozone.name)
expect(page).to have_content('1234')
expect(page).to have_content('Not feasible')
expect(page).to have_content('It is impossible')
expect(page).to have_content('Ana (ana@admins.org)')
within('#assigned_valuators') do
expect(page).to have_content('Rachel (rachel@valuators.org)')
expect(page).to have_content('Rick (rick@valuators.org)')
end
end
scenario 'not visible for not assigned valuators' do
logout
login_as create(:valuator).user
administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
association_name: 'People of the neighbourhood',
price: 1234,
feasible: false,
feasible_explanation: 'It is impossible',
administrator: administrator)
spending_proposal.valuators << [@valuator, valuator2]
expect { visit valuation_spending_proposal_path(spending_proposal) }.to raise_error "Not Found"
end
end
feature 'Valuate' do
background do
@spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
administrator: create(:administrator))
@spending_proposal.valuators << @valuator
end
scenario 'Dossier empty by default' do
visit valuation_spending_proposals_path
click_link @spending_proposal.title
within('#price') { expect(page).to have_content('Undefined') }
within('#price_first_year') { expect(page).to have_content('Undefined') }
within('#time_scope') { expect(page).to have_content('Undefined') }
within('#feasibility') { expect(page).to have_content('Undefined') }
expect(page).to_not have_content('Valuation finished')
expect(page).to_not have_content('Internal comments')
end
scenario 'Edit dossier' do
visit valuation_spending_proposals_path
within("#spending_proposal_#{@spending_proposal.id}") do
click_link "Edit"
end
fill_in 'spending_proposal_price', with: '12345'
fill_in 'spending_proposal_price_first_year', with: '9876'
fill_in 'spending_proposal_price_explanation', with: 'Very cheap idea'
choose 'spending_proposal_feasible_true'
fill_in 'spending_proposal_feasible_explanation', with: 'Everything is legal and easy to do'
fill_in 'spending_proposal_time_scope', with: '19 months'
fill_in 'spending_proposal_internal_comments', with: 'Should be double checked by the urbanism area'
click_button 'Save changes'
expect(page).to have_content "Dossier updated"
visit valuation_spending_proposals_path
click_link @spending_proposal.title
within('#price') { expect(page).to have_content('12345') }
within('#price_first_year') { expect(page).to have_content('9876') }
expect(page).to have_content('Very cheap idea')
within('#time_scope') { expect(page).to have_content('19 months') }
within('#feasibility') { expect(page).to have_content('Feasible') }
expect(page).to_not have_content('Valuation finished')
expect(page).to have_content('Internal comments')
expect(page).to have_content('Should be double checked by the urbanism area')
end
scenario 'Finish valuation' do
visit valuation_spending_proposal_path(@spending_proposal)
click_link 'Edit dossier'
check 'spending_proposal_valuation_finished'
click_button 'Save changes'
visit valuation_spending_proposals_path
expect(page).to_not have_content @spending_proposal.title
click_link 'Valuation finished'
expect(page).to have_content @spending_proposal.title
click_link @spending_proposal.title
expect(page).to have_content('Valuation finished')
end
end
end

View File

@@ -0,0 +1,78 @@
require 'rails_helper'
feature 'Valuation' do
let(:user) { create(:user) }
scenario 'Access as regular user is not authorized' do
login_as(user)
visit root_path
expect(page).to_not have_link("Valuation")
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
expect(current_path).to eq(proposals_path)
expect(page).to have_content "You do not have permission to access this page"
end
scenario 'Access as moderator is not authorized' do
create(:moderator, user: user)
login_as(user)
visit root_path
expect(page).to_not have_link("Valuation")
visit valuation_root_path
expect(current_path).not_to eq(valuation_root_path)
expect(current_path).to eq(proposals_path)
expect(page).to have_content "You do not have permission to access this page"
end
scenario 'Access as a valuator is authorized' do
create(:valuator, user: user)
login_as(user)
visit root_path
expect(page).to have_link("Valuation")
click_on "Valuation"
expect(current_path).to eq(valuation_root_path)
expect(page).to_not have_content "You do not have permission to access this page"
end
scenario 'Access as an administrator is authorized' do
create(:administrator, user: user)
login_as(user)
visit root_path
expect(page).to have_link("Valuation")
click_on "Valuation"
expect(current_path).to eq(valuation_root_path)
expect(page).to_not have_content "You do not have permission to access this page"
end
scenario "Valuation access links" do
create(:valuator, user: user)
login_as(user)
visit root_path
expect(page).to have_link('Valuation')
expect(page).to_not have_link('Administration')
expect(page).to_not have_link('Moderation')
end
scenario 'Valuation dashboard' do
create(:valuator, user: user)
login_as(user)
visit root_path
click_link 'Valuation'
expect(current_path).to eq(valuation_root_path)
expect(page).to have_css('#valuation_menu')
expect(page).to_not have_css('#admin_menu')
expect(page).to_not have_css('#moderation_menu')
end
end

View File

@@ -0,0 +1,10 @@
require 'rails_helper'
require 'cancan/matchers'
describe "Abilities::Valuator" do
subject(:ability) { Ability.new(user) }
let(:user) { valuator.user }
let(:valuator) { create(:valuator) }
it { should be_able_to(:manage, SpendingProposal) }
end

View File

@@ -61,6 +61,38 @@ describe SpendingProposal do
end
end
describe "by_administrator" do
it "should return spending proposals assigned to specific administrator" do
spending_proposal1 = create(:spending_proposal, administrator_id: 33)
spending_proposal2 = create(:spending_proposal)
by_administrator = SpendingProposal.by_administrator(33)
expect(by_administrator.size).to eq(1)
expect(by_administrator.first).to eq(spending_proposal1)
end
end
describe "by_valuator" do
it "should return spending proposals assigned to specific valuator" do
spending_proposal1 = create(:spending_proposal)
spending_proposal2 = create(:spending_proposal)
spending_proposal3 = create(:spending_proposal)
valuator1 = create(:valuator)
valuator2 = create(:valuator)
spending_proposal1.valuators << valuator1
spending_proposal2.valuators << valuator2
spending_proposal3.valuators << [valuator1, valuator2]
by_valuator = SpendingProposal.by_valuator(valuator1.id)
expect(by_valuator.size).to eq(2)
expect(by_valuator.sort).to eq([spending_proposal1,spending_proposal3].sort)
end
end
describe "scopes" do
describe "valuation_open" do
it "should return all spending proposals with false valuation_finished" do