Merge pull request #241 from medialab-prado/issue_239

Fixed #239
This commit is contained in:
Juan Salvador Pérez García
2018-07-25 13:16:24 +02:00
committed by GitHub
82 changed files with 1131 additions and 694 deletions

View File

@@ -284,10 +284,10 @@
i { i {
display: inline-block; display: inline-block;
width: rem-calc(20); width: rem-calc(24);
height: rem-calc(20); height: rem-calc(24);
border-radius: rem-calc(10); border-radius: rem-calc(10);
padding-right: rem-calc(4); padding-right: rem-calc(5);
} }
} }

View File

@@ -0,0 +1,67 @@
class Admin::Dashboard::ActionsController < Admin::Dashboard::BaseController
helper_method :dashboard_action, :resource
def index
@dashboard_actions = ::Dashboard::Action.order(required_supports: :asc)
end
def new
@dashboard_action = ::Dashboard::Action.new(
active: true,
day_offset: 0,
required_supports: 0,
request_to_administrators: true,
action_type: 'proposed_action'
)
end
def create
@dashboard_action = ::Dashboard::Action.new(dashboard_action_params)
if @dashboard_action.save
redirect_to admin_dashboard_actions_path, notice: t('admin.dashboard.actions.create.notice')
else
render :new
end
end
def edit; end
def update
if dashboard_action.update(dashboard_action_params)
redirect_to admin_dashboard_actions_path
else
render :edit
end
end
def destroy
if dashboard_action.destroy
flash[:notice] = t('admin.dashboard.actions.delete.success')
else
flash[:error] = dashboard_action.errors.full_messages.join(',')
end
redirect_to admin_dashboard_actions_path
end
private
def resource
@dashboard_action
end
def dashboard_action_params
params
.require(:dashboard_action)
.permit(
:title, :description, :short_description, :request_to_administrators, :day_offset,
:required_supports, :order, :active, :action_type,
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
links_attributes: [:id, :label, :url, :open_in_new_tab, :_destroy]
)
end
def dashboard_action
@dashboard_action ||= ::Dashboard::Action.find(params[:id])
end
end

View File

@@ -0,0 +1,26 @@
class Admin::Dashboard::AdministratorTasksController < Admin::Dashboard::BaseController
helper_method :administrator_task
def index
authorize! :index, ::Dashboard::AdministratorTask
@administrator_tasks = ::Dashboard::AdministratorTask.pending
end
def edit
authorize! :edit, administrator_task
end
def update
authorize! :update, administrator_task
administrator_task.update(user: current_user, executed_at: Time.now)
redirect_to admin_dashboard_administrator_tasks_path,
{ flash: { notice: t("admin.dashboard.administrator_tasks.update.success") } }
end
private
def administrator_task
@administrator_task ||= ::Dashboard::AdministratorTask.find(params[:id])
end
end

View File

@@ -1,4 +1,4 @@
class Admin::ProposalDashboard::BaseController < Admin::BaseController class Admin::Dashboard::BaseController < Admin::BaseController
helper_method :namespace helper_method :namespace
private private

View File

@@ -1,67 +0,0 @@
class Admin::ProposalDashboard::ActionsController < Admin::ProposalDashboard::BaseController
helper_method :proposal_dashboard_action, :resource
def index
@proposal_dashboard_actions = ProposalDashboardAction.order(required_supports: :asc)
end
def new
@proposal_dashboard_action = ProposalDashboardAction.new(
active: true,
day_offset: 0,
required_supports: 0,
request_to_administrators: true,
action_type: 'proposed_action'
)
end
def create
@proposal_dashboard_action = ProposalDashboardAction.new(proposal_dashboard_action_params)
if @proposal_dashboard_action.save
redirect_to admin_proposal_dashboard_actions_path, notice: t('admin.proposal_dashboard_actions.create.notice')
else
render :new
end
end
def edit; end
def update
if proposal_dashboard_action.update(proposal_dashboard_action_params)
redirect_to admin_proposal_dashboard_actions_path
else
render :edit
end
end
def destroy
if proposal_dashboard_action.destroy
flash[:notice] = t('admin.proposal_dashboard_actions.delete.success')
else
flash[:error] = proposal_dashboard_action.errors.full_messages.join(',')
end
redirect_to admin_proposal_dashboard_actions_path
end
private
def resource
@proposal_dashboard_action
end
def proposal_dashboard_action_params
params
.require(:proposal_dashboard_action)
.permit(
:title, :description, :short_description, :request_to_administrators, :day_offset, :required_supports, :order, :active, :action_type,
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
links_attributes: [:id, :label, :url, :open_in_new_tab, :_destroy]
)
end
def proposal_dashboard_action
@proposal_dashboard_action ||= ProposalDashboardAction.find(params[:id])
end
end

View File

@@ -1,25 +0,0 @@
class Admin::ProposalDashboard::AdministratorTasksController < Admin::ProposalDashboard::BaseController
helper_method :administrator_task
def index
authorize! :index, AdministratorTask
@administrator_tasks = AdministratorTask.pending
end
def edit
authorize! :edit, administrator_task
end
def update
authorize! :update, administrator_task
administrator_task.update(user: current_user, executed_at: Time.now)
redirect_to admin_proposal_dashboard_administrator_tasks_path, { flash: { notice: t('.success') } }
end
private
def administrator_task
@administrator_task ||= AdministratorTask.find(params[:id])
end
end

View File

@@ -4,7 +4,7 @@ class Dashboard::BaseController < ApplicationController
helper_method :proposal, :proposed_actions, :resource, :resources, :next_goal, :next_goal_supports, :next_goal_progress, :community_members_count helper_method :proposal, :proposed_actions, :resource, :resources, :next_goal, :next_goal_supports, :next_goal_progress, :community_members_count
respond_to :html respond_to :html
layout 'proposals_dashboard' layout 'dashboard'
private private
@@ -13,11 +13,11 @@ class Dashboard::BaseController < ApplicationController
end end
def proposed_actions def proposed_actions
@proposed_actions ||= ProposalDashboardAction.proposed_actions.active_for(proposal).order(order: :asc) @proposed_actions ||= Dashboard::Action.proposed_actions.active_for(proposal).order(order: :asc)
end end
def resources def resources
@resources ||= ProposalDashboardAction.resources.active_for(proposal).order(order: :asc) @resources ||= Dashboard::Action.resources.active_for(proposal).order(order: :asc)
end end
def next_goal_supports def next_goal_supports
@@ -35,6 +35,6 @@ class Dashboard::BaseController < ApplicationController
end end
def next_goal def next_goal
@next_goal ||= ProposalDashboardAction.next_goal_for(proposal) @next_goal ||= Dashboard::Action.next_goal_for(proposal)
end end
end end

View File

@@ -2,7 +2,7 @@ class Dashboard::ResourcesController < Dashboard::BaseController
skip_authorization_check skip_authorization_check
def index def index
@resources = ProposalDashboardAction @resources = Dashboard::Action
.active .active
.resources .resources
.where('required_supports > 0') .where('required_supports > 0')

View File

@@ -1,5 +1,5 @@
class ProposalsDashboardController < Dashboard::BaseController class DashboardController < Dashboard::BaseController
helper_method :proposal_dashboard_action, :active_resources, :course helper_method :dashboard_action, :active_resources, :course
def index def index
authorize! :dashboard, proposal authorize! :dashboard, proposal
@@ -15,13 +15,13 @@ class ProposalsDashboardController < Dashboard::BaseController
def execute def execute
authorize! :dashboard, proposal authorize! :dashboard, proposal
ProposalExecutedDashboardAction.create(proposal: proposal, proposal_dashboard_action: proposal_dashboard_action, executed_at: Time.now) Dashboard::ExecutedAction.create(proposal: proposal, action: dashboard_action, executed_at: Time.now)
redirect_to progress_proposal_dashboard_index_path(proposal.to_param) redirect_to progress_proposal_dashboard_index_path(proposal.to_param)
end end
def new_request def new_request
authorize! :dashboard, proposal authorize! :dashboard, proposal
@proposal_executed_dashboard_action = ProposalExecutedDashboardAction.new @dashboard_executed_action = Dashboard::ExecutedAction.new
end end
def create_request def create_request
@@ -29,17 +29,17 @@ class ProposalsDashboardController < Dashboard::BaseController
source_params = { source_params = {
proposal: proposal, proposal: proposal,
proposal_dashboard_action: proposal_dashboard_action, action: dashboard_action,
executed_at: Time.now executed_at: Time.now
} }
@proposal_executed_dashboard_action = ProposalExecutedDashboardAction.new(source_params) @dashboard_executed_action = Dashboard::ExecutedAction.new(source_params)
if @proposal_executed_dashboard_action.save if @dashboard_executed_action.save
AdministratorTask.create(source: @proposal_executed_dashboard_action) Dashboard::AdministratorTask.create(source: @dashboard_executed_action)
redirect_to progress_proposal_dashboard_index_path(proposal.to_param), { flash: { info: t('.success') } } redirect_to progress_proposal_dashboard_index_path(proposal.to_param), { flash: { info: t('.success') } }
else else
flash.now[:alert] = @proposal_executed_dashboard_action.errors.full_messages.join('<br>') flash.now[:alert] = @dashboard_executed_action.errors.full_messages.join('<br>')
render :new_request render :new_request
end end
end end
@@ -69,15 +69,15 @@ class ProposalsDashboardController < Dashboard::BaseController
private private
def proposal_dashboard_action def dashboard_action
@proposal_dashboard_action ||= ProposalDashboardAction.find(params[:id]) @dashboard_action ||= Dashboard::Action.find(params[:id])
end end
def active_resources def active_resources
@active_resources ||= ProposalDashboardAction.active.resources.order(required_supports: :asc, day_offset: :asc) @active_resources ||= Dashboard::Action.active.resources.order(required_supports: :asc, day_offset: :asc)
end end
def course def course
@course ||= ProposalDashboardAction.course_for(proposal) @course ||= Dashboard::Action.course_for(proposal)
end end
end end

View File

@@ -1,6 +1,6 @@
module Admin::ProposalDashboardActionsHelper module Admin::ProposalDashboardActionsHelper
def active_human_readable(active) def active_human_readable(active)
return t('admin.proposal_dashboard_actions.index.active') if active return t('admin.dashboard.actions.index.active') if active
t('admin.proposal_dashboard_actions.index.inactive') t('admin.dashboard.actions.index.inactive')
end end
end end

View File

@@ -44,7 +44,7 @@ module AdminHelper
["homepage", "cards"].include?(controller_name) ["homepage", "cards"].include?(controller_name)
end end
def menu_proposals_dashboard? def menu_dashboard?
["actions", "administrator_tasks"].include?(controller_name) ["actions", "administrator_tasks"].include?(controller_name)
end end

View File

