[noosfero/noosfero][master] 3 commits: Add responsible attribute to task

Leandro Nunes gitlab at gitlab.com
Sat May 30 22:23:18 BRT 2015


Leandro Nunes pushed to branch master at Noosfero / noosfero


Commits:
eedb7167 by Victor Costa at 2015-05-30T22:07:24Z
Add responsible attribute to task

- - - - -
3b63b2e9 by Leandro Nunes dos Santos at 2015-05-30T22:07:24Z
removing reponsible filter from person task management

- - - - -
4d8cdb3d by Leandro Nunes at 2015-05-31T01:23:09Z
Merge branch 'task_responsible' into 'master'

Allow assignment of a task responsible to improve task management on large communities

Add responsible attribute to task and add an option to filter tasks by responsible.

See merge request !582

- - - - -


9 changed files:

- app/controllers/my_profile/tasks_controller.rb
- app/models/task.rb
- app/views/tasks/_task.html.erb
- app/views/tasks/index.html.erb
- + db/migrate/20150525101430_add_responsible_to_task.rb
- public/javascripts/tasks.js
- public/stylesheets/tasks.css
- test/functional/tasks_controller_test.rb
- test/unit/task_test.rb


Changes:

=====================================
app/controllers/my_profile/tasks_controller.rb
=====================================
--- a/app/controllers/my_profile/tasks_controller.rb
+++ b/app/controllers/my_profile/tasks_controller.rb
@@ -5,15 +5,35 @@ class TasksController < MyProfileController
   def index
     @filter_type = params[:filter_type].presence
     @filter_text = params[:filter_text].presence
+    @filter_responsible = params[:filter_responsible]
     @task_types = Task.pending_types_for(profile)
-    @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page])
+
+    @tasks = Task.pending_all(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.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
 
   def processed
     @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at)
   end
 
+  def change_responsible
+    task = profile.tasks.find(params[:task_id])
+
+    if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i
+      return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id}
+    end
+
+    responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present?
+    task.responsible = responsible
+    task.save!
+    render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}}
+  end
+
   VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
 
   def close


=====================================
app/models/task.rb
=====================================
--- a/app/models/task.rb
+++ b/app/models/task.rb
@@ -33,6 +33,7 @@ class Task < ActiveRecord::Base
 
   belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id
   belongs_to :target, :foreign_key => :target_id, :polymorphic => true
+  belongs_to :responsible, :class_name => 'Person', :foreign_key => :responsible_id
 
   validates_uniqueness_of :code, :on => :create
   validates_presence_of :code


=====================================
app/views/tasks/_task.html.erb
=====================================
--- a/app/views/tasks/_task.html.erb
+++ b/app/views/tasks/_task.html.erb
@@ -2,6 +2,16 @@
 
   <%= render :partial => 'task_icon', :locals => {:task => task} %>
 
+  <% if profile.organization? && @responsible_candidates.present? %>
+    <div class="task_responsible">
+      <span class="label"><%= _('Assign to:') %></span>
+      <span>
+        <% change_responsible_url = url_for :action => :change_responsible, :controller => :tasks %>
+        <%= select_tag "tasks[#{task.id}][responsible]", options_from_collection_for_select(@responsible_candidates, :id, :name, task.responsible.present? ? task.responsible.id : nil), :include_blank => true, :onchange => "change_task_responsible(this);", 'data-old-responsible' => task.responsible.present? ? task.responsible.id : nil, 'data-task' => task.id, 'data-url' => change_responsible_url %>
+      </span>
+    </div>
+  <% end %>
+
   <div class="task_decisions">
     <%=
         labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept',


=====================================
app/views/tasks/index.html.erb
=====================================
--- a/app/views/tasks/index.html.erb
+++ b/app/views/tasks/index.html.erb
@@ -29,6 +29,11 @@
     <p>
       <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %>
     </p>
+    <% if profile.organization? %>
+      <p>
+        <%= 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') %>
+      </p>
+    <% end %>
     <p>
       <%= submit_button(:search, _('Search')) %>
     </p>


=====================================
db/migrate/20150525101430_add_responsible_to_task.rb
=====================================
--- /dev/null
+++ b/db/migrate/20150525101430_add_responsible_to_task.rb
@@ -0,0 +1,7 @@
+class AddResponsibleToTask < ActiveRecord::Migration
+
+  def change
+    add_column :tasks, :responsible_id, :integer
+  end
+
+end


=====================================
public/javascripts/tasks.js
=====================================
--- a/public/javascripts/tasks.js
+++ b/public/javascripts/tasks.js
@@ -47,3 +47,19 @@
 
 })(jQuery)
 
