diff --git a/CHANGELOG b/CHANGELOG index 30710fc..592db6e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +v 6.4.0 + - Added sorting to project issues page + v 6.3.0 - API for adding gitlab-ci service - Init script now waits for pids to appear after (re)starting before reporting status (Rovanion Luckey) diff --git a/app/contexts/issues/list_context.rb b/app/contexts/issues/list_context.rb index da2eed0..fd27356 100644 --- a/app/contexts/issues/list_context.rb +++ b/app/contexts/issues/list_context.rb @@ -29,8 +29,26 @@ module Issues if params[:milestone_id].present? @issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id])) end + + # Sort by :sort param + @issues = sort(@issues, params[:sort]) @issues end + + private + + def sort(issues, condition) + case condition + when 'newest' then issues.except(:order).order('created_at DESC') + when 'oldest' then issues.except(:order).order('created_at ASC') + when 'recently_updated' then issues.except(:order).order('updated_at DESC') + when 'last_updated' then issues.except(:order).order('updated_at ASC') + when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC") + when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC") + else issues + end + end + end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index e8f845b..e03d54c 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -23,6 +23,9 @@ class Projects::IssuesController < Projects::ApplicationController assignee_id, milestone_id = params[:assignee_id], params[:milestone_id] @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero? @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero? + sort_param = params[:sort] || 'newest' + @sort = sort_param.humanize unless sort_param.empty? + respond_to do |format| format.html # index.html.erb diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index ee0e681..6b6903c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -70,6 +70,8 @@ module ProjectsHelper scope: params[:scope], label_name: params[:label_name], milestone_id: params[:milestone_id], + assignee_id: params[:assignee_id], + sort: params[:sort], } options = exist_opts.merge(options) diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml index 427d653..0022f82 100644 --- a/app/views/projects/issues/_issues.html.haml +++ b/app/views/projects/issues/_issues.html.haml @@ -78,6 +78,26 @@ %strong= milestone.title %small.light= milestone.expires_at + .dropdown.inline.prepend-left-10 + %a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"} + %span.light sort: + = @sort + %b.caret + %ul.dropdown-menu + %li + = link_to project_filter_path(sort: 'newest') do + Newest + = link_to project_filter_path(sort: 'oldest') do + Oldest + = link_to project_filter_path(sort: 'recently_updated') do + Recently updated + = link_to project_filter_path(sort: 'last_updated') do + Last updated + = link_to project_filter_path(sort: 'milestone_due_soon') do + Milestone due soon + = link_to project_filter_path(sort: 'milestone_due_later') do + Milestone due later + %ul.well-list.issues-list = render @issues diff --git a/spec/contexts/issues/list_context_spec.rb b/spec/contexts/issues/list_context_spec.rb new file mode 100644 index 0000000..63f2f38 --- /dev/null +++ b/spec/contexts/issues/list_context_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +describe Issues::ListContext do + + let(:user) { create(:user) } + let(:project) { create(:project, creator: user) } + + titles = ['foo','bar','baz'] + titles.each_with_index do |title, index| + let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) } + end + + describe 'sorting' do + + it 'sorts by newest' do + params = {:sort => 'newest'} + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq foo + end + + it 'sorts by oldest' do + params = {:sort => 'oldest'} + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq baz + end + + it 'sorts by recently updated' do + params = {:sort => 'recently_updated'} + baz.updated_at = Time.now + 10 + baz.save + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq baz + end + + it 'sorts by least recently updated' do + params = {:sort => 'last_updated'} + bar.updated_at = Time.now - 10 + bar.save + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq bar + end + + describe 'sorting by milestone' do + + let(:newer_due_milestone) { create(:milestone, :due_date => '2013-12-11') } + let(:later_due_milestone) { create(:milestone, :due_date => '2013-12-12') } + + before :each do + foo.milestone = newer_due_milestone + foo.save + bar.milestone = later_due_milestone + bar.save + end + + it 'sorts by most recently due milestone' do + params = {:sort => 'milestone_due_soon'} + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq foo + + end + + it 'sorts by least recently due milestone' do + params = {:sort => 'milestone_due_later'} + + issues = Issues::ListContext.new(project, user, params).execute + issues.first.should eq bar + end + + end + end + +end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 8cb9849..5b1a14a 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -95,4 +95,87 @@ describe "Issues" do page.should have_content 'gitlab' end end + + describe 'filter issue' do + titles = ['foo','bar','baz'] + titles.each_with_index do |title, index| + let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) } + end + let(:newer_due_milestone) { create(:milestone, :due_date => '2013-12-11') } + let(:later_due_milestone) { create(:milestone, :due_date => '2013-12-12') } + + it 'sorts by newest' do + visit project_issues_path(project, sort: 'newest') + + page.should have_selector("ul.issues-list li:first-child", :text => 'foo') + page.should have_selector("ul.issues-list li:last-child", :text => 'baz') + end + + it 'sorts by oldest' do + visit project_issues_path(project, sort: 'oldest') + + page.should have_selector("ul.issues-list li:first-child", :text => 'baz') + page.should have_selector("ul.issues-list li:last-child", :text => 'foo') + end + + it 'sorts by most recently updated' do + baz.updated_at = Time.now + 100 + baz.save + visit project_issues_path(project, sort: 'recently_updated') + + page.should have_selector("ul.issues-list li:first-child", :text => 'baz') + end + + it 'sorts by least recently updated' do + baz.updated_at = Time.now - 100 + baz.save + visit project_issues_path(project, sort: 'last_updated') + + page.should have_selector("ul.issues-list li:first-child", :text => 'baz') + end + + describe 'sorting by milestone' do + + before :each do + foo.milestone = newer_due_milestone + foo.save + bar.milestone = later_due_milestone + bar.save + end + + it 'sorts by recently due milestone' do + visit project_issues_path(project, sort: 'milestone_due_soon') + + page.should have_selector("ul.issues-list li:first-child", :text => 'foo') + end + + it 'sorts by least recently due milestone' do + visit project_issues_path(project, sort: 'milestone_due_later') + + page.should have_selector("ul.issues-list li:first-child", :text => 'bar') + end + end + + describe 'combine filter and sort' do + + let(:user2) { create(:user) } + + before :each do + foo.assignee = user2 + foo.save + bar.assignee = user2 + bar.save + end + + it 'sorts with a filter applied' do + visit project_issues_path(project, sort: 'oldest', assignee_id: user2.id) + + page.should have_selector("ul.issues-list li:first-child", :text => 'bar') + page.should have_selector("ul.issues-list li:last-child", :text => 'foo') + page.should_not have_content 'baz' + + end + end + end + end -- libgit2 0.21.2