@@ -1,6 +1,6 @@
module ProposalsDashboardHelper module ProposalsDashboardHelper
def my_proposal_menu_class def my_proposal_menu_class
return 'is-active' if controller_name == 'proposals_dashboard' && action_name == 'index' return 'is-active' if controller_name == 'dashboard' && action_name == 'index'
nil nil
end end
@@ -10,12 +10,12 @@ module ProposalsDashboardHelper
end end
def community_menu_class def community_menu_class
return 'is-active' if controller_name == 'proposals_dashboard' && action_name == 'community' return 'is-active' if controller_name == 'dashboard' && action_name == 'community'
nil nil
end end
def progress_menu_active? def progress_menu_active?
is_proposed_action_request? || (controller_name == 'proposals_dashboard' && action_name == 'progress') is_proposed_action_request? || (controller_name == 'dashboard' && action_name == 'progress')
end end
def resources_menu_visible?(proposal, resources) def resources_menu_visible?(proposal, resources)
@@ -56,24 +56,24 @@ module ProposalsDashboardHelper
end end
def is_resource_request? def is_resource_request?
controller_name == 'proposals_dashboard' && action_name == 'new_request' && proposal_dashboard_action&.resource? controller_name == 'dashboard' && action_name == 'new_request' && dashboard_action&.resource?
end end
def is_proposed_action_request? def is_proposed_action_request?
controller_name == 'proposals_dashboard' && action_name == 'new_request' && proposal_dashboard_action&.proposed_action? controller_name == 'dashboard' && action_name == 'new_request' && dashboard_action&.proposed_action?
end end
def is_request_active(id) def is_request_active(id)
controller_name == 'proposals_dashboard' && action_name == 'new_request' && proposal_dashboard_action&.id == id controller_name == 'dashboard' && action_name == 'new_request' && dashboard_action&.id == id
end end
def resoure_availability_label(resource) def resoure_availability_label(resource)
label = [] label = []
label << t('proposals_dashboard.resource.required_days', days: resource.day_offset) if resource.day_offset > 0 label << t("dashboard.resource.required_days", days: resource.day_offset) if resource.day_offset > 0
label << t('proposals_dashboard.resource.required_supports', supports: number_with_delimiter(resource.required_supports, delimiter: '.')) if resource.required_supports > 0 label << t("dashboard.resource.required_supports", supports: number_with_delimiter(resource.required_supports, delimiter: '.')) if resource.required_supports > 0
label.join(" #{t('proposals_dashboard.resource.and')}<br>") label.join(" #{t("dashboard.resource.and")}<br>")
end end
def daily_selected_class def daily_selected_class
@@ -98,9 +98,9 @@ module ProposalsDashboardHelper
end end
def resource_tooltip(resource, proposal) def resource_tooltip(resource, proposal)
return t('proposals_dashboard.resource.resource_locked') unless resource.active_for?(proposal) return t("dashboard.resource.resource_locked") unless resource.active_for?(proposal)
return t('proposals_dashboard.resource.view_resource') if resource.executed_for?(proposal) return t("dashboard.resource.view_resource") if resource.executed_for?(proposal)
return t('proposals_dashboard.resource.resource_requested') if resource.requested_for?(proposal) return t("dashboard.resource.resource_requested") if resource.requested_for?(proposal)
t('proposals_dashboard.resource.request_resource') t("dashboard.resource.request_resource")
end end
end end

View File

@@ -48,7 +48,7 @@ module Abilities
can [:search, :index], ::User can [:search, :index], ::User
can :manage, Annotation can :manage, Annotation
can :manage, ProposalDashboardAction can :manage, Dashboard::Action
can [:read, :update, :valuate, :destroy, :summary], SpendingProposal can [:read, :update, :valuate, :destroy, :summary], SpendingProposal
@@ -85,6 +85,7 @@ module Abilities
can [:create, :destroy], DirectUpload can [:create, :destroy], DirectUpload
can [:deliver], Newsletter, hidden_at: nil can [:deliver], Newsletter, hidden_at: nil
can [:manage], Dashboard::AdministratorTask
end end
end end
end end

View File

@@ -63,7 +63,6 @@ module Abilities
cannot :moderate, ProposalNotification, author_id: user.id cannot :moderate, ProposalNotification, author_id: user.id
can :index, ProposalNotification can :index, ProposalNotification
can :manage, AdministratorTask
end end
end end
end end

5
app/models/dashboard.rb Normal file
View File

@@ -0,0 +1,5 @@
module Dashboard
def self.table_name_prefix
'dashboard_'
end
end

View File

@@ -0,0 +1,84 @@
class Dashboard::Action < ActiveRecord::Base
include Documentable
documentable max_documents_allowed: 3,
max_file_size: 3.megabytes,
accepted_content_types: [ 'application/pdf' ]
include Linkable
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
has_many :executed_actions, dependent: :restrict_with_error, class_name: 'Dashboard::ExecutedAction'
has_many :proposals, through: :executed_actions
enum action_type: [:proposed_action, :resource]
validates :title,
presence: true,
allow_blank: false,
length: { in: 4..80 }
validates :action_type, presence: true
validates :day_offset,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0
}
validates :required_supports,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 0
}
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
scope :resources, -> { where(action_type: 1) }
scope :proposed_actions, -> { where(action_type: 0) }
scope :active_for, ->(proposal) do
published_at = proposal.published_at&.to_date || Date.today
active
.where('required_supports <= ?', proposal.cached_votes_up)
.where('day_offset <= ?', (Date.today - published_at).to_i)
end
scope :course_for, lambda { |proposal|
active
.resources
.where('required_supports > ?', proposal.cached_votes_up)
.order(required_supports: :asc)
}
def active_for?(proposal)
published_at = proposal.published_at&.to_date || Date.today
required_supports <= proposal.cached_votes_up && day_offset <= (Date.today - published_at).to_i
end
def requested_for?(proposal)
executed_action = executed_actions.find_by(proposal: proposal)
return false if executed_action.nil?
executed_action.administrator_tasks.any?
end
def executed_for?(proposal)
executed_action = executed_actions.find_by(proposal: proposal)
return false if executed_action.nil?
executed_action.administrator_tasks.where.not(executed_at: nil).any?
end
def self.next_goal_for(proposal)
course_for(proposal).first
end
def request_to_administrators?
request_to_administrators || false
end
end

View File

@@ -0,0 +1,11 @@
class Dashboard::AdministratorTask < ActiveRecord::Base
belongs_to :source, polymorphic: true
belongs_to :user
validates :source, presence: true
default_scope { order(created_at: :asc) }
scope :pending, -> { where(executed_at: nil) }
scope :done, -> { where.not(executed_at: nil) }
end

View File

@@ -0,0 +1,10 @@
class Dashboard::ExecutedAction < ActiveRecord::Base
belongs_to :proposal
belongs_to :action, class_name: 'Dashboard::Action'
has_many :administrator_tasks, as: :source, dependent: :destroy, class_name: 'Dashboard::AdministratorTask'
validates :proposal, presence: true, uniqueness: { scope: :action }
validates :action, presence: true
validates :executed_at, presence: true
end

View File

@@ -31,8 +31,8 @@ class Proposal < ActiveRecord::Base
belongs_to :geozone belongs_to :geozone
has_many :comments, as: :commentable, dependent: :destroy has_many :comments, as: :commentable, dependent: :destroy
has_many :proposal_notifications, dependent: :destroy has_many :proposal_notifications, dependent: :destroy
has_many :proposal_executed_dashboard_actions, dependent: :destroy has_many :dashboard_executed_actions, dependent: :destroy, class_name: 'Dashboard::ExecutedAction'
has_many :proposal_dashboard_actions, through: :proposal_executed_dashboard_actions has_many :dashboard_actions, through: :dashboard_executed_actions, class_name: 'Dashboard::Action'
has_many :polls, as: :related has_many :polls, as: :related
validates :title, presence: true validates :title, presence: true

View File

@@ -18,7 +18,7 @@ class ProposalAchievementsQuery
achievements.each do |achievement| achievements.each do |achievement|
grouped_results[key] << { grouped_results[key] << {
executed_at: achievements.last.executed_at, executed_at: achievements.last.executed_at,
title: achievements.last.proposal_dashboard_action.title title: achievements.last.action.title
} }
end end
end end
@@ -36,11 +36,11 @@ class ProposalAchievementsQuery
end end
def achievements def achievements
ProposalExecutedDashboardAction Dashboard::ExecutedAction
.joins(:proposal_dashboard_action) .joins(:action)
.includes(:proposal_dashboard_action) .includes(:action)
.where(proposal: proposal, executed_at: start_date.beginning_of_day..end_date.end_of_day) .where(proposal: proposal, executed_at: start_date.beginning_of_day..end_date.end_of_day)
.where(proposal_dashboard_actions: { action_type: 0 }) .where(dashboard_actions: { action_type: 0 })
.order(executed_at: :asc) .order(executed_at: :asc)
end end

View File

@@ -237,15 +237,15 @@
<li class="section-title"> <li class="section-title">
<a href="#"> <a href="#">
<span class="icon-check"></span> <span class="icon-check"></span>
<strong><%= t("admin.menu.proposals_dashboard") %></strong> <strong><%= t("admin.menu.dashboard") %></strong>
</a> </a>
<ul <%= "class=is-active" if menu_proposals_dashboard? %>> <ul <%= "class=is-active" if menu_dashboard? %>>
<li <%= "class=is-active" if controller_name == "actions" %>> <li <%= "class=is-active" if controller_name == "actions" %>>
<%= link_to ProposalDashboardAction.model_name.human(count: 2), admin_proposal_dashboard_actions_path %> <%= link_to t("admin.menu.dashboard_actions"), admin_dashboard_actions_path %>
</li> </li>
<li <%= "class=is-active" if controller_name == "administrator_tasks" %>> <li <%= "class=is-active" if controller_name == "administrator_tasks" %>>
<%= link_to admin_proposal_dashboard_administrator_tasks_path do %> <%= link_to admin_dashboard_administrator_tasks_path do %>
<%= t("admin.menu.administrator_tasks") %> <%= t("admin.menu.administrator_tasks") %>
<% end %> <% end %>
</li> </li>

View File

@@ -0,0 +1,88 @@
<%= render 'shared/errors' %>
<div class="row">
<div class="small-12 column">
<%= f.label :title %>
<%= f.text_field :title, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 column">
<%= f.label :short_description %>
<%= f.text_field :short_description, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 column">
<%= f.cktext_area :description,
ckeditor: { language: I18n.locale } %>
</div>
</div>
<div class="row">
<div class="small-12 medium-3 column">
<%= f.label :action_type %>
<% ::Dashboard::Action.action_types.keys.each do |action_type_value| %>
<%= f.radio_button :action_type, action_type_value, label: false %>
<%= f.label "action_type_#{action_type_value}", t("admin.dashboard.actions.action_type.#{action_type_value}") %>
<br>
<% end %>
</div>
</div>
<div class="small-12 column">
<%= f.check_box :request_to_administrators, label: ::Dashboard::Action.human_attribute_name(:request_to_administrators) %>
</div>
<div class="row">
<div class="small-12 medium-4 large-4 column">
<%= f.label :day_offset %>
<%= f.number_field :day_offset, label: false, step: 1, min: 0 %>
<p class="help-text"><%= t("admin.dashboard.actions.form.day_offset_help_text") %></p>
</div>
<div class="small-12 medium-4 large-4 column">
<%= f.label :required_supports %>
<%= f.number_field :required_supports, label: false, step: 1, min: 0 %>
<p class="help-text"><%= t("admin.dashboard.actions.form.required_supports_help_text") %></p>
</div>
<div class="small-12 medium-4 large-4 column">
<%= f.label :order %>
<%= f.number_field :order, label: false, step: 1, min: 0 %>
</div>
</div>
<div class="small-12 column">
<%= f.check_box :active, label: ::Dashboard::Action.human_attribute_name(:active) %>
</div>
<div class="small-12 column">
<hr>
</div>
<% if feature?(:allow_attached_documents) %>
<div class="documents small-12 column">
<%= render 'documents/nested_documents', documentable: dashboard_action, f: f %>
</div>
<% end %>
<div class="small-12 column">
<hr>
</div>
<div class="links small-12 column">
<%= render 'links/nested_links', linkable: dashboard_action, f: f %>
</div>
<div class="small-12 column">
<hr>
</div>
<div class="row">
<div class="actions small-12 large-3 medium-3 column">
<%= f.submit(class: 'button expanded', value: t("admin.dashboard.actions.form.submit_button")) %>
</div>
</div>

View File

