Commit 13635dd88d20397838dae40b6c6adadc733cf55a
1 parent
36dfeecb
Exists in
web_steps_improvements
and in
6 other branches
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>
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 |