+function change_task_responsible(el) {
+  jQuery.post($(el).data('url'), {task_id: $(el).data('task'),
+                    responsible_id: $(el).val(),
+                    old_responsible_id: $(el).data('old-responsible')}, function(data) {
+    if (data.success) {
+      $(el).effect("highlight");
+      $(el).data('old-responsible', data.new_responsible.id);
+    } else {
+      $(el).effect("highlight", {color: 'red'});
+    }
+    if (data.notice) {
+      display_notice(data.notice);
+    }
+  });
+}
+


=====================================
public/stylesheets/tasks.css
=====================================
--- a/public/stylesheets/tasks.css
+++ b/public/stylesheets/tasks.css
@@ -49,3 +49,7 @@
   text-decoration: underline;
   font-weight: bold;
 }
+
+.task_responsible {
+  text-align: right;
+}


=====================================
test/functional/tasks_controller_test.rb
=====================================
--- a/test/functional/tasks_controller_test.rb
+++ b/test/functional/tasks_controller_test.rb
@@ -433,4 +433,91 @@ class TasksControllerTest < ActionController::TestCase
     post :index, :page => 2
     assert_equal [t4], assigns(:tasks)
   end
+
+  should 'filter tasks by responsible' do
+    Task.stubs(:per_page).returns(3)
+    requestor = fast_create(Person)
+    responsible = fast_create(Person)
+    t1 = Task.create!(:requestor => requestor, :target => profile, :responsible => responsible)
+    t2 = Task.create!(:requestor => requestor, :target => profile, :responsible => responsible)
+    t3 = Task.create!(:requestor => requestor, :target => profile)
+
+    get :index, :filter_responsible => responsible.id
+
+    assert_includes assigns(:tasks), t1
+    assert_includes assigns(:tasks), t2
+    assert_not_includes assigns(:tasks), t3
+
+    get :index
+
+    assert_includes assigns(:tasks), t1
+    assert_includes assigns(:tasks), t2
+    assert_includes assigns(:tasks), t3
+  end
+
+  should 'do not display responsible assignment if profile is not an organization' do
+    profile = create_user('personprofile').person
+    t1 = Task.create!(:requestor => profile, :target => profile)
+    @controller.stubs(:profile).returns(profile)
+    login_as profile.user.login
+    get :index
+
+    assert_select "#task-#{t1.id}"
+    assert_select '.task_responsible', 0
+  end
+
+  should 'do not display responsible assignment filter if profile is not an organization' do
+    profile = create_user('personprofile').person
+    @controller.stubs(:profile).returns(profile)
+    login_as profile.user.login
+    get :index
+
+    assert_select '.filter_responsible', 0
+  end
+
+  should 'display responsible assignment if profile is an organization' do
+    profile = fast_create(Community)
+    person1 = create_user('person1').person
+    person2 = create_user('person2').person
+    person3 = create_user('person3').person
+    profile.add_admin(person1)
+    profile.add_admin(person2)
+    profile.add_member(person3)
+    Task.create!(:requestor => person3, :target => profile)
+    @controller.stubs(:profile).returns(profile)
+
+    login_as person1.user.login
+    get :index
+    assert_equivalent [person1, person2], assigns(:responsible_candidates)
+    assert_select '.task_responsible'
+  end
+
+  should 'change task responsible' do
+    profile = fast_create(Community)
+    @controller.stubs(:profile).returns(profile)
+    person = create_user('person1').person
+    profile.add_admin(person)
+    task = Task.create!(:requestor => person, :target => profile)
+
+    assert_equal nil, task.responsible
+    login_as person.user.login
+    post :change_responsible, :task_id => task.id, :responsible_id => person.id
+    assert_equal person, task.reload.responsible
+  end
+
+  should 'not change task responsible if old responsible is not the current' do
+    profile = fast_create(Community)
+    @controller.stubs(:profile).returns(profile)
+    person1 = create_user('person1').person
+    person2 = create_user('person2').person
+    profile.add_admin(person1)
+    task = Task.create!(:requestor => person1, :target => profile, :responsible => person1)
+
+    login_as person1.user.login
+    post :change_responsible, :task_id => task.id, :responsible_id => person2.id, :old_responsible => nil
+    assert_equal person1, task.reload.responsible
+    json_response = ActiveSupport::JSON.decode(response.body)
+    assert !json_response['success']
+  end
+
 end


=====================================
test/unit/task_test.rb
=====================================
--- a/test/unit/task_test.rb
+++ b/test/unit/task_test.rb
@@ -432,6 +432,14 @@ class TaskTest < ActiveSupport::TestCase
     assert t1.ham?
   end
 
+  should 'be able to assign a responsible to a task' do
+    person = fast_create(Person)
+    task = fast_create(Task)
+    task.responsible = person
+    task.save!
+    assert_equal person, task.responsible
+  end
+
   protected
 
   def sample_user



View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/923baeaaf6ec95d3e001c9e944bbe18bb6115ee1...4d8cdb3d01b2c672c6df56d126f8e0bb4e700bac
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150531/b6115170/attachment-0001.html>


More information about the Noosfero-dev mailing list