Commit 27f11bf70f49c69586dfd9c479d448642e7cecf1
Exists in
web_steps_improvements
and in
6 other branches
Merge branch 'tasks_text_filter_with_autocomplete' into 'master'
Autocomplete tasks by name in administration area. - Create a text field to autocomplete administration tasks. Signed-off-by: Leandro Nunes <lenadronunes@gmail.com> Signed-off-by: Michel Felipe <mfelipeof@gmail.com> See merge request !831
Showing
5 changed files
with
78 additions
and
27 deletions
Show diff stats
app/controllers/my_profile/tasks_controller.rb
@@ -14,16 +14,15 @@ class TasksController < MyProfileController | @@ -14,16 +14,15 @@ class TasksController < MyProfileController | ||
14 | @filter_text = params[:filter_text].presence | 14 | @filter_text = params[:filter_text].presence |
15 | @filter_responsible = params[:filter_responsible] | 15 | @filter_responsible = params[:filter_responsible] |
16 | @task_types = Task.pending_types_for(profile) | 16 | @task_types = Task.pending_types_for(profile) |
17 | - | ||
18 | - @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc') | 17 | + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) |
19 | @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? | 18 | @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? |
20 | @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) | 19 | @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) |
21 | - | ||
22 | @failed = params ? params[:failed] : {} | 20 | @failed = params ? params[:failed] : {} |
23 | 21 | ||
24 | @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization? | 22 | @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task')}) if profile.organization? |
25 | 23 | ||
26 | @view_only = !current_person.has_permission?(:perform_task, profile) | 24 | @view_only = !current_person.has_permission?(:perform_task, profile) |
25 | + | ||
27 | end | 26 | end |
28 | 27 | ||
29 | def processed | 28 | def processed |
@@ -95,4 +94,12 @@ class TasksController < MyProfileController | @@ -95,4 +94,12 @@ class TasksController < MyProfileController | ||
95 | @ticket = Ticket.where('(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]).first | 94 | @ticket = Ticket.where('(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]).first |
96 | end | 95 | end |
97 | 96 | ||
97 | + def search_tasks | ||
98 | + filter_type = params[:filter_type].presence | ||
99 | + filter_text = params[:filter_text].presence | ||
100 | + result = Task.pending_all(profile,filter_type, filter_text) | ||
101 | + | ||
102 | + render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} } | ||
103 | + end | ||
104 | + | ||
98 | end | 105 | end |
app/models/task.rb
@@ -324,6 +324,7 @@ class Task < ActiveRecord::Base | @@ -324,6 +324,7 @@ class Task < ActiveRecord::Base | ||
324 | where [environment_condition, profile_condition].compact.join(' OR ') | 324 | where [environment_condition, profile_condition].compact.join(' OR ') |
325 | } | 325 | } |
326 | 326 | ||
327 | + | ||
327 | def self.pending_types_for(profile) | 328 | def self.pending_types_for(profile) |
328 | Task.to(profile).pending.select('distinct type').map { |t| [t.class.name, t.title] } | 329 | Task.to(profile).pending.select('distinct type').map { |t| [t.class.name, t.title] } |
329 | end | 330 | end |
app/views/tasks/index.html.erb
@@ -21,25 +21,20 @@ | @@ -21,25 +21,20 @@ | ||
21 | </div> | 21 | </div> |
22 | <% end %> | 22 | <% end %> |
23 | 23 | ||
24 | -<%= form_tag '#', :method => 'get' do %> | ||
25 | - <%= field_set_tag _('Filter'), :class => 'filter_fields' do %> | ||
26 | - <p> | ||
27 | - <%= labelled_select(_('Type of task')+': ', :filter_type, :first, :last, @filter_type, type_collection, {:id => 'filter-type'}) %> | ||
28 | - </p> | ||
29 | - <p> | ||
30 | - <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text',:value => @filter_text}) %> | ||
31 | - </p> | ||
32 | - <% if profile.organization? %> | ||
33 | - <p> | ||
34 | - <%= 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') %> | ||
35 | - </p> | 24 | +<%= form_tag '#', :method => 'post' do %> |
25 | + | ||
26 | + <%= field_set_tag _('Filter'), :class => 'filter_fields' do %> | ||
27 | + <p> | ||
28 | + <%= labelled_select(_('Type of task')+': ', :filter_type, :first, :last, @filter_type, type_collection, {:id => 'filter-type'}) %> | ||
29 | + </p> | ||
30 | + <p> | ||
31 | + <%= labelled_text_field(_("Text filter")+': ', :filter_text, nil, {:id => 'filter-text-autocomplete',:value => @filter_text}) %> | ||
32 | + </p> | ||
33 | + <p> | ||
34 | + <%= submit_button(:search, _('Search')) %> | ||
35 | + </p> | ||
36 | <% end %> | 36 | <% end %> |
37 | - <p> | ||
38 | - <%= submit_button(:search, _('Search')) %> | ||
39 | - </p> | ||
40 | - <% end %> | ||
41 | <% end %> | 37 | <% end %> |
42 | - | ||
43 | <% if @tasks.empty? %> | 38 | <% if @tasks.empty? %> |
44 | <p> | 39 | <p> |
45 | <em><%= _('No pending tasks for %s') % profile.name %></em> | 40 | <em><%= _('No pending tasks for %s') % profile.name %></em> |
@@ -59,18 +54,18 @@ | @@ -59,18 +54,18 @@ | ||
59 | <p> | 54 | <p> |
60 | <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> | 55 | <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "up-set-all-tasks-to") %> |
61 | </p> | 56 | </p> |
62 | - <% end %> | 57 | + <% end %> |
63 | 58 | ||
64 | <div class="task_boxes"> | 59 | <div class="task_boxes"> |
65 | <%= render :partial => 'task', :collection => @tasks %> | 60 | <%= render :partial => 'task', :collection => @tasks %> |
66 | </div> | 61 | </div> |
67 | 62 | ||
68 | <% unless @view_only %> | 63 | <% unless @view_only %> |
69 | - <p> | ||
70 | - <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | ||
71 | - </p> | 64 | + <p> |
65 | + <%= labelled_select(_("Set all to: "), 'set-decisions', 'first', 'last', nil, [['',""],['accept',_("Accept")],['reject',_("Reject")],['skip',_("Skip")]], :id => "down-set-all-tasks-to") %> | ||
66 | + </p> | ||
72 | <% end %> | 67 | <% end %> |
73 | - </ul> | 68 | + </ul> |
74 | 69 | ||
75 | <%= pagination_links(@tasks)%> | 70 | <%= pagination_links(@tasks)%> |
76 | 71 |
public/javascripts/tasks.js
@@ -58,6 +58,22 @@ | @@ -58,6 +58,22 @@ | ||
58 | $('.task_title').css('margin-right', $('.task_decisions').width()+'px'); | 58 | $('.task_title').css('margin-right', $('.task_decisions').width()+'px'); |
59 | $('.task_title').css('margin-left', $('.task_arrow').width()+'px'); | 59 | $('.task_title').css('margin-left', $('.task_arrow').width()+'px'); |
60 | 60 | ||
61 | + //Autocomplete tasks by type | ||
62 | + $('#filter-text-autocomplete').autocomplete({ | ||
63 | + source:function(request,response){ | ||
64 | + $.ajax({ | ||
65 | + url:document.location.pathname+'/search_tasks', | ||
66 | + dataType:'json', | ||
67 | + data:{ | ||
68 | + filter_text:request.term, | ||
69 | + filter_type:jQuery('#filter-type').val() | ||
70 | + }, | ||
71 | + success:response | ||
72 | + }) | ||
73 | + }, | ||
74 | + minLength:2 | ||
75 | + }); | ||
76 | + | ||
61 | })(jQuery) | 77 | })(jQuery) |
62 | 78 | ||
63 | function change_task_responsible(el) { | 79 | function change_task_responsible(el) { |
test/functional/tasks_controller_test.rb
@@ -4,6 +4,7 @@ require 'tasks_controller' | @@ -4,6 +4,7 @@ require 'tasks_controller' | ||
4 | class TasksControllerTest < ActionController::TestCase | 4 | class TasksControllerTest < ActionController::TestCase |
5 | 5 | ||
6 | self.default_params = {profile: 'testuser'} | 6 | self.default_params = {profile: 'testuser'} |
7 | + | ||
7 | def setup | 8 | def setup |
8 | @controller = TasksController.new | 9 | @controller = TasksController.new |
9 | @request = ActionController::TestRequest.new | 10 | @request = ActionController::TestRequest.new |
@@ -27,6 +28,37 @@ class TasksControllerTest < ActionController::TestCase | @@ -27,6 +28,37 @@ class TasksControllerTest < ActionController::TestCase | ||
27 | assert assigns(:tasks) | 28 | assert assigns(:tasks) |
28 | end | 29 | end |
29 | 30 | ||
31 | + should 'get filtered tasks to autocomplete text field' do | ||
32 | + | ||
33 | + #Create a admin user and a simple user | ||
34 | + profile_admin = create_user('admin_tester').person | ||
35 | + Environment.default.add_admin(profile_admin) | ||
36 | + user = fast_create(Person,:name => 'FakeUser') | ||
37 | + | ||
38 | + #Create a task of type 'ModerateUserRegistration' | ||
39 | + task_data = { | ||
40 | + :target => Environment.default, | ||
41 | + :spam => false, | ||
42 | + :data => {:user_id => user.id,:name => user.name} | ||
43 | + } | ||
44 | + ModerateUserRegistration.create!(task_data) | ||
45 | + | ||
46 | + #Use admin user to your profile with a pending task above | ||
47 | + @controller.stubs(:profile).returns(profile_admin) | ||
48 | + login_as profile_admin.identifier | ||
49 | + | ||
50 | + #Perform a http request to 'search_task' action with params | ||
51 | + post :search_tasks, :filter_type =>'ModerateUserRegistration', :filter_text => 'Fak' | ||
52 | + | ||
53 | + assert_response :success | ||
54 | + | ||
55 | + #Check if json response matches with a 'FakeUser' | ||
56 | + json_response = ActiveSupport::JSON.decode(@response.body) | ||
57 | + value = json_response[0]['value'] | ||
58 | + | ||
59 | + assert_equal value, 'FakeUser' | ||
60 | + end | ||
61 | + | ||
30 | should 'list pending tasks without spam' do | 62 | should 'list pending tasks without spam' do |
31 | requestor = fast_create(Person) | 63 | requestor = fast_create(Person) |
32 | task_spam = Task.create!(:requestor => requestor, :target => profile, :spam => true) | 64 | task_spam = Task.create!(:requestor => requestor, :target => profile, :spam => true) |
@@ -437,13 +469,13 @@ class TasksControllerTest < ActionController::TestCase | @@ -437,13 +469,13 @@ class TasksControllerTest < ActionController::TestCase | ||
437 | t2 = CleanHouse.create!(:requestor => requestor, :target => profile) | 469 | t2 = CleanHouse.create!(:requestor => requestor, :target => profile) |
438 | t3 = FeedDog.create!(:requestor => requestor, :target => profile) | 470 | t3 = FeedDog.create!(:requestor => requestor, :target => profile) |
439 | 471 | ||
440 | - get :index, :filter_type => t1.type, :filter_text => 'test' | 472 | + post :index, :filter_type => t1.type, :filter_text => 'test' |
441 | 473 | ||
442 | assert_includes assigns(:tasks), t1 | 474 | assert_includes assigns(:tasks), t1 |
443 | assert_not_includes assigns(:tasks), t2 | 475 | assert_not_includes assigns(:tasks), t2 |
444 | assert_not_includes assigns(:tasks), t3 | 476 | assert_not_includes assigns(:tasks), t3 |
445 | 477 | ||
446 | - get :index | 478 | + post :index |
447 | 479 | ||
448 | assert_includes assigns(:tasks), t1 | 480 | assert_includes assigns(:tasks), t1 |
449 | assert_includes assigns(:tasks), t2 | 481 | assert_includes assigns(:tasks), t2 |