@@ -0,0 +1,11 @@
<div class="row">
<div class="small-12 column">
<%= back_link_to admin_dashboard_actions_path, t("admin.dashboard.actions.edit.back") %>
<h1><%= t("admin.dashboard.actions.edit.editing") %></h1>
<%= form_for dashboard_action, url: { action: 'update' } do |f| %>
<%= render 'form', f: f %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,45 @@
<%= link_to t("admin.dashboard.actions.index.create"),
new_admin_dashboard_action_path, class: 'button success float-right' %>
<h2 class="inline-block">
<%= t("admin.dashboard.actions.index.title") %>
</h2>
<table>
<thead>
<tr>
<th><%= t("admin.dashboard.actions.index.action_title") %></th>
<th><%= t("admin.dashboard.actions.index.action_type") %></th>
<th class="text-right"><%= t("admin.dashboard.actions.index.required_supports") %></th>
<th class="text-center"><%= t("admin.dashboard.actions.index.action_active") %></th>
<th></th>
</tr>
</thead>
<tbody>
<% if @dashboard_actions.empty? %>
<tr>
<td colspan="100%"><%= t("admin.dashboard.actions.index.no_records") %></td>
</tr>
<% end %>
<% @dashboard_actions.each do |action| %>
<tr id="<%= dom_id(action) %>">
<td><%= action.title %></td>
<td><%= t("admin.dashboard.actions.action_type.#{action.action_type}") %></td>
<td class="text-right"><%= number_with_delimiter(action.required_supports, delimiter: '.') %></td>
<td class="text-center"><%= active_human_readable(action.active) %></td>
<td class="text-right">
<%= link_to t("admin.dashboard.actions.index.edit"),
edit_admin_dashboard_action_path(action),
class: 'edit-banner button hollow' %>
<%= link_to t("admin.dashboard.actions.index.delete"),
admin_dashboard_action_path(action),
method: :delete,
class: 'button hollow alert',
data: { confirm: t("admin.actions.confirm") } %>
</td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,11 @@
<div class="dashboard-action-new row">
<div class="small-12 column">
<%= back_link_to admin_dashboard_actions_path, t("admin.dashboard.actions.new.back") %>
<h1><%= t("admin.dashboard.actions.new.creating") %></h1>
<%= form_for dashboard_action, url: { action: 'create' } do |f| %>
<%= render 'form', f: f %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,16 @@
<%= form_for administrator_task, url: { action: 'update' } do |f| %>
<div class="callout">
<h5><%= t("admin.dashboard.administrator_tasks.form.proposal", title: administrator_task.source.proposal.title) %></h5>
<p><%= t("admin.dashboard.administrator_tasks.form.request", title: administrator_task.source.action.title) %></p>
<%= link_to t("admin.dashboard.administrator_tasks.form.check_details"),
proposal_path(administrator_task.source.proposal),
target: '_blank' %>
</div>
<div class="row">
<div class="actions small-12 large-3 medium-3 column">
<%= f.submit(class: 'button expanded', value: t("admin.dashboard.administrator_tasks.form.solve")) %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,9 @@
<div class="row">
<div class="small-12 column">
<%= back_link_to admin_dashboard_administrator_tasks_path, t("admin.dashboard.administrator_tasks.edit.back") %>
<h1><%= t("admin.dashboard.administrator_tasks.edit.solving") %></h1>
<%= render 'form' %>
</div>
</div>

View File

@@ -1,11 +1,11 @@
<h2 class="inline-block"> <h2 class="inline-block">
<%= t("admin.proposal_dashboard.administrator_tasks.index.title") %> <%= t("admin.dashboard.administrator_tasks.index.title") %>
</h2> </h2>
<table> <table>
<thead> <thead>
<tr> <tr>
<th><%= AdministratorTask.human_attribute_name(:source) %></th> <th><%= t("admin.dashboard.administrator_tasks.index.source") %></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@@ -13,7 +13,7 @@
<tbody> <tbody>
<% if @administrator_tasks.empty? %> <% if @administrator_tasks.empty? %>
<tr> <tr>
<td colspan="100%"><%= t("admin.proposal_dashboard.administrator_tasks.index.no_records") %></td> <td colspan="100%"><%= t("admin.dashboard.administrator_tasks.index.no_records") %></td>
</tr> </tr>
<% end %> <% end %>
@@ -21,11 +21,11 @@
<tr id="<%= dom_id(task) %>"> <tr id="<%= dom_id(task) %>">
<td> <td>
<%= task.source.proposal.title %>: <%= task.source.proposal.title %>:
<%= task.source.proposal_dashboard_action.title %> <%= task.source.action.title %>
</td> </td>
<td style="text-align: right"> <td style="text-align: right">
<%= link_to t("admin.proposal_dashboard.administrator_tasks.index.solve"), <%= link_to t("admin.dashboard.administrator_tasks.index.solve"),
edit_admin_proposal_dashboard_administrator_task_path(task), edit_admin_dashboard_administrator_task_path(task),
class: 'edit-banner button hollow' %> class: 'edit-banner button hollow' %>
</td> </td>
</tr> </tr>

View File

@@ -1,90 +0,0 @@
<%= form_for [:admin, proposal_dashboard_action] do |f| %>
<%= render 'shared/errors' %>
<div class="row">
<div class="small-12 column">
<%= f.label :title %>
<%= f.text_field :title, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 column">
<%= f.label :short_description %>
<%= f.text_field :short_description, label: false %>
</div>
</div>
<div class="row">
<div class="small-12 column">
<%= f.cktext_area :description,
ckeditor: { language: I18n.locale } %>
</div>
</div>
<div class="row">
<div class="small-12 medium-3 column">
<%= f.label :action_type %>
<% ProposalDashboardAction.action_types.keys.each do |action_type_value| %>
<%= f.radio_button :action_type, action_type_value, label: false %>
<%= f.label "action_type_#{action_type_value}", t("admin.proposal_dashboard_actions.action_type.#{action_type_value}") %>
<br>
<% end %>
</div>
</div>
<div class="small-12 column">
<%= f.check_box :request_to_administrators, label: ProposalDashboardAction.human_attribute_name(:request_to_administrators) %>
</div>
<div class="row">
<div class="small-12 medium-4 large-4 column">
<%= f.label :day_offset %>
<%= f.number_field :day_offset, label: false, step: 1, min: 0 %>
<p class="help-text"><%= t("admin.proposal_dashboard_actions.form.day_offset_help_text") %></p>
</div>
<div class="small-12 medium-4 large-4 column">
<%= f.label :required_supports %>
<%= f.number_field :required_supports, label: false, step: 1, min: 0 %>
<p class="help-text"><%= t("admin.proposal_dashboard_actions.form.required_supports_help_text") %></p>
</div>
<div class="small-12 medium-4 large-4 column">
<%= f.label :order %>
<%= f.number_field :order, label: false, step: 1, min: 0 %>
</div>
</div>
<div class="small-12 column">
<%= f.check_box :active, label: ProposalDashboardAction.human_attribute_name(:active) %>
</div>
<div class="small-12 column">
<hr>
</div>
<% if feature?(:allow_attached_documents) %>
<div class="documents small-12 column">
<%= render 'documents/nested_documents', documentable: proposal_dashboard_action, f: f %>
</div>
<% end %>
<div class="small-12 column">
<hr>
</div>
<div class="links small-12 column">
<%= render 'links/nested_links', linkable: proposal_dashboard_action, f: f %>
</div>
<div class="small-12 column">
<hr>
</div>
<div class="row">
<div class="actions small-12 large-3 medium-3 column">
<%= f.submit(class: 'button expanded', value: t("admin.proposal_dashboard_actions.form.submit_button")) %>
</div>
</div>
<% end %>

View File

@@ -1,9 +0,0 @@
<div class="row">
<div class="small-12 column">
<%= back_link_to admin_proposal_dashboard_actions_path, t("admin.proposal_dashboard_actions.edit.back") %>
<h1><%= t("admin.proposal_dashboard_actions.edit.editing") %></h1>
<%= render 'form' %>
</div>
</div>

View File

@@ -1,45 +0,0 @@
<%= link_to t("admin.proposal_dashboard_actions.index.create"),
new_admin_proposal_dashboard_action_path, class: 'button success float-right' %>
<h2 class="inline-block">
<%= t("admin.proposal_dashboard_actions.index.title") %>
</h2>
<table>
<thead>
<tr>
<th><%= t("admin.proposal_dashboard_actions.index.action_title") %></th>
<th><%= t("admin.proposal_dashboard_actions.index.action_type") %></th>
<th class="text-right"><%= t("admin.proposal_dashboard_actions.index.required_supports") %></th>
<th class="text-center"><%= t("admin.proposal_dashboard_actions.index.action_active") %></th>
<th></th>
</tr>
</thead>
<tbody>
<% if @proposal_dashboard_actions.empty? %>
<tr>
<td colspan="100%"><%= t("admin.proposal_dashboard_actions.index.no_records") %></td>
</tr>
<% end %>
<% @proposal_dashboard_actions.each do |action| %>
<tr id="<%= dom_id(action) %>">
<td><%= action.title %></td>
<td><%= t("admin.proposal_dashboard_actions.action_type.#{action.action_type}") %></td>
<td class="text-right"><%= number_with_delimiter(action.required_supports, delimiter: '.') %></td>
<td class="text-center"><%= active_human_readable(action.active) %></td>
<td class="text-right">
<%= link_to t("admin.proposal_dashboard_actions.index.edit"),
edit_admin_proposal_dashboard_action_path(action),
class: 'edit-banner button hollow' %>
<%= link_to t("admin.proposal_dashboard_actions.index.delete"),
admin_proposal_dashboard_action_path(action),
method: :delete,
class: 'button hollow alert',
data: { confirm: t("admin.actions.confirm") } %>
</td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -1,9 +0,0 @@
<div class="proposal-dashboard-action-new row">
<div class="small-12 column">
<%= back_link_to admin_proposal_dashboard_actions_path, t("admin.proposal_dashboard_actions.new.back") %>
<h1><%= t("admin.proposal_dashboard_actions.new.creating") %></h1>
<%= render 'form' %>
</div>
</div>

View File

@@ -1,16 +0,0 @@
<%= form_for [:admin_proposal_dashboard, administrator_task] do |f| %>
<div class="callout">
<h5><%= t("admin.proposal_dashboard.administrator_tasks.form.proposal", title: administrator_task.source.proposal.title) %></h5>
<p><%= t("admin.proposal_dashboard.administrator_tasks.form.request", title: administrator_task.source.proposal_dashboard_action.title) %></p>
<%= link_to t("admin.proposal_dashboard.administrator_tasks.form.check_details"),
proposal_path(administrator_task.source.proposal),
target: '_blank' %>
</div>
<div class="row">
<div class="actions small-12 large-3 medium-3 column">
<%= f.submit(class: 'button expanded', value: t("admin.proposal_dashboard.administrator_tasks.form.solve")) %>
</div>
</div>
<% end %>

View File

@@ -1,9 +0,0 @@
<div class="row">
<div class="small-12 column">
<%= back_link_to admin_proposal_dashboard_administrator_tasks_path, t("admin.proposal_dashboard.administrator_tasks.edit.back") %>
<h1><%= t("admin.proposal_dashboard.administrator_tasks.edit.solving") %></h1>
<%= render 'form' %>
</div>
</div>

View File

@@ -0,0 +1,8 @@
<% if dashboard_action.request_to_administrators && !dashboard_action.requested_for?(proposal) %>
<%= form_for @dashboard_executed_action,
url: create_request_proposal_dashboard_url(proposal, dashboard_action) do |f| %>
<div class="actions">
<%= f.submit(class: 'button', value: t("dashboard.form.request")) %>
</div>
<% end %>
<% end %>

View File

@@ -2,7 +2,7 @@
<div class="column small-12"> <div class="column small-12">
<i class="fi-flag"></i> <i class="fi-flag"></i>
<strong> <strong>
<%= t("proposals_dashboard.goal.target_supports", count: number_with_precision(goal.required_supports, delimiter: '.', precision: 0)) %> <%= t("dashboard.goal.target_supports", count: number_with_precision(goal.required_supports, delimiter: '.', precision: 0)) %>
</strong> </strong>
</div> </div>
<div class="column small-12">&nbsp;</div> <div class="column small-12">&nbsp;</div>
@@ -12,15 +12,15 @@
<strong><%= goal.title %></strong> <strong><%= goal.title %></strong>
</div> </div>
<div class="column small-12 skip-icon"> <div class="column small-12 skip-icon">
<p class="help-text"><%= t("proposals_dashboard.goal.unlocked_resource") %></p> <p class="help-text"><%= t("dashboard.goal.unlocked_resource") %></p>
</div> </div>
<% if goal.day_offset.positive? %> <% if goal.day_offset.positive? %>
<div class="column small-12"> <div class="column small-12">
<strong><%= t("proposals_dashboard.goal.days", count: goal.day_offset) %></strong> <strong><%= t("dashboard.goal.days", count: goal.day_offset) %></strong>
</div> </div>
<div class="column small-12"> <div class="column small-12">
<p class="help-text"><%= t("proposals_dashboard.goal.ideal_time") %></p> <p class="help-text"><%= t("dashboard.goal.ideal_time") %></p>
</div> </div>
<% end %> <% end %>
</div> </div>

