diff --git a/controllers/myprofile/proposals_discussion_plugin_evaluate_tasks_controller.rb b/controllers/myprofile/proposals_discussion_plugin_evaluate_tasks_controller.rb
new file mode 100644
index 0000000..1c8d394
--- /dev/null
+++ b/controllers/myprofile/proposals_discussion_plugin_evaluate_tasks_controller.rb
@@ -0,0 +1,41 @@
+class ProposalsDiscussionPluginEvaluateTasksController < MyProfileController
+
+ protect :view_tasks, :profile, :only => [:flag_approve_proposal, :flag_reject_proposal]
+
+ def flag_approve_proposal
+ if request.post? && params[:task_id]
+ result = {
+ success: false,
+ message: _('Error flagging proposal. Please, contact the system admin')
+ }
+
+ task = Task.to(profile).find_by_id params[:task_id]
+ save = task.flag_accept_proposal(current_person)
+
+ if save
+ result = {:success => true }
+ end
+ end
+
+ render json: result
+ end
+
+ def flag_reject_proposal
+ if request.post? && params[:task_id]
+ result = {
+ success: false,
+ message: _('Error flagging proposal. Please, contact the system admin')
+ }
+
+ task = Task.to(profile).find_by_id params[:task_id]
+ save = task.flag_reject_proposal(current_person)
+
+ if save
+ result = {:success => true }
+ end
+ end
+
+ render json: result
+ end
+
+end
diff --git a/controllers/myprofile/proposals_discussion_plugin_tasks_controller.rb b/controllers/myprofile/proposals_discussion_plugin_tasks_controller.rb
new file mode 100644
index 0000000..0f434eb
--- /dev/null
+++ b/controllers/myprofile/proposals_discussion_plugin_tasks_controller.rb
@@ -0,0 +1,35 @@
+class ProposalsDiscussionPluginTasksController < TasksController
+
+ def index
+ @email_templates = profile.email_templates.find_all_by_template_type(:task_rejection)
+
+ @filter_type = params[:filter_type].presence
+ @filter_text = params[:filter_text].presence
+ @filter_responsible = params[:filter_responsible]
+ @filter_tags = params[:filter_tags]
+
+ @view_only = !current_person.has_permission?(:perform_task, profile)
+
+ @task_tags = [OpenStruct.new(:name => _('All'), :id => nil) ] + Task.all_tags
+ @task_types = Task.pending_types_for(profile)
+
+ if @view_only
+ @tasks = Task.pending_all(profile, false, false).order_by('created_at', 'asc')
+ @tasks = @tasks.where(:responsible_id => current_person.id)
+ else
+
+ @tasks = ProposalsDiscussionPlugin::ProposalTask.pending_evaluated(profile, @filter_type, @filter_text).order_by('created_at', 'asc')
+ @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
+ @tasks = @tasks.tagged_with(@filter_tags, any: true) if @filter_tags.present?
+ end
+
+ @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
+
+ @failed = params ? params[:failed] : {}
+
+ @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization?
+
+
+ end
+
+end
diff --git a/db/migrate/20150618100000_create_proposal_evaluation_table.rb b/db/migrate/20150618100000_create_proposal_evaluation_table.rb
new file mode 100644
index 0000000..0e95fdb
--- /dev/null
+++ b/db/migrate/20150618100000_create_proposal_evaluation_table.rb
@@ -0,0 +1,23 @@
+class CreateProposalEvaluationTable < ActiveRecord::Migration
+ def self.up
+ create_table :proposals_discussion_plugin_proposal_evaluations do |t|
+ t.integer "proposal_task_id"
+ t.integer "evaluator_id"
+ t.integer "flagged_status"
+ t.timestamps
+ end
+ add_index(
+ :proposals_discussion_plugin_proposal_evaluations,
+ [:proposal_task_id],
+ name: 'index_proposals_discussion_plugin_proposal_task_id'
+ )
+ add_index(
+ :proposals_discussion_plugin_proposal_evaluations,
+ [:evaluator_id],
+ name: 'index_proposals_discussion_plugin_proposal_evaluator_id'
+ )
+ end
+ def self.down
+ drop_table :proposals_discussion_plugin_proposal_evaluations
+ end
+end
diff --git a/lib/proposals_discussion_plugin/proposal_evaluation.rb b/lib/proposals_discussion_plugin/proposal_evaluation.rb
new file mode 100644
index 0000000..cb78e10
--- /dev/null
+++ b/lib/proposals_discussion_plugin/proposal_evaluation.rb
@@ -0,0 +1,7 @@
+class ProposalsDiscussionPlugin::ProposalEvaluation < Noosfero::Plugin::ActiveRecord
+ belongs_to :proposal_task
+ belongs_to :evaluated_by, :class_name => 'Person', :foreign_key => :evaluator_id
+
+ attr_accessor :flagged_status
+
+end
diff --git a/lib/proposals_discussion_plugin/proposal_task.rb b/lib/proposals_discussion_plugin/proposal_task.rb
index 3270786..bfbe558 100644
--- a/lib/proposals_discussion_plugin/proposal_task.rb
+++ b/lib/proposals_discussion_plugin/proposal_task.rb
@@ -10,6 +10,16 @@ class ProposalsDiscussionPlugin::ProposalTask < Task
settings_items :article, :type => Hash, :default => {}
settings_items :closing_statment, :article_parent_id
+
+ scope :pending_evaluated, lambda { |profile, filter_type, filter_text|
+ self
+ .to(profile)
+ .without_spam.pending
+ .of(filter_type)
+ .like('data', filter_text)
+ .where(:status => ProposalsDiscussionPlugin::ProposalTask::Status.evaluated_statuses)
+ }
+
before_create do |task|
if !task.target.nil?
organization = task.target
@@ -18,8 +28,80 @@ class ProposalsDiscussionPlugin::ProposalTask < Task
end
end
+ def unflagged?
+ ! flagged?
+ end
+
+ def flagged?
+ flagged_for_approval? || flagged_for_reproval?
+ end
+
+ def flagged_for_approval?
+ Status::FLAGGED_FOR_APPROVAL.eql?(self.status)
+ end
+
+ def flagged_for_reproval?
+ Status::FLAGGED_FOR_REPROVAL.eql?(self.status)
+ end
+
after_create :schedule_spam_checking
+ module Status
+ FLAGGED_FOR_APPROVAL = 5
+ FLAGGED_FOR_REPROVAL = 6
+
+ class << self
+ def names
+ [
+ nil,
+ N_('Active'), N_('Cancelled'), N_('Finished'),
+ N_('Hidden'), N_('Flagged for Approval'), N_('Flagged for Reproval')
+ ]
+ end
+
+ def evaluated_statuses
+ [
+ FLAGGED_FOR_APPROVAL,
+ FLAGGED_FOR_REPROVAL
+ ]
+ end
+ end
+ end
+
+
+ def flag_accept_proposal(evaluated_by)
+ transaction do
+ if evaluated_by
+ ProposalsDiscussionPlugin::ProposalEvaluation.new do |evaluation|
+ evaluation.evaluated_by = evaluated_by
+ evaluation.flagged_status = Status::FLAGGED_FOR_APPROVAL
+ evaluation.proposal_task = self
+ evaluation.save!
+ end
+ end
+ self.status = Status::FLAGGED_FOR_APPROVAL
+ self.save!
+ return true
+ end
+ end
+
+ def flag_reject_proposal(evaluated_by)
+ transaction do
+ if evaluated_by
+ ProposalsDiscussionPlugin::ProposalEvaluation.new do |evaluation|
+ evaluation.evaluated_by = evaluated_by
+ evaluation.flagged_status = Status::FLAGGED_FOR_REPROVAL
+ evaluation.proposal_task = self
+ evaluation.save!
+ end
+ end
+ self.status = Status::FLAGGED_FOR_REPROVAL
+ self.save!
+ return true
+ end
+ end
+
+
def schedule_spam_checking
self.delay.check_for_spam
end
@@ -65,7 +147,6 @@ class ProposalsDiscussionPlugin::ProposalTask < Task
article_abstract
end
-
def information
{:message => _("%{requestor} wants to send the following proposal.
%{abstract}"), :variables => {:abstract => abstract}}
end
@@ -90,7 +171,7 @@ class ProposalsDiscussionPlugin::ProposalTask < Task
# def article_title
# article ? article.title : _('(The original text was removed)')
# end
-
+
# def article
# Article.find_by_id data[:article_id]
# end
diff --git a/public/images/approval.png b/public/images/approval.png
new file mode 100644
index 0000000..be13a3e
Binary files /dev/null and b/public/images/approval.png differ
diff --git a/public/images/reproval.png b/public/images/reproval.png
new file mode 100644
index 0000000..bab6f37
Binary files /dev/null and b/public/images/reproval.png differ
diff --git a/public/style.css b/public/style.css
index 9d0e302..642def4 100644
--- a/public/style.css
+++ b/public/style.css
@@ -319,3 +319,33 @@ form .proposals-discussion-plugin .body textarea {
#content .article-body.article-body-proposals-discussion-plugin_proposal .discussion {
color: gray;
}
+
+.evaluation_bar {
+ width: 400px;
+}
+
+.evaluation_button {
+ cursor: pointer;
+}
+
+.evaluation_button img {
+ float:left;
+ width: 32px;
+ height:32px;
+ margin-left: 30px;
+}
+
+.evaluation_button span {
+ margin-left: 8px;
+ font-size: 24px;
+ width: auto;
+ float:left;
+}
+
+.evaluation_button.approval span {
+ color: green;
+}
+
+.evaluation_button.reproval span {
+ color: red;
+}
diff --git a/views/proposals_discussion_plugin_tasks/_task_accept_details.html.erb b/views/proposals_discussion_plugin_tasks/_task_accept_details.html.erb
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/views/proposals_discussion_plugin_tasks/_task_accept_details.html.erb
diff --git a/views/proposals_discussion_plugin_tasks/_task_reject_details.html.erb b/views/proposals_discussion_plugin_tasks/_task_reject_details.html.erb
new file mode 100644
index 0000000..6a0452c
--- /dev/null
+++ b/views/proposals_discussion_plugin_tasks/_task_reject_details.html.erb
@@ -0,0 +1,5 @@
+<% if @email_templates.present? %>
+
+ +<% + type_collection = [[nil, _('All')]] + @task_types +%> + +<% if !@failed.blank? %> +
<%=_("This error happened with the following tasks: ")%>
++ <%= labelled_select(_('Type of task')+': ', :filter_type, :first, :last, @filter_type, type_collection, {:id => 'filter-type'}) %> +
++ <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %> +
+ <% if profile.organization? %> ++ <%= labelled_select(_('Assigned to')+': ', :filter_responsible, :id, :name, @filter_responsible, [OpenStruct.new(:name => _('All'), :id => nil), OpenStruct.new(:name => _('Unassigned'), :id => -1)] + @responsible_candidates, :class => 'filter_responsible') %> +
+ <% end %> ++ <%= labelled_select(_('Tags')+': ', :filter_tags, :id, :name, @filter_tags, @task_tags, {:id => 'filter-add-tag'}) %> + <%= text_field_tag( :filter_tags, @filter_tags, :size => 36, :class => 'filter-tags' ) %> +
+ ++ <%= submit_button(:search, _('Search')) %> +
+ <% end %> + <% end %> +<% end %> +<% if @tasks.empty? %> ++ <%= _('No pending tasks for %s') % profile.name %> +
+<% else %> + <%= form_tag :action => 'close' do%> + <% button_bar(:class => 'task-actions') do %> + <%# FiXME button(:edit, _('View my requests'), :action => 'list_requested') %> + <%# FIXME button('menu-mail', _('Send request'), :action => 'new') %> + <%= submit_button :save, _("Apply!") %> + <%= button(:edit, _('View processed tasks'), :action => 'processed') %> + <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> + <% end unless @view_only %> + ++ <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> +
+ <% end %> + ++ <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> +
+ <% end %> +