Commit eedb71671eeb96d4b20730f1309681b50f390dbf
Committed by
Leandro Santos
1 parent
99a580fd
Exists in
master
and in
25 other branches
Add responsible attribute to task
Showing
9 changed files
with
148 additions
and
1 deletions
Show diff stats
app/controllers/my_profile/tasks_controller.rb
@@ -5,15 +5,35 @@ class TasksController < MyProfileController | @@ -5,15 +5,35 @@ class TasksController < MyProfileController | ||
5 | def index | 5 | def index |
6 | @filter_type = params[:filter_type].presence | 6 | @filter_type = params[:filter_type].presence |
7 | @filter_text = params[:filter_text].presence | 7 | @filter_text = params[:filter_text].presence |
8 | + @filter_responsible = params[:filter_responsible] | ||
8 | @task_types = Task.pending_types_for(profile) | 9 | @task_types = Task.pending_types_for(profile) |
9 | - @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | 10 | + |
11 | + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc') | ||
12 | + @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? | ||
13 | + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) | ||
14 | + | ||
10 | @failed = params ? params[:failed] : {} | 15 | @failed = params ? params[:failed] : {} |
16 | + | ||
17 | + @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) | ||
11 | end | 18 | end |
12 | 19 | ||
13 | def processed | 20 | def processed |
14 | @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) | 21 | @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) |
15 | end | 22 | end |
16 | 23 | ||
24 | + def change_responsible | ||
25 | + task = profile.tasks.find(params[:task_id]) | ||
26 | + | ||
27 | + if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i | ||
28 | + return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id} | ||
29 | + end | ||
30 | + | ||
31 | + responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present? | ||
32 | + task.responsible = responsible | ||
33 | + task.save! | ||
34 | + render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}} | ||
35 | + end | ||
36 | + | ||
17 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] | 37 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
18 | 38 | ||
19 | def close | 39 | def close |
app/models/task.rb
@@ -33,6 +33,7 @@ class Task < ActiveRecord::Base | @@ -33,6 +33,7 @@ class Task < ActiveRecord::Base | ||
33 | 33 | ||
34 | belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id | 34 | belongs_to :requestor, :class_name => 'Profile', :foreign_key => :requestor_id |
35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true | 35 | belongs_to :target, :foreign_key => :target_id, :polymorphic => true |
36 | + belongs_to :responsible, :class_name => 'Person', :foreign_key => :responsible_id | ||
36 | 37 | ||
37 | validates_uniqueness_of :code, :on => :create | 38 | validates_uniqueness_of :code, :on => :create |
38 | validates_presence_of :code | 39 | validates_presence_of :code |
app/views/tasks/_task.html.erb
@@ -2,6 +2,16 @@ | @@ -2,6 +2,16 @@ | ||
2 | 2 | ||
3 | <%= render :partial => 'task_icon', :locals => {:task => task} %> | 3 | <%= render :partial => 'task_icon', :locals => {:task => task} %> |
4 | 4 | ||
5 | + <% if profile.organization? && @responsible_candidates.present? %> | ||
6 | + <div class="task_responsible"> | ||
7 | + <span class="label"><%= _('Assign to:') %></span> | ||
8 | + <span> | ||
9 | + <% change_responsible_url = url_for :action => :change_responsible, :controller => :tasks %> | ||
10 | + <%= 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 %> | ||
11 | + </span> | ||
12 | + </div> | ||
13 | + <% end %> | ||
14 | + | ||
5 | <div class="task_decisions"> | 15 | <div class="task_decisions"> |
6 | <%= | 16 | <%= |
7 | labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', | 17 | labelled_radio_button(_("Accept"), "tasks[#{task.id}][decision]", 'finish', task.default_decision == 'accept', |
app/views/tasks/index.html.erb
@@ -30,6 +30,9 @@ | @@ -30,6 +30,9 @@ | ||
30 | <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %> | 30 | <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %> |
31 | </p> | 31 | </p> |
32 | <p> | 32 | <p> |
33 | + <%= labelled_select(_('Assigned to')+': ', :filter_responsible, :id, :name, @filter_responsible, [OpenStruct.new(:name => _('All'), :id => nil), OpenStruct.new(:name => _('Unassigned'), :id => -1)] + @responsible_candidates) %> | ||
34 | + </p> | ||
35 | + <p> | ||
33 | <%= submit_button(:search, _('Search')) %> | 36 | <%= submit_button(:search, _('Search')) %> |
34 | </p> | 37 | </p> |
35 | <% end %> | 38 | <% end %> |
public/javascripts/tasks.js
@@ -47,3 +47,19 @@ | @@ -47,3 +47,19 @@ | ||
47 | 47 | ||
48 | })(jQuery) | 48 | })(jQuery) |
49 | 49 | ||
50 | +function change_task_responsible(el) { | ||
51 | + jQuery.post($(el).data('url'), {task_id: $(el).data('task'), | ||
52 | + responsible_id: $(el).val(), | ||
53 | + old_responsible_id: $(el).data('old-responsible')}, function(data) { | ||
54 | + if (data.success) { | ||
55 | + $(el).effect("highlight"); | ||
56 | + $(el).data('old-responsible', data.new_responsible.id); | ||
57 | + } else { | ||
58 | + $(el).effect("highlight", {color: 'red'}); | ||
59 | + } | ||
60 | + if (data.notice) { | ||
61 | + display_notice(data.notice); | ||
62 | + } | ||
63 | + }); | ||
64 | +} | ||
65 | + |
public/stylesheets/tasks.css
test/functional/tasks_controller_test.rb
@@ -433,4 +433,82 @@ class TasksControllerTest < ActionController::TestCase | @@ -433,4 +433,82 @@ class TasksControllerTest < ActionController::TestCase | ||
433 | post :index, :page => 2 | 433 | post :index, :page => 2 |
434 | assert_equal [t4], assigns(:tasks) | 434 | assert_equal [t4], assigns(:tasks) |
435 | end | 435 | end |
436 | + | ||
437 | + should 'filter tasks by responsible' do | ||
438 | + Task.stubs(:per_page).returns(3) | ||
439 | + requestor = fast_create(Person) | ||
440 | + responsible = fast_create(Person) | ||
441 | + t1 = Task.create!(:requestor => requestor, :target => profile, :responsible => responsible) | ||
442 | + t2 = Task.create!(:requestor => requestor, :target => profile, :responsible => responsible) | ||
443 | + t3 = Task.create!(:requestor => requestor, :target => profile) | ||
444 | + | ||
445 | + get :index, :filter_responsible => responsible.id | ||
446 | + | ||
447 | + assert_includes assigns(:tasks), t1 | ||
448 | + assert_includes assigns(:tasks), t2 | ||
449 | + assert_not_includes assigns(:tasks), t3 | ||
450 | + | ||
451 | + get :index | ||
452 | + | ||
453 | + assert_includes assigns(:tasks), t1 | ||
454 | + assert_includes assigns(:tasks), t2 | ||
455 | + assert_includes assigns(:tasks), t3 | ||
456 | + end | ||
457 | + | ||
458 | + should 'do not display responsible assignment if profile is not an organization' do | ||
459 | + profile = create_user('personprofile').person | ||
460 | + t1 = Task.create!(:requestor => profile, :target => profile) | ||
461 | + @controller.stubs(:profile).returns(profile) | ||
462 | + login_as profile.user.login | ||
463 | + get :index | ||
464 | + | ||
465 | + assert_select "#task-#{t1.id}" | ||
466 | + assert_select '.task_responsible', 0 | ||
467 | + end | ||
468 | + | ||
469 | + should 'display responsible assignment if profile is an organization' do | ||
470 | + profile = fast_create(Community) | ||
471 | + person1 = create_user('person1').person | ||
472 | + person2 = create_user('person2').person | ||
473 | + person3 = create_user('person3').person | ||
474 | + profile.add_admin(person1) | ||
475 | + profile.add_admin(person2) | ||
476 | + profile.add_member(person3) | ||
477 | + Task.create!(:requestor => person3, :target => profile) | ||
478 | + @controller.stubs(:profile).returns(profile) | ||
479 | + | ||
480 | + login_as person1.user.login | ||
481 | + get :index | ||
482 | + assert_equivalent [person1, person2], assigns(:responsible_candidates) | ||
483 | + assert_select '.task_responsible' | ||
484 | + end | ||
485 | + | ||
486 | + should 'change task responsible' do | ||
487 | + profile = fast_create(Community) | ||
488 | + @controller.stubs(:profile).returns(profile) | ||
489 | + person = create_user('person1').person | ||
490 | + profile.add_admin(person) | ||
491 | + task = Task.create!(:requestor => person, :target => profile) | ||
492 | + | ||
493 | + assert_equal nil, task.responsible | ||
494 | + login_as person.user.login | ||
495 | + post :change_responsible, :task_id => task.id, :responsible_id => person.id | ||
496 | + assert_equal person, task.reload.responsible | ||
497 | + end | ||
498 | + | ||
499 | + should 'not change task responsible if old responsible is not the current' do | ||
500 | + profile = fast_create(Community) | ||
501 | + @controller.stubs(:profile).returns(profile) | ||
502 | + person1 = create_user('person1').person | ||
503 | + person2 = create_user('person2').person | ||
504 | + profile.add_admin(person1) | ||
505 | + task = Task.create!(:requestor => person1, :target => profile, :responsible => person1) | ||
506 | + | ||
507 | + login_as person1.user.login | ||
508 | + post :change_responsible, :task_id => task.id, :responsible_id => person2.id, :old_responsible => nil | ||
509 | + assert_equal person1, task.reload.responsible | ||
510 | + json_response = ActiveSupport::JSON.decode(response.body) | ||
511 | + assert !json_response['success'] | ||
512 | + end | ||
513 | + | ||
436 | end | 514 | end |
test/unit/task_test.rb
@@ -432,6 +432,14 @@ class TaskTest < ActiveSupport::TestCase | @@ -432,6 +432,14 @@ class TaskTest < ActiveSupport::TestCase | ||
432 | assert t1.ham? | 432 | assert t1.ham? |
433 | end | 433 | end |
434 | 434 | ||
435 | + should 'be able to assign a responsible to a task' do | ||
436 | + person = fast_create(Person) | ||
437 | + task = fast_create(Task) | ||
438 | + task.responsible = person | ||
439 | + task.save! | ||
440 | + assert_equal person, task.responsible | ||
441 | + end | ||
442 | + | ||
435 | protected | 443 | protected |
436 | 444 | ||
437 | def sample_user | 445 | def sample_user |