View File

@@ -2,7 +2,7 @@
<li class="section-title"> <li class="section-title">
<%= link_to proposal_dashboard_index_path(proposal.to_param), class: my_proposal_menu_class do %> <%= link_to proposal_dashboard_index_path(proposal.to_param), class: my_proposal_menu_class do %>
<i class="fi-lightbulb"></i> <i class="fi-lightbulb"></i>
<strong><%= t("proposals_dashboard.menu.my_proposal") %></strong> <strong><%= t("dashboard.menu.my_proposal") %></strong>
<% end %> <% end %>
</li> </li>
@@ -10,7 +10,7 @@
<%= link_to progress_proposal_dashboard_index_path(proposal.to_param), <%= link_to progress_proposal_dashboard_index_path(proposal.to_param),
class: progress_menu_class do %> class: progress_menu_class do %>
<span class="fi-graph-trend"></span> <span class="fi-graph-trend"></span>
<strong><%= t("proposals_dashboard.menu.progress") %></strong> <strong><%= t("dashboard.menu.progress") %></strong>
<% end %> <% end %>
</li> </li>
@@ -18,15 +18,15 @@
<li class="section-title"> <li class="section-title">
<a href="#" <%= 'class=is-active' if resources_menu_active? %>> <a href="#" <%= 'class=is-active' if resources_menu_active? %>>
<span class="icon-file-text-o"></span> <span class="icon-file-text-o"></span>
<strong><%= t("proposals_dashboard.menu.resources") %></strong> <strong><%= t("dashboard.menu.resources") %></strong>
</a> </a>
<%= resources_menu do %> <%= resources_menu do %>
<% if can?(:manage_polls, proposal) %> <% if can?(:manage_polls, proposal) %>
<%= polls_menu do %> <%= polls_menu do %>
<%= link_to proposal_dashboard_polls_path(proposal.to_param) do %> <%= link_to proposal_dashboard_polls_path(proposal.to_param) do %>
<span data-tooltip title="<%= Setting['proposals.poll_short_title'] || t("proposals_dashboard.menu.polls") %>"> <span data-tooltip title="<%= Setting['proposals.poll_short_title'] || t("dashboard.menu.polls") %>">
<%= t("proposals_dashboard.menu.polls") %> <%= t("dashboard.menu.polls") %>
</span> </span>
<% end %> <% end %>
<% end %> <% end %>
@@ -49,7 +49,7 @@
<%= link_to community_proposal_dashboard_index_path(proposal.to_param), <%= link_to community_proposal_dashboard_index_path(proposal.to_param),
class: community_menu_class do %> class: community_menu_class do %>
<span class="fi-torsos-all"></span> <span class="fi-torsos-all"></span>
<strong><%= t("proposals_dashboard.menu.community") %></strong> <strong><%= t("dashboard.menu.community") %></strong>
<% end %> <% end %>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,29 @@
<% if next_goal.present? %>
<div id='goals-section'>
<br><br>
<div class="action-title">
<h5><%= t("dashboard.next_goal.title") %></h5>
<hr>
</div>
<div id="next-goal" data-toggler=".hide">
<%= render 'goal', goal: next_goal %>
<div class="column small-12">
<a data-toggle="complete-course next-goal" id='see-complete-course-link'>
<%= t("dashboard.next_goal.see_complete_course") %>
</a>
</div>
</div>
<% if course.count > 1 %>
<div class="hide" id="complete-course" data-toggler=".hide">
<%= render partial: 'goal', collection: course %>
<div class="column small-12">
<a data-toggle="complete-course next-goal"><%= t("dashboard.next_goal.hide_course") %></a>
</div>
</div>
<% end %>
</div>
<% end %>

View File

@@ -1,13 +1,13 @@
<% if can?(:manage_polls, proposal) %> <% if can?(:manage_polls, proposal) %>
<div class="column"> <div class="column">
<div class="card resource-card primary" <div class="card resource-card primary"
data-tooltip title="<%= t("proposals_dashboard.resource.request_resource") %>" data-tooltip title="<%= t("dashboard.resource.request_resource") %>"
data-position="bottom" data-alignment="right"> data-position="bottom" data-alignment="right">
<div class="card-section"> <div class="card-section">
<p class="text-right"> <p class="text-right">
<i class="fi-pencil"></i> <i class="fi-pencil resource-icon"></i>
</p> </p>
<h4 class="text-center"><%= t("proposals_dashboard.menu.polls") %></h4> <h4 class="text-center"><%= t("dashboard.menu.polls") %></h4>
<p class="text-center"> <p class="text-center">
<%= Setting['proposals.poll_short_title'] %> <%= Setting['proposals.poll_short_title'] %>
</p> </p>
@@ -15,7 +15,9 @@
<div class="card-section text-center bottom-container"> <div class="card-section text-center bottom-container">
<div class="bottom-element text-center"> <div class="bottom-element text-center">
<%= link_to t("proposals_dashboard.resource.request_resource"), proposal_dashboard_polls_path(proposal.to_param), class: 'button primary' %> <%= link_to t("dashboard.resource.request_resource"),
proposal_dashboard_polls_path(proposal.to_param),
class: 'button primary' %>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -14,7 +14,7 @@
<div> <div>
<h4><%= proposed_action.title %></h4> <h4><%= proposed_action.title %></h4>
<% if proposed_action.proposals.where(id: proposal.id).any? %> <% if proposed_action.proposals.where(id: proposal.id).any? %>
<p><%=l(proposed_action.proposal_executed_dashboard_actions.find_by(proposal: proposal).executed_at.to_date) %></p> <p><%=l(proposed_action.executed_actions.find_by(proposal: proposal).executed_at.to_date) %></p>
<% else %> <% else %>
<% unless proposed_action.short_description.blank? %> <% unless proposed_action.short_description.blank? %>
<p><%= proposed_action.short_description %></p> <p><%= proposed_action.short_description %></p>

View File

@@ -1,7 +1,7 @@
<% if proposed_actions.any? %> <% if proposed_actions.any? %>
<br><br> <br><br>
<div class="action-title"> <div class="action-title">
<h5><%= t("proposals_dashboard.recommended_actions.title") %></h5> <h5><%= t("dashboard.recommended_actions.title") %></h5>
<hr> <hr>
</div> </div>

View File

@@ -21,15 +21,15 @@
<div class="card-section text-center bottom-container"> <div class="card-section text-center bottom-container">
<% if resource.executed_for?(proposal) %> <% if resource.executed_for?(proposal) %>
<div class="bottom-element text-center"> <div class="bottom-element text-center">
<%= link_to t("proposals_dashboard.resource.view_resource"), <%= link_to t("dashboard.resource.view_resource"),
new_request_proposal_dashboard_path(proposal, resource), new_request_proposal_dashboard_path(proposal, resource),
class: 'button success' %> class: 'button success' %>
</div> </div>
<% elsif resource.requested_for?(proposal) %> <% elsif resource.requested_for?(proposal) %>
<strong><%= t("proposals_dashboard.resource.resource_requested") %></strong> <strong><%= t("dashboard.resource.resource_requested") %></strong>
<% elsif resource.active_for?(proposal) %> <% elsif resource.active_for?(proposal) %>
<div class="bottom-element text-center"> <div class="bottom-element text-center">
<%= link_to t("proposals_dashboard.resource.request_resource"), <%= link_to t("dashboard.resource.request_resource"),
new_request_proposal_dashboard_path(proposal, resource), new_request_proposal_dashboard_path(proposal, resource),
class: 'button primary' %> class: 'button primary' %>
</div> </div>

View File

@@ -0,0 +1,12 @@
<div id='available-resources-section'>
<br><br>
<div class="action-title">
<h5><%= t("dashboard.resources.available_resources") %></h5>
<hr>
</div>
<div class="row small-up-2 medium-up-3 large-up-4">
<%= render 'poll_resource' %>
<%= render partial: 'resource', collection: active_resources %>
</div>
</div>

View File

@@ -1,35 +1,35 @@
<% content_for :action_title, t("proposals_dashboard.menu.community") %> <% content_for :action_title, t("dashboard.menu.community") %>
<div class="row"> <div class="row">
<div class="small-12 large-9 column"> <div class="small-12 large-9 column">
<%= link_to t("proposals_dashboard.community.access_community"), community_path(proposal.community), class: 'button hollow' %> <%= link_to t("dashboard.community.access_community"), community_path(proposal.community), class: 'button hollow' %>
<% unless proposal.community.latest_activity.nil? %> <% unless proposal.community.latest_activity.nil? %>
<p class="help-text"><%= t("proposals_dashboard.community.latest_activity", at: l(proposal.community.latest_activity.to_date)) %></p> <p class="help-text"><%= t("dashboard.community.latest_activity", at: l(proposal.community.latest_activity.to_date)) %></p>
<% end %> <% end %>
</div> </div>
<div class="small-12 large-1 column community-totals"> <div class="small-12 large-1 column community-totals">
<span class="fi-torsos-all"></span> <span class="fi-torsos-all"></span>
&nbsp;<strong><%= number_with_delimiter(proposal.community.participants_count, delimiter: '.') %></strong> &nbsp;<strong><%= number_with_delimiter(proposal.community.participants_count, delimiter: '.') %></strong>
<p><%= t("proposals_dashboard.community.participants") %></p> <p><%= t("dashboard.community.participants") %></p>
</div> </div>
<div class="small-12 large-1 column community-totals"> <div class="small-12 large-1 column community-totals">
<span class="fi-comment-quotes"></span> <span class="fi-comment-quotes"></span>
&nbsp;<strong><%= number_with_delimiter(proposal.community.debates_count, delimiter: '.') %></strong> &nbsp;<strong><%= number_with_delimiter(proposal.community.debates_count, delimiter: '.') %></strong>
<p><%= t("proposals_dashboard.community.debates") %></p> <p><%= t("dashboard.community.debates") %></p>
</div> </div>
<div class="small-12 large-1 column community-totals"> <div class="small-12 large-1 column community-totals">
<span class="fi-comments"></span> <span class="fi-comments"></span>
&nbsp;<strong><%= number_with_delimiter(proposal.community.comments_count, delimiter: '.') %></strong> &nbsp;<strong><%= number_with_delimiter(proposal.community.comments_count, delimiter: '.') %></strong>
<p><%= t("proposals_dashboard.community.comments") %></p> <p><%= t("dashboard.community.comments") %></p>
</div> </div>
</div> </div>
<% if proposal.community.comments.any? %> <% if proposal.community.comments.any? %>
<div class="action-title"> <div class="action-title">
<h5><%= t("proposals_dashboard.community.latest_comments") %></h5> <h5><%= t("dashboard.community.latest_comments") %></h5>
<hr> <hr>
</div> </div>

View File

@@ -1,6 +1,6 @@
<% content_for :action_title, t("proposals_dashboard.index.title") %> <% content_for :action_title, t("dashboard.index.title") %>
<% if current_editable?(proposal) %> <% if current_editable?(proposal) %>
<%= link_to t("proposals_dashboard.index.edit_proposal_link"), edit_proposal_path(proposal), target: '_blank', class: 'button hollow' %> <%= link_to t("dashboard.index.edit_proposal_link"), edit_proposal_path(proposal), target: '_blank', class: 'button hollow' %>
<% end %> <% end %>
@@ -13,13 +13,13 @@
<% end %> <% end %>
<% unless proposal.retired? %> <% unless proposal.retired? %>
<%= link_to t("proposals_dashboard.index.retire"), <%= link_to t("dashboard.index.retire"),
retire_form_proposal_path(proposal), retire_form_proposal_path(proposal),
class: 'button hollow alert', class: 'button hollow alert',
target: '_blank' %> target: '_blank' %>
<% end %> <% end %>
<% if can?(:publish, proposal) %> <% if can?(:publish, proposal) %>
<%= link_to t("proposals_dashboard.index.publish"), publish_proposal_dashboard_index_path(proposal), class: 'button success', method: :patch %> <%= link_to t("dashboard.index.publish"), publish_proposal_dashboard_index_path(proposal), class: 'button success', method: :patch %>
<% end %> <% end %>

