@@ -168,7 +168,7 @@ body.admin {
|
||||
clear: both;
|
||||
|
||||
.checkbox {
|
||||
font-size: rem-calc(12);
|
||||
font-size: $small-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -641,6 +641,10 @@ form {
|
||||
line-height: $line-height;
|
||||
}
|
||||
|
||||
fieldset legend {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
height: 48px\9;
|
||||
line-height: 48px\9;
|
||||
@@ -648,13 +652,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);
|
||||
|
||||
15
app/controllers/valuation/base_controller.rb
Normal file
15
app/controllers/valuation/base_controller.rb
Normal 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
|
||||
38
app/controllers/valuation/spending_proposals_controller.rb
Normal file
38
app/controllers/valuation/spending_proposals_controller.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
30
app/helpers/valuation_helper.rb
Normal file
30
app/helpers/valuation_helper.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -34,6 +34,7 @@ class SpendingProposal < ActiveRecord::Base
|
||||
results = self
|
||||
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_valuator(params[:valuator_id]) if params[:valuator_id].present?
|
||||
results = results.send(current_filter) if current_filter.present?
|
||||
results.for_render
|
||||
end
|
||||
@@ -50,6 +51,10 @@ class SpendingProposal < ActiveRecord::Base
|
||||
where(administrator_id: administrator.presence)
|
||||
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
|
||||
|
||||
@@ -62,6 +62,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>
|
||||
|
||||
@@ -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 %>
|
||||
|
||||
17
app/views/valuation/_menu.html.erb
Normal file
17
app/views/valuation/_menu.html.erb
Normal 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>
|
||||
132
app/views/valuation/spending_proposals/edit.html.erb
Normal file
132
app/views/valuation/spending_proposals/edit.html.erb
Normal 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>
|
||||
41
app/views/valuation/spending_proposals/index.html.erb
Normal file
41
app/views/valuation/spending_proposals/index.html.erb
Normal 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 %>
|
||||
92
app/views/valuation/spending_proposals/show.html.erb
Normal file
92
app/views/valuation/spending_proposals/show.html.erb
Normal 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 %>
|
||||
Reference in New Issue
Block a user