View File

@@ -0,0 +1,26 @@
<% content_for :action_title, dashboard_action.title %>
<div class="row">
<div class="small-12 medium-8 column">
<%== dashboard_action.description %>
<%= render 'dashboard/form' %>
</div>
<div class="small-12 medium-4 column">
<% if dashboard_action.links.any? %>
<div class="proposal-dashboard-action-links">
<h3><%= t("dashboard.new_request.links") %></h3>
<% dashboard_action.links.each do |link| %>
<% if link.open_in_new_tab %>
<%= link_to link.label, link.url, target: '_blank' %>
<% else %>
<%= link_to link.label, link.url %>
<% end %>
<% end %>
</div>
<% end %>
<%= render 'documents/documents', documents: dashboard_action.documents %>
</div>
</div>

View File

@@ -1,15 +1,15 @@
<% content_for :action_title, t("proposals_dashboard.progress.title") %> <% content_for :action_title, t("dashboard.progress.title") %>
<div class="row"> <div class="row">
<div class="small-12 column"> <div class="small-12 column">
<div class="button-group"> <div class="button-group">
<%= link_to t("proposals_dashboard.progress.group_by_date"), <%= link_to t("dashboard.progress.group_by_date"),
progress_proposal_dashboard_index_path(proposal), progress_proposal_dashboard_index_path(proposal),
class: "button #{daily_selected_class}" %> class: "button #{daily_selected_class}" %>
<%= link_to t("proposals_dashboard.progress.group_by_week"), <%= link_to t("dashboard.progress.group_by_week"),
progress_proposal_dashboard_index_path(proposal, group_by: 'week'), progress_proposal_dashboard_index_path(proposal, group_by: 'week'),
class: "button #{weekly_selected_class}" %> class: "button #{weekly_selected_class}" %>
<%= link_to t("proposals_dashboard.progress.group_by_month"), <%= link_to t("dashboard.progress.group_by_month"),
progress_proposal_dashboard_index_path(proposal, group_by: 'month'), progress_proposal_dashboard_index_path(proposal, group_by: 'month'),
class: "button #{monthly_selected_class}" %> class: "button #{monthly_selected_class}" %>
</div> </div>
@@ -22,9 +22,9 @@
data-successful-proposal-graph-url="<%= successful_supports_proposal_dashboard_index_path(proposal, format: :json) %>" data-successful-proposal-graph-url="<%= successful_supports_proposal_dashboard_index_path(proposal, format: :json) %>"
data-proposal-achievements-url="<%= achievements_proposal_dashboard_index_path(proposal, format: :json) %>" data-proposal-achievements-url="<%= achievements_proposal_dashboard_index_path(proposal, format: :json) %>"
data-proposal-graph-group-by="<%= params[:group_by] %>" data-proposal-graph-group-by="<%= params[:group_by] %>"
data-proposal-graph-progress-label="<%= t("proposals_dashboard.progress.progress") %>" data-proposal-graph-progress-label="<%= t("dashboard.progress.progress") %>"
data-proposal-graph-supports-label="<%= t("proposals_dashboard.progress.supports") %>" data-proposal-graph-supports-label="<%= t("dashboard.progress.supports") %>"
data-proposal-graph-success-label="<%= t("proposals_dashboard.progress.success") %>" data-proposal-graph-success-label="<%= t("dashboard.progress.success") %>"
data-proposal-success="<%= Setting["votes_for_proposal_success"] %>" data-proposal-success="<%= Setting["votes_for_proposal_success"] %>"
class="c3 proposal-graph" class="c3 proposal-graph"
style="max-height: 320px; position: relative;"></div> style="max-height: 320px; position: relative;"></div>

View File

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="<%= I18n.locale %>" data-current-user-id="<%= current_user.try(:id) %>">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<%= render "layouts/tracking_data" %>
<%= render "layouts/meta_tags" %>
<title><%= content_for?(:title) ? yield(:title) : setting['org_name'] %></title>
<%= content_for :canonical %>
<%= stylesheet_link_tag "application" %>
<!--[if lt IE 9]>
<%= stylesheet_link_tag "ie" %>
<![endif]-->
<%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<%= favicon_link_tag "favicon.ico" %>
<%= favicon_link_tag image_path_for("apple-touch-icon-200.png"),
rel: "icon apple-touch-icon",
sizes: "200x200",
type: "image/png" %>
<%= content_for :social_media_meta_tags %>
<%= setting['per_page_code_head'].try(:html_safe) %>
</head>
<body class="proposal-dashboard">
<%= setting['per_page_code_body'].try(:html_safe) %>
<h1 class="show-for-sr"><%= setting['org_name'] %></h1>
<div class="off-canvas-wrapper">
<div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
<div class="off-canvas position-left" id="offCanvas" data-off-canvas>
<div class="show-for-small-only">
<div class="dashboard-sidebar" data-equalizer-watch>
<%= render partial: 'dashboard/menu' %>
</div>
</div>
</div>
<div class="off-canvas-content" data-off-canvas-content>
<%= render partial: 'layouts/header', locals: {with_subnavigation: false} %>
<div class="no-margin-top row expanded collapse" data-equalizer>
<div class="small-12 medium-3 column" data-equalizer-watch>
<div class="show-for-small-only">
<button type="button" class="button hollow expanded" data-toggle="offCanvas"><%= t("admin.menu.admin") %></button>
</div>
<div id="side_menu" class="hide-for-small-only">
<div class="dashboard-sidebar" data-equalizer-watch>
<%= render partial: 'dashboard/menu' %>
</div>
</div>
</div>
<div class="admin-content small-12 medium-9 column" data-equalizer-watch>
<%= render partial: 'layouts/flash' %>
<%= render partial: 'layouts/dashboard/proposal_totals' %>
<%= render partial: 'layouts/dashboard/proposal_header' %>
<%= yield %>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -8,9 +8,9 @@
<div class="counter"> <div class="counter">
<div class="counter-value"> <div class="counter-value">
<%= ProposalDashboardAction.active.resources.active_for(proposal).count %> <%= Dashboard::Action.active.resources.active_for(proposal).count %>
/ /
<%= ProposalDashboardAction.active.resources.count %> <%= Dashboard::Action.active.resources.count %>
</div> </div>
<div class="counter-label"><%= t('.active_resources') %></div> <div class="counter-label"><%= t('.active_resources') %></div>
</div> </div>

View File

@@ -1,8 +0,0 @@
<% if proposal_dashboard_action.request_to_administrators && !proposal_dashboard_action.requested_for?(proposal) %>
<%= form_for @proposal_executed_dashboard_action,
url: create_request_proposal_dashboard_url(proposal, proposal_dashboard_action) do |f| %>
<div class="actions">
<%= f.submit(class: 'button', value: t("proposals_dashboard.form.request")) %>
</div>
<% end %>
<% end %>

View File

@@ -1,25 +0,0 @@
<% if next_goal.present? %>
<br><br>
<div class="action-title">
<h5><%= t("proposals_dashboard.next_goal.title") %></h5>
<hr>
</div>
<div id="next-goal" data-toggler=".hide">
<%= render 'goal', goal: next_goal %>
<div class="column small-12">
<a data-toggle="complete-course next-goal"><%= t("proposals_dashboard.next_goal.see_complete_course") %></a>
</div>
</div>
<% if course.count > 1 %>
<div class="hide" id="complete-course" data-toggler=".hide">
<%= render partial: 'goal', collection: course %>
<div class="column small-12">
<a data-toggle="complete-course next-goal"><%= t("proposals_dashboard.next_goal.hide_course") %></a>
</div>
</div>
<% end %>
<% end %>

View File

@@ -1,10 +0,0 @@
<br><br>
<div class="action-title">
<h5><%= t("proposals_dashboard.resources.available_resources") %></h5>
<hr>
</div>
<div class="row small-up-2 medium-up-3 large-up-4">
<%= render 'poll_resource' %>
<%= render partial: 'resource', collection: active_resources %>
</div>

View File

@@ -1,26 +0,0 @@
<% content_for :action_title, proposal_dashboard_action.title %>
<div class="row">
<div class="small-12 medium-8 column">
<%== proposal_dashboard_action.description %>
<%= render 'proposals_dashboard/form' %>
</div>
<div class="small-12 medium-4 column">
<% if proposal_dashboard_action.links.any? %>
<div class="proposal-dashboard-action-links">
<h3><%= t("proposals_dashboard.new_request.links") %></h3>
<% proposal_dashboard_action.links.each do |link| %>
<% if link.open_in_new_tab %>
<%= link_to link.label, link.url, target: '_blank' %>
<% else %>
<%= link_to link.label, link.url %>
<% end %>
<% end %>
</div>
<% end %>
<%= render 'documents/documents', documents: proposal_dashboard_action.documents %>
</div>
</div>

View File

@@ -106,10 +106,10 @@ en:
proposal_notification: proposal_notification:
one: "Proposal notification" one: "Proposal notification"
other: "Proposal notifications" other: "Proposal notifications"
proposal_dashboard_action: dashboard/action:
one: Proposal dashboard action one: Proposal dashboard action
other: Proposal dashboard actions other: Proposal dashboard actions
administrator_task: dashboard/administrator_task:
one: Task one: Task
other: Tasks other: Tasks
link: link:
@@ -268,7 +268,7 @@ en:
link_url: Link URL link_url: Link URL
widget/feed: widget/feed:
limit: Number of items limit: Number of items
proposal_dashboard_action: dashboard/action:
title: Title title: Title
short_description: Short description short_description: Short description
description: Description description: Description
@@ -279,7 +279,7 @@ en:
order: Order order: Order
active: Active active: Active
action_type: Type action_type: Type
administrator_task: dashboard/administrator_task:
source: Source source: Source
user: Executed by user: Executed by
link: link:

View File

@@ -318,6 +318,52 @@ en:
back: Go back to %{org} back: Go back to %{org}
title: Administration title: Administration
description: Welcome to the %{org} admin panel. description: Welcome to the %{org} admin panel.
actions:
action_type:
proposed_action: Proposed action
resource: Resource
index:
create: Create
edit: Edit
delete: Delete
no_records: No records found
active: 'Yes'
inactive: 'No'
title: Resources/Recomended actions
action_title: Title
action_type: Type
required_supports: Required supports
action_active: Active
new:
creating: New action for the proposals dashboard
back: Back to list
create:
notice: Action created successfully
edit:
editing: Edit action for the proposals dashboard
back: Back to list
delete:
success: Action successfully deleted
form:
submit_button: Save
day_offset_help_text: Enter 0 so that this value is not taken into account.
required_supports_help_text: Enter 0 so that this value is not taken into account.
administrator_tasks:
index:
title: Pending tasks
solve: Solve
no_records: There are no pending tasks
source: Source
edit:
back: Back to pending tasks list
solving: Solve pending task
form:
solve: Mark as solved
proposal: "The proposal: %{title}"
request: "Has requested: %{title}"
check_details: Check the proposal details
update:
success: The task has been marked as solved.
debates: debates:
index: index:
filter: Filter filter: Filter
@@ -545,8 +591,9 @@ en:
title_booths: Voting booths title_booths: Voting booths
legislation: Collaborative Legislation legislation: Collaborative Legislation
users: Users users: Users
proposals_dashboard: Proposals dashboard dashboard: Proposals dashboard
administrator_tasks: Pending tasks administrator_tasks: Pending tasks
dashboard_actions: Proposal dashboard actions
administrators: administrators:
index: index:
title: Administrators title: Administrators
@@ -1094,36 +1141,6 @@ en:
delete: delete:
success: Geozone successfully deleted success: Geozone successfully deleted
error: This geozone can't be deleted since there are elements attached to it error: This geozone can't be deleted since there are elements attached to it
proposal_dashboard_actions:
action_type:
proposed_action: Proposed action
resource: Resource
index:
create: Create
edit: Edit
delete: Delete
no_records: No records found
active: 'Yes'
inactive: 'No'
title: Resources/Recomended actions
action_title: Title
action_type: Type
required_supports: Required supports
action_active: Active
new:
creating: New action for the proposals dashboard
back: Back to list
create:
notice: Action created successfully
edit:
editing: Edit action for the proposals dashboard
back: Back to list
delete:
success: Action successfully deleted
form:
submit_button: Save
day_offset_help_text: Enter 0 so that this value is not taken into account.
required_supports_help_text: Enter 0 so that this value is not taken into account.
signature_sheets: signature_sheets:
author: Author author: Author
created_at: Creation date created_at: Creation date
@@ -1324,19 +1341,3 @@ en:
submit_header: Save header submit_header: Save header
card_title: Edit card card_title: Edit card
submit_card: Save card submit_card: Save card
proposal_dashboard:
administrator_tasks:
index:
title: Pending tasks
solve: Solve
no_records: There are no pending tasks
edit:
back: Back to pending tasks list
solving: Solve pending task
form:
solve: Mark as solved
proposal: "The proposal: %{title}"
request: "Has requested: %{title}"
check_details: Check the proposal details
update:
success: The task has been marked as solved.

View File

@@ -503,7 +503,7 @@ en:
update: update:
form: form:
submit_button: Save changes submit_button: Save changes
proposals_dashboard: dashboard:
menu: menu:
my_proposal: My proposal my_proposal: My proposal
progress: Progress progress: Progress
@@ -561,7 +561,6 @@ en:
debates: Debates debates: Debates
comments: Comments comments: Comments
latest_comments: Latest messages latest_comments: Latest messages
dashboard:
polls: polls:
index: index:
title: Polls title: Polls

View File

@@ -106,10 +106,10 @@ es:
proposal_notification: proposal_notification:
one: "Notificación de propuesta" one: "Notificación de propuesta"
other: "Notificaciones de propuestas" other: "Notificaciones de propuestas"
proposal_dashboard_action: dashboard/action:
one: Acción del panel de control de propuestas one: Acción del panel de control de propuestas
other: Acciones del panel de control de propuestas other: Acciones del panel de control de propuestas
administrator_task: dashboard/administrator_task:
one: Tarea one: Tarea
other: Tareas other: Tareas
link: link:
@@ -269,7 +269,7 @@ es:
link_url: URL del enlace link_url: URL del enlace
widget/feed: widget/feed:
limit: Número de elementos limit: Número de elementos
proposal_dashboard_action: dashboard/action:
title: Título title: Título
short_description: Descripción corta short_description: Descripción corta
description: Descripción description: Descripción
@@ -280,7 +280,7 @@ es:
order: Orden order: Orden
active: Activa active: Activa
action_type: Tipo action_type: Tipo
administrator_task: dashboard/administrator_task:
source: Fuente source: Fuente
user: Ejecutado por user: Ejecutado por
executed_at: Ejecutado el executed_at: Ejecutado el

View File

@@ -318,6 +318,52 @@ es:
back: Volver a %{org} back: Volver a %{org}
title: Administración title: Administración
description: Bienvenido al panel de administración de %{org}. description: Bienvenido al panel de administración de %{org}.
actions:
action_type:
proposed_action: Acción propuesta
resource: Recurso
index:
create: Crear
edit: Editar
delete: Borrar
no_records: No se encontraron registros
active: 'Si'
inactive: 'No'
title: Recursos/Acciones recomendadas
action_title: Título
action_type: Tipo
required_supports: Apoyos necesarios
action_active: Activo
new:
creating: Nueva acción para el dashboard de propuestas
back: Volver a la lista
create:
notice: Acción creada con éxito
edit:
editing: Editar acción para el dashboard de propuestas
back: Volver a la lista
form:
submit_button: Guardar
day_offset_help_text: Introduce 0 para que este valor no se tenga en cuenta.
required_supports_help_text: Introduce 0 para que este valor no se tenga en cuenta.
delete:
success: Acción borrada con éxito
administrator_tasks:
index:
title: Tareas pendientes
solve: Resolver
no_records: No hay tareas pendientes
source: Origen
edit:
back: Volver a la lista de tareas pendientes
solving: Resolver tarea pendiente
form:
solve: Marcar como resuelta
proposal: "La propuesta: %{title}"
request: "Ha solicitado: %{title}"
check_details: Ver los detalles de la propuesta
update:
success: La tarea ha sido marcada como resuelta
debates: debates:
index: index:
filter: Filtro filter: Filtro
@@ -545,8 +591,9 @@ es:
title_booths: Urnas de votación title_booths: Urnas de votación
legislation: Legislación colaborativa legislation: Legislación colaborativa
users: Usuarios users: Usuarios
proposals_dashboard: Panel de control de propuestas dashboard: Panel de control de propuestas
administrator_tasks: Tareas pendientes administrator_tasks: Tareas pendientes
dashboard_actions: Acciones del panel de control de propuestas
administrators: administrators:
index: index:
title: Administradores title: Administradores
@@ -1094,36 +1141,6 @@ es:
delete: delete:
success: Distrito borrado correctamente success: Distrito borrado correctamente
error: No se puede borrar el distrito porque ya tiene elementos asociados error: No se puede borrar el distrito porque ya tiene elementos asociados
proposal_dashboard_actions:
action_type:
proposed_action: Acción propuesta
resource: Recurso
index:
create: Crear
edit: Editar
delete: Borrar
no_records: No se encontraron registros
active: 'Si'
inactive: 'No'
title: Recursos/Acciones recomendadas
action_title: Título
action_type: Tipo
required_supports: Apoyos necesarios
action_active: Activo
new:
creating: Nueva acción para el dashboard de propuestas
back: Volver a la lista
create:
notice: Acción creada con éxito
edit:
editing: Editar acción para el dashboard de propuestas
back: Volver a la lista
form:
submit_button: Guardar
day_offset_help_text: Introduce 0 para que este valor no se tenga en cuenta.
required_supports_help_text: Introduce 0 para que este valor no se tenga en cuenta.
delete:
success: Acción borrada con éxito
signature_sheets: signature_sheets:
author: Autor author: Autor
created_at: Fecha de creación created_at: Fecha de creación
@@ -1324,19 +1341,3 @@ es:
submit_header: Guardar encabezado submit_header: Guardar encabezado
card_title: Editar tarjeta card_title: Editar tarjeta
submit_card: Guardar tarjeta submit_card: Guardar tarjeta
proposal_dashboard:
administrator_tasks:
index:
title: Tareas pendientes
solve: Resolver
no_records: No hay tareas pendientes
edit:
back: Volver a la lista de tareas pendientes
solving: Resolver tarea pendiente
form:
solve: Marcar como resuelta
proposal: "La propuesta: %{title}"
request: "Ha solicitado: %{title}"
check_details: Ver los detalles de la propuesta
update:
success: La tarea ha sido marcada como resuelta

View File

@@ -503,7 +503,7 @@ es:
update: update:
form: form:
submit_button: Guardar cambios submit_button: Guardar cambios
proposals_dashboard: dashboard:
menu: menu:
my_proposal: Mi propuesta my_proposal: Mi propuesta
progress: Progreso progress: Progreso
@@ -561,7 +561,6 @@ es:
debates: Debates debates: Debates
comments: Comentarios comments: Comentarios
latest_comments: Últimos mensajes latest_comments: Últimos mensajes
dashboard:
polls: polls:
index: index:
title: Encuestas title: Encuestas

View File

@@ -196,7 +196,7 @@ namespace :admin do
resources :feeds, only: [:update] resources :feeds, only: [:update]
end end
namespace :proposal_dashboard do namespace :dashboard do
resources :actions, only: [:index, :new, :create, :edit, :update, :destroy] resources :actions, only: [:index, :new, :create, :edit, :update, :destroy]
resources :administrator_tasks, only: [:index, :edit, :update] resources :administrator_tasks, only: [:index, :edit, :update]
end end

View File

@@ -3,7 +3,7 @@ namespace :dashboard do
end end
resources :proposals do resources :proposals do
resources :proposals_dashboard, as: :dashboard, path: :dashboard, only: [:index] do resources :dashboard, only: [:index] do
collection do collection do
patch :publish patch :publish
get :supports get :supports

View File

@@ -0,0 +1,6 @@
class RenameProposalDashboardActionsToDashboardActions < ActiveRecord::Migration
def change
rename_table :proposal_dashboard_actions, :dashboard_actions
rename_column :proposal_executed_dashboard_actions, :proposal_dashboard_action_id, :dashboard_action_id
end
end

View File

@@ -0,0 +1,5 @@
class RenameProposalExecutedDashboardActionsToDashboardExecutedActions < ActiveRecord::Migration
def change
rename_table :proposal_executed_dashboard_actions, :dashboard_executed_actions
end
end

View File

@@ -0,0 +1,6 @@
class RenameAdministratorTaskToDashboardAdministratorTask < ActiveRecord::Migration
def change
rename_index :administrator_tasks, 'index_administrator_tasks_on_source_type_and_source_id', 'index_dashboard_administrator_tasks_on_source'
rename_table :administrator_tasks, :dashboard_administrator_tasks
end
end

View File

@@ -0,0 +1,5 @@
class RenameDashboardActionIdToActionId < ActiveRecord::Migration
def change
rename_column :dashboard_executed_actions, :dashboard_action_id, :action_id
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180711224810) do ActiveRecord::Schema.define(version: 20180723112930) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -30,18 +30,6 @@ ActiveRecord::Schema.define(version: 20180711224810) do
add_index "activities", ["actionable_id", "actionable_type"], name: "index_activities_on_actionable_id_and_actionable_type", using: :btree add_index "activities", ["actionable_id", "actionable_type"], name: "index_activities_on_actionable_id_and_actionable_type", using: :btree
add_index "activities", ["user_id"], name: "index_activities_on_user_id", using: :btree add_index "activities", ["user_id"], name: "index_activities_on_user_id", using: :btree
create_table "administrator_tasks", force: :cascade do |t|
t.integer "source_id"
t.string "source_type"
t.integer "user_id"
t.datetime "executed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "administrator_tasks", ["source_type", "source_id"], name: "index_administrator_tasks_on_source_type_and_source_id", using: :btree
add_index "administrator_tasks", ["user_id"], name: "index_administrator_tasks_on_user_id", using: :btree
create_table "administrators", force: :cascade do |t| create_table "administrators", force: :cascade do |t|
t.integer "user_id" t.integer "user_id"
end end
@@ -318,6 +306,43 @@ ActiveRecord::Schema.define(version: 20180711224810) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
create_table "dashboard_actions", force: :cascade do |t|
t.string "title", limit: 80
t.text "description"
t.string "link"
t.boolean "request_to_administrators", default: false
t.integer "day_offset", default: 0
t.integer "required_supports", default: 0
t.integer "order", default: 0
t.boolean "active", default: true
t.datetime "hidden_at"
t.integer "action_type", default: 0, null: false
t.string "short_description"
end
create_table "dashboard_administrator_tasks", force: :cascade do |t|
t.integer "source_id"
t.string "source_type"
t.integer "user_id"
t.datetime "executed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "dashboard_administrator_tasks", ["source_type", "source_id"], name: "index_dashboard_administrator_tasks_on_source", using: :btree
add_index "dashboard_administrator_tasks", ["user_id"], name: "index_dashboard_administrator_tasks_on_user_id", using: :btree
create_table "dashboard_executed_actions", force: :cascade do |t|
t.integer "proposal_id"
t.integer "action_id"
t.datetime "executed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "dashboard_executed_actions", ["action_id"], name: "index_proposal_action", using: :btree
add_index "dashboard_executed_actions", ["proposal_id"], name: "index_dashboard_executed_actions_on_proposal_id", using: :btree
create_table "debates", force: :cascade do |t| create_table "debates", force: :cascade do |t|
t.string "title", limit: 80 t.string "title", limit: 80
t.text "description" t.text "description"
@@ -905,31 +930,6 @@ ActiveRecord::Schema.define(version: 20180711224810) do
add_index "polls", ["related_type", "related_id"], name: "index_polls_on_related_type_and_related_id", using: :btree add_index "polls", ["related_type", "related_id"], name: "index_polls_on_related_type_and_related_id", using: :btree
add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree
create_table "proposal_dashboard_actions", force: :cascade do |t|
t.string "title", limit: 80
t.text "description"
t.string "link"
t.boolean "request_to_administrators", default: false
t.integer "day_offset", default: 0
t.integer "required_supports", default: 0
t.integer "order", default: 0
t.boolean "active", default: true
t.datetime "hidden_at"
t.integer "action_type", default: 0, null: false
t.string "short_description"
end
create_table "proposal_executed_dashboard_actions", force: :cascade do |t|
t.integer "proposal_id"
t.integer "proposal_dashboard_action_id"
t.datetime "executed_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "proposal_executed_dashboard_actions", ["proposal_dashboard_action_id"], name: "index_proposal_action", using: :btree
add_index "proposal_executed_dashboard_actions", ["proposal_id"], name: "index_proposal_executed_dashboard_actions_on_proposal_id", using: :btree
create_table "proposal_notifications", force: :cascade do |t| create_table "proposal_notifications", force: :cascade do |t|
t.string "title" t.string "title"
t.text "body" t.text "body"
@@ -1328,11 +1328,13 @@ ActiveRecord::Schema.define(version: 20180711224810) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
add_foreign_key "administrator_tasks", "users"
add_foreign_key "administrators", "users" add_foreign_key "administrators", "users"
add_foreign_key "annotations", "legacy_legislations" add_foreign_key "annotations", "legacy_legislations"
add_foreign_key "annotations", "users" add_foreign_key "annotations", "users"
add_foreign_key "budget_investments", "communities" add_foreign_key "budget_investments", "communities"
add_foreign_key "dashboard_administrator_tasks", "users"
add_foreign_key "dashboard_executed_actions", "dashboard_actions", column: "action_id"
add_foreign_key "dashboard_executed_actions", "proposals"
add_foreign_key "documents", "users" add_foreign_key "documents", "users"
add_foreign_key "failed_census_calls", "poll_officers" add_foreign_key "failed_census_calls", "poll_officers"
add_foreign_key "failed_census_calls", "users" add_foreign_key "failed_census_calls", "users"
@@ -1364,8 +1366,6 @@ ActiveRecord::Schema.define(version: 20180711224810) do
add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id" add_foreign_key "poll_recounts", "poll_booth_assignments", column: "booth_assignment_id"
add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id"
add_foreign_key "poll_voters", "polls" add_foreign_key "poll_voters", "polls"
add_foreign_key "proposal_executed_dashboard_actions", "proposal_dashboard_actions"
add_foreign_key "proposal_executed_dashboard_actions", "proposals"
add_foreign_key "proposals", "communities" add_foreign_key "proposals", "communities"
add_foreign_key "related_content_scores", "related_contents" add_foreign_key "related_content_scores", "related_contents"
add_foreign_key "related_content_scores", "users" add_foreign_key "related_content_scores", "users"

View File

@@ -217,6 +217,14 @@ FactoryBot.define do
trait :draft do trait :draft do
published_at nil published_at nil
end end
trait :retired do
retired_at { Time.current }
end
trait :published do
published_at { Time.current }
end
end end
factory :spending_proposal do factory :spending_proposal do
@@ -1029,7 +1037,7 @@ LOREM_IPSUM
factory :widget_feed, class: 'Widget::Feed' do factory :widget_feed, class: 'Widget::Feed' do
end end
factory :proposal_dashboard_action, class: 'ProposalDashboardAction' do factory :dashboard_action, class: 'Dashboard::Action' do
title { Faker::Lorem.sentence } title { Faker::Lorem.sentence }
description { Faker::Lorem.sentence } description { Faker::Lorem.sentence }
link nil link nil
@@ -1042,13 +1050,11 @@ LOREM_IPSUM
action_type 'proposed_action' action_type 'proposed_action'
trait :admin_request do trait :admin_request do
link nil
request_to_administrators true request_to_administrators true
end end
trait :external_link do trait :external_link do
link { Faker::Internet.url } link { Faker::Internet.url }
request_to_administrators false
end end
trait :inactive do trait :inactive do
@@ -1072,14 +1078,14 @@ LOREM_IPSUM
end end
end end
factory :proposal_executed_dashboard_action, class: 'ProposalExecutedDashboardAction' do factory :dashboard_executed_action, class: 'Dashboard::ExecutedAction' do
proposal proposal
proposal_dashboard_action action { |s| s.association(:dashboard_action) }
executed_at { Time.current } executed_at { Time.current }
end end
factory :administrator_task do factory :dashboard_administrator_task, class: 'Dashboard::AdministratorTask' do
source { |s| s.association(:proposal_executed_dashboard_action) } source { |s| s.association(:dashboard_executed_action) }
user user
executed_at { Time.current } executed_at { Time.current }
@@ -1095,7 +1101,7 @@ LOREM_IPSUM
end end
factory :link do factory :link do
linkable { |s| s.association(:proposal_dashboard_action) } linkable { |s| s.association(:action) }
label { Faker::Lorem.sentence } label { Faker::Lorem.sentence }
url { Faker::Internet.url } url { Faker::Internet.url }
open_in_new_tab false open_in_new_tab false

View File

@@ -1,68 +0,0 @@
require 'rails_helper'
describe 'Administrator tasks' do
let(:administrator) { create(:administrator) }
before do
login_as administrator.user
end
context 'when accessing the pending task list' do
context 'and no pending task' do
before do
visit admin_proposal_dashboard_administrator_tasks_path
end
scenario 'informs that there are no pending tasks' do
expect(page).to have_content('There are no pending tasks')
end
end
context 'and there are pending tasks' do
let!(:task) { create :administrator_task, :pending }
before do
visit admin_proposal_dashboard_administrator_tasks_path
end
scenario 'shows the related proposal title' do
expect(page).to have_content(task.source.proposal.title)
end
scenario 'shows the requested action title' do
expect(page).to have_content(task.source.proposal_dashboard_action.title)
end
scenario 'has a link that allows solving the request' do
expect(page).to have_link('Solve')
end
end
end
context 'when solving a pending task' do
let!(:task) { create :administrator_task, :pending }
before do
visit admin_proposal_dashboard_administrator_tasks_path
click_link 'Solve'
end
scenario 'contains a link to the proposal' do
expect(page).to have_link('Check the proposal details')
end
scenario 'contains a button that solves the request' do
expect(page).to have_button('Mark as solved')
end
context 'and the Mark as solved button is pressed' do
before do
click_button 'Mark as solved'
end
scenario 'The proposal dissapears from the list' do
expect(page).not_to have_content(task.source.proposal.title)
end
end
end
end

View File

@@ -1,6 +1,6 @@
require 'rails_helper' require 'rails_helper'
feature 'Admin proposal dasboard actions' do feature 'Admin dashboard actions' do
let(:admin) { create :administrator } let(:admin) { create :administrator }
before do before do
@@ -10,7 +10,7 @@ feature 'Admin proposal dasboard actions' do
context 'when visiting index' do context 'when visiting index' do
context 'and no actions defined' do context 'and no actions defined' do
before do before do
visit admin_proposal_dashboard_actions_path visit admin_dashboard_actions_path
end end
scenario 'shows that there are no records available' do scenario 'shows that there are no records available' do
@@ -19,10 +19,10 @@ feature 'Admin proposal dasboard actions' do
end end
context 'and actions defined' do context 'and actions defined' do
let!(:action) { create :proposal_dashboard_action } let!(:action) { create :dashboard_action }
before do before do
visit admin_proposal_dashboard_actions_path visit admin_dashboard_actions_path
end end
scenario 'shows the action data' do scenario 'shows the action data' do
@@ -32,16 +32,16 @@ feature 'Admin proposal dasboard actions' do
end end
context 'when creating an action' do context 'when creating an action' do
let(:action) { build :proposal_dashboard_action } let(:action) { build :dashboard_action }
before do before do
visit admin_proposal_dashboard_actions_path visit admin_dashboard_actions_path
click_link 'Create' click_link 'Create'
end end
scenario 'Creates a new action' do scenario 'Creates a new action' do
fill_in 'proposal_dashboard_action_title', with: action.title fill_in 'dashboard_action_title', with: action.title
fill_in 'proposal_dashboard_action_description', with: action.description fill_in 'dashboard_action_description', with: action.description
click_button 'Save' click_button 'Save'
@@ -50,16 +50,16 @@ feature 'Admin proposal dasboard actions' do
end end
context 'when editing an action' do context 'when editing an action' do
let!(:action) { create :proposal_dashboard_action } let!(:action) { create :dashboard_action }
let(:title) { Faker::Lorem.sentence } let(:title) { Faker::Lorem.sentence }
before do before do
visit admin_proposal_dashboard_actions_path visit admin_dashboard_actions_path
click_link 'Edit' click_link 'Edit'
end end
scenario 'Updates the action' do scenario 'Updates the action' do
fill_in 'proposal_dashboard_action_title', with: title fill_in 'dashboard_action_title', with: title
click_button 'Save' click_button 'Save'
expect(page).to have_content(title) expect(page).to have_content(title)
@@ -67,10 +67,10 @@ feature 'Admin proposal dasboard actions' do
end end
context 'when destroying an action' do context 'when destroying an action' do
let!(:action) { create :proposal_dashboard_action } let!(:action) { create :dashboard_action }
before do before do
visit admin_proposal_dashboard_actions_path visit admin_dashboard_actions_path
end end
scenario 'deletes the action', js: true do scenario 'deletes the action', js: true do

View File

@@ -0,0 +1,70 @@
require 'rails_helper'
feature 'Admin administrator tasks' do
let(:admin) { create :administrator }
before do
login_as(admin.user)
end
context 'when visiting index' do
context 'and no pending tasks' do
before do
visit admin_dashboard_administrator_tasks_path
end
scenario 'shows that there are no records available' do
expect(page).to have_content('There are no pending tasks')
end
end
context 'and actions defined' do
let!(:task) { create :dashboard_administrator_task, :pending }
before do
visit admin_dashboard_administrator_tasks_path
end
scenario 'shows the task data' do
expect(page).to have_content(task.source.proposal.title)
expect(page).to have_content(task.source.action.title)
end
scenario 'has a link that allows solving the request' do
expect(page).to have_link('Solve')
end
end
end
context 'when solving a task' do
let!(:task) { create :dashboard_administrator_task, :pending }
before do
visit admin_dashboard_administrator_tasks_path
click_link 'Solve'
end
scenario 'Shows task details' do
expect(page).to have_content(task.source.proposal.title)
expect(page).to have_content(task.source.action.title)
end
scenario 'contains a link to the proposal' do
expect(page).to have_link('Check the proposal details')
end
scenario 'contains a button that solves the request' do
expect(page).to have_button('Mark as solved')
end
scenario 'After it is solved dissapears from the list' do
click_button 'Mark as solved'
expect(page).not_to have_content(task.source.proposal.title)
expect(page).not_to have_content(task.source.action.title)
expect(page).to have_content('The task has been marked as solved')
end
end
end

View File

@@ -0,0 +1,137 @@
require 'rails_helper'
feature "Proposal's dashboard" do
let!(:proposal) { create(:proposal, :draft) }
before do
login_as(proposal.author)
visit proposal_dashboard_index_path(proposal)
end
scenario 'Dashboard has a link to my proposal' do
expect(page).to have_link('My proposal')
end
scenario 'My proposal has a link to edit the proposal' do
expect(page).to have_link('Edit')
end
scenario 'My proposal has a link to retire the proposal' do
expect(page).to have_link('Retire')
end
scenario 'My proposal has a link to publish the proposal' do
expect(page).to have_link('Publish')
end
scenario "Publish link dissapears after proposal's publication" do
click_link 'Publish'
expect(page).not_to have_link('Publish')
end
scenario 'Dashboard progress shows current goal', js: true do
goal = create(:dashboard_action, :resource, :active, required_supports: proposal.votes_for.size + 1_000)
future_goal = create(:dashboard_action, :resource, :active, required_supports: proposal.votes_for.size + 2_000)
visit progress_proposal_dashboard_index_path(proposal)
within 'div#goals-section' do
expect(page).to have_content(goal.title)
expect(page).not_to have_content(future_goal.title)
find(:css, '#see-complete-course-link').click
expect(page).to have_content(goal.title)
expect(page).to have_content(future_goal.title)
end
end
scenario 'Dashboard progress show proposed actions' do
action = create(:dashboard_action, :proposed_action, :active)
visit progress_proposal_dashboard_index_path(proposal)
expect(page).to have_content(action.title)
find(:css, "#dashboard_action_#{action.id}_execute").click
expect(page).not_to have_selector(:css, "#dashboard_action_#{action.id}_execute")
end
scenario 'Dashboard progress show available resources' do
available = create(:dashboard_action, :resource, :active)
requested = create(:dashboard_action, :resource, :admin_request, :active)
executed_action = create(:dashboard_executed_action, action: requested, proposal: proposal, executed_at: Time.current)
_task = create(:dashboard_administrator_task, :pending, source: executed_action)
solved = create(:dashboard_action, :resource, :admin_request, :active)
executed_solved_action = create(:dashboard_executed_action, action: solved, proposal: proposal, executed_at: Time.current)
_solved_task = create(:dashboard_administrator_task, :done, source: executed_solved_action)
unavailable = create(:dashboard_action, :resource, :active, required_supports: proposal.votes_for.size + 1_000)
visit progress_proposal_dashboard_index_path(proposal)
within 'div#available-resources-section' do
expect(page).to have_content('Polls')
expect(page).to have_content(available.title)
expect(page).to have_content(unavailable.title)
expect(page).to have_content(requested.title)
expect(page).to have_content(solved.title)
within "div#dashboard_action_#{available.id}" do
expect(page).to have_link('Request resource')
end
within "div#dashboard_action_#{requested.id}" do
expect(page).to have_content('Resource already requested')
end
within "div#dashboard_action_#{unavailable.id}" do
expect(page).to have_content('1.000 supports required')
end
within "div#dashboard_action_#{solved.id}" do
expect(page).to have_link('See resource')
end
end
end
scenario 'Dashboard has a link to polls feature' do
expect(page).to have_link('Polls')
end
scenario 'Dashboard has a link to resources on main menu' do
feature = create(:dashboard_action, :resource, :active)
visit proposal_dashboard_index_path(proposal)
expect(page).to have_link(feature.title)
end
scenario 'Request resource with admin request', js: true do
feature = create(:dashboard_action, :resource, :active, :admin_request)
visit proposal_dashboard_index_path(proposal)
click_link(feature.title)
click_button 'Request'
expect(page).to have_content('The request for the administrator has been successfully sent.')
end
scenario 'Resource without admin request do not have a request link', js: true do
feature = create(:dashboard_action, :resource, :active)
visit proposal_dashboard_index_path(proposal)
click_link(feature.title)
expect(page).not_to have_button('Request')
end
scenario 'Dashboard has a link to dashboard community', js: true do
expect(page).to have_link('Community')
click_link 'Community'
expect(page).to have_content('Participants')
expect(page).to have_content('Debates')
expect(page).to have_content('Comments')
expect(page).to have_link('Access the community')
end
end

View File

@@ -492,6 +492,27 @@ feature 'Users' do
expect(page).to have_content proposal.title expect(page).to have_content proposal.title
end end
scenario 'Retired proposals do not have a link to the dashboard', js: true do
proposal = create(:proposal, :retired, author: @user)
login_as @user
visit user_path(@user)
expect(page).to have_content proposal.title
expect(page).not_to have_link 'Dashboard'
expect(page).to have_content('Dashboard not available for retired proposals')
end
scenario 'Published proposals have a link to the dashboard' do
proposal = create(:proposal, :published, author: @user)
login_as @user
visit user_path(@user)
expect(page).to have_content proposal.title
expect(page).to have_link 'Dashboard'
end
end end
describe 'Budget Investments' do describe 'Budget Investments' do
@@ -533,5 +554,4 @@ feature 'Users' do
end end
end end
end end

View File

@@ -4,13 +4,13 @@ describe Admin::ProposalDashboardActionsHelper do
describe 'active_human_readable' do describe 'active_human_readable' do
context 'when active is true' do context 'when active is true' do
it 'returns label for active state' do it 'returns label for active state' do
expect(active_human_readable(true)).to eq(t('admin.proposal_dashboard_actions.index.active')) expect(active_human_readable(true)).to eq(t('admin.dashboard.actions.index.active'))
end end
end end
context 'when active is false' do context 'when active is false' do
it 'returns label for inactive state' do it 'returns label for inactive state' do
expect(active_human_readable(false)).to eq(t('admin.proposal_dashboard_actions.index.inactive')) expect(active_human_readable(false)).to eq(t('admin.dashboard.actions.index.inactive'))
end end
end end
end end

View File

@@ -29,7 +29,7 @@ describe Abilities::Administrator do
let(:hidden_comment) { create(:comment, :hidden) } let(:hidden_comment) { create(:comment, :hidden) }
let(:hidden_proposal) { create(:proposal, :hidden) } let(:hidden_proposal) { create(:proposal, :hidden) }
let(:administrator_task) { create(:administrator_task) } let(:dashboard_administrator_task) { create(:dashboard_administrator_task) }
it { should be_able_to(:index, Debate) } it { should be_able_to(:index, Debate) }
it { should be_able_to(:show, debate) } it { should be_able_to(:show, debate) }
@@ -90,11 +90,11 @@ describe Abilities::Administrator do
it { should be_able_to(:destroy, proposal_document) } it { should be_able_to(:destroy, proposal_document) }
it { should_not be_able_to(:destroy, budget_investment_image) } it { should_not be_able_to(:destroy, budget_investment_image) }
it { should_not be_able_to(:destroy, budget_investment_document) } it { should_not be_able_to(:destroy, budget_investment_document) }
it { should be_able_to(:manage, ProposalDashboardAction) } it { should be_able_to(:manage, Dashboard::Action) }
it { should be_able_to(:stats, poll) } it { should be_able_to(:stats, poll) }
it { should be_able_to(:results, poll) } it { should be_able_to(:results, poll) }
it { is_expected.to be_able_to :manage, AdministratorTask } it { is_expected.to be_able_to :manage, Dashboard::AdministratorTask }
it { is_expected.to be_able_to :manage, administrator_task } it { is_expected.to be_able_to :manage, dashboard_administrator_task }
end end

View File

@@ -104,7 +104,7 @@ describe Abilities::Common do
it { should be_able_to(:destroy, own_budget_investment_image) } it { should be_able_to(:destroy, own_budget_investment_image) }
it { should_not be_able_to(:destroy, budget_investment_image) } it { should_not be_able_to(:destroy, budget_investment_image) }
it { should_not be_able_to(:manage, ProposalDashboardAction) } it { should_not be_able_to(:manage, Dashboard::Action) }
describe 'flagging content' do describe 'flagging content' do
it { should be_able_to(:flag, debate) } it { should be_able_to(:flag, debate) }

View File

@@ -34,7 +34,7 @@ describe Abilities::Everyone do
it { should be_able_to(:read_results, finished_budget) } it { should be_able_to(:read_results, finished_budget) }
it { should_not be_able_to(:read_results, reviewing_ballot_budget) } it { should_not be_able_to(:read_results, reviewing_ballot_budget) }
it { should_not be_able_to(:manage, ProposalDashboardAction) } it { should_not be_able_to(:manage, Dashboard::Action) }
context 'when accessing poll results' do context 'when accessing poll results' do
let(:results_enabled) { true } let(:results_enabled) { true }

View File

@@ -1,8 +1,8 @@
require 'rails_helper' require 'rails_helper'
describe ProposalDashboardAction do describe Dashboard::Action do
subject do subject do
build :proposal_dashboard_action, build :dashboard_action,
title: title, title: title,
description: description, description: description,
day_offset: day_offset, day_offset: day_offset,
@@ -85,5 +85,51 @@ describe ProposalDashboardAction do
it { should_not be_valid } it { should_not be_valid }
end end
context 'active_for?' do
let(:proposal) { create(:proposal, published_at: published_at, cached_votes_up: cached_votes_up) }
let(:published_at) { Time.current }
let(:cached_votes_up) { Proposal.votes_needed_for_success + 100 }
it { should be_active_for(proposal) }
context 'and not enough supports' do
let(:required_supports) { cached_votes_up + 100 }
it { should_not be_active_for(proposal) }
end
context 'and not passed enough time since publication' do
let(:day_offset) { 10 }
it { should_not be_active_for(proposal) }
end
end
context 'executed_for? and requested_for?' do
let(:proposal) { create(:proposal) }
subject { create(:dashboard_action, :active, :admin_request, :resource) }
it { should_not be_requested_for(proposal) }
it { should_not be_executed_for(proposal) }
context 'and executed action' do
let(:executed_action) { create(:dashboard_executed_action, proposal: proposal, action: subject) }
context 'and pending administrator task' do
let!(:task) { create(:dashboard_administrator_task, :pending, source: executed_action) }
it { should be_requested_for(proposal) }
it { should_not be_executed_for(proposal) }
end
context 'and solved administrator task' do
let!(:task) { create(:dashboard_administrator_task, :done, source: executed_action) }
it { should be_requested_for(proposal) }
it { should be_executed_for(proposal) }
end
end
end
end end

View File

@@ -0,0 +1,15 @@
require 'rails_helper'
describe Dashboard::AdministratorTask do
subject { build :dashboard_administrator_task, source: executed_action }
let(:executed_action) { build :dashboard_executed_action }
it { should be_valid }
context 'when source is nil' do
let(:executed_action) { nil }
it { should_not be_valid }
end
end

View File

@@ -1,16 +1,16 @@
require 'rails_helper' require 'rails_helper'
describe ProposalExecutedDashboardAction do describe Dashboard::ExecutedAction do
subject do subject do
build :proposal_executed_dashboard_action, build :dashboard_executed_action,
proposal: proposal, proposal: proposal,
proposal_dashboard_action: proposal_dashboard_action, action: action,
executed_at: executed_at executed_at: executed_at
end end
let(:proposal) { create :proposal } let(:proposal) { create :proposal }
let(:proposal_dashboard_action) do let(:action) do
create :proposal_dashboard_action, request_to_administrators: request_to_administrators, link: Faker::Internet.url create :dashboard_action, request_to_administrators: request_to_administrators, link: Faker::Internet.url
end end
let(:request_to_administrators) { false } let(:request_to_administrators) { false }
let(:executed_at) { Time.current } let(:executed_at) { Time.current }
@@ -23,8 +23,8 @@ describe ProposalExecutedDashboardAction do
it { should_not be_valid } it { should_not be_valid }
end end
context 'when proposal_dashboard_action is nil' do context 'when action is nil' do
let(:proposal_dashboard_action) { nil } let(:action) { nil }
it { should_not be_valid } it { should_not be_valid }
end end
@@ -42,7 +42,7 @@ describe ProposalExecutedDashboardAction do
end end
context 'when it has been already executed' do context 'when it has been already executed' do
let!(:executed) { create(:proposal_executed_dashboard_action, proposal: proposal, proposal_dashboard_action: proposal_dashboard_action) } let!(:executed) { create(:dashboard_executed_action, proposal: proposal, action: action) }
it { should_not be_valid } it { should_not be_valid }
end end

View File

@@ -3,13 +3,13 @@ require 'rails_helper'
describe Link do describe Link do
subject do subject do
build :link, build :link,
linkable: proposal_dashboard_action, linkable: dashboard_action,
label: label, label: label,
url: url, url: url,
open_in_new_tab: true open_in_new_tab: true
end end
let(:proposal_dashboard_action) { build :proposal_dashboard_action } let(:dashboard_action) { build :dashboard_action }
let(:label) { Faker::Lorem.sentence } let(:label) { Faker::Lorem.sentence }
let(:url) { Faker::Internet.url } let(:url) { Faker::Internet.url }