Commit 2eddae57 authored by Patrick Bair's avatar Patrick Bair

Merge branch 'add-missing-issue-due-date-filters' into 'master'

Add missing issue due date filters

See merge request gitlab-org/gitlab!78460
parents 8ee173a5 393e4a5c
...@@ -108,8 +108,14 @@ class IssuesFinder < IssuableFinder ...@@ -108,8 +108,14 @@ class IssuesFinder < IssuableFinder
if params.filter_by_no_due_date? if params.filter_by_no_due_date?
items.without_due_date items.without_due_date
elsif params.filter_by_any_due_date?
items.with_due_date
elsif params.filter_by_overdue? elsif params.filter_by_overdue?
items.due_before(Date.today) items.due_before(Date.today)
elsif params.filter_by_due_today?
items.due_today
elsif params.filter_by_due_tomorrow?
items.due_tomorrow
elsif params.filter_by_due_this_week? elsif params.filter_by_due_this_week?
items.due_between(Date.today.beginning_of_week, Date.today.end_of_week) items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif params.filter_by_due_this_month? elsif params.filter_by_due_this_month?
......
...@@ -10,6 +10,10 @@ class IssuesFinder ...@@ -10,6 +10,10 @@ class IssuesFinder
user_can_see_all_issues? user_can_see_all_issues?
end end
def filter_by_any_due_date?
due_date? && params[:due_date] == Issue::AnyDueDate.name
end
def filter_by_no_due_date? def filter_by_no_due_date?
due_date? && params[:due_date] == Issue::NoDueDate.name due_date? && params[:due_date] == Issue::NoDueDate.name
end end
...@@ -18,6 +22,14 @@ class IssuesFinder ...@@ -18,6 +22,14 @@ class IssuesFinder
due_date? && params[:due_date] == Issue::Overdue.name due_date? && params[:due_date] == Issue::Overdue.name
end end
def filter_by_due_today?
due_date? && params[:due_date] == Issue::DueToday.name
end
def filter_by_due_tomorrow?
due_date? && params[:due_date] == Issue::DueTomorrow.name
end
def filter_by_due_this_week? def filter_by_due_this_week?
due_date? && params[:due_date] == Issue::DueThisWeek.name due_date? && params[:due_date] == Issue::DueThisWeek.name
end end
......
...@@ -29,8 +29,10 @@ class Issue < ApplicationRecord ...@@ -29,8 +29,10 @@ class Issue < ApplicationRecord
DueDateStruct = Struct.new(:title, :name).freeze DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze AnyDueDate = DueDateStruct.new('Any Due Date', 'any').freeze
Overdue = DueDateStruct.new('Overdue', 'overdue').freeze Overdue = DueDateStruct.new('Overdue', 'overdue').freeze
DueToday = DueDateStruct.new('Due Today', 'today').freeze
DueTomorrow = DueDateStruct.new('Due Tomorrow', 'tomorrow').freeze
DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze
DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
...@@ -107,7 +109,9 @@ class Issue < ApplicationRecord ...@@ -107,7 +109,9 @@ class Issue < ApplicationRecord
scope :without_due_date, -> { where(due_date: nil) } scope :without_due_date, -> { where(due_date: nil) }
scope :due_before, ->(date) { where('issues.due_date < ?', date) } scope :due_before, ->(date) { where('issues.due_date < ?', date) }
scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) } scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) }
scope :due_today, -> { where(due_date: Date.current) }
scope :due_tomorrow, -> { where(due_date: Date.tomorrow) } scope :due_tomorrow, -> { where(due_date: Date.tomorrow) }
scope :not_authored_by, ->(user) { where.not(author_id: user) } scope :not_authored_by, ->(user) { where.not(author_id: user) }
scope :order_due_date_asc, -> { reorder(::Gitlab::Database.nulls_last_order('due_date', 'ASC')) } scope :order_due_date_asc, -> { reorder(::Gitlab::Database.nulls_last_order('due_date', 'ASC')) }
......
...@@ -29,7 +29,9 @@ When requested across groups or projects, it's expected to be the same as the `f ...@@ -29,7 +29,9 @@ When requested across groups or projects, it's expected to be the same as the `f
## List issues ## List issues
> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9. > The `weight` property moved to GitLab Premium in 13.9.
> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get all issues the authenticated user has access to. By default it Get all issues the authenticated user has access to. By default it
returns only issues created by the current user. To get all issues, returns only issues created by the current user. To get all issues,
...@@ -61,7 +63,7 @@ GET /issues?state=opened ...@@ -61,7 +63,7 @@ GET /issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. | | `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ | | `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_ | `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `iids[]` | integer array | no | Return only the issues having the given `iid` | | `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` | | `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
...@@ -231,7 +233,9 @@ Please use `iid` of the `epic` attribute instead. ...@@ -231,7 +233,9 @@ Please use `iid` of the `epic` attribute instead.
## List group issues ## List group issues
> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9. > The `weight` property moved to GitLab Premium in 13.9.
> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a group's issues. Get a list of a group's issues.
...@@ -264,7 +268,7 @@ GET /groups/:id/issues?state=opened ...@@ -264,7 +268,7 @@ GET /groups/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. | | `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ | | `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_ | `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` | | `iids[]` | integer array | no | Return only the issues having the given `iid` |
...@@ -431,7 +435,9 @@ Please use `iid` of the `epic` attribute instead. ...@@ -431,7 +435,9 @@ Please use `iid` of the `epic` attribute instead.
## List project issues ## List project issues
> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9. > The `weight` property moved to GitLab Premium in 13.9.
> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a project's issues. Get a list of a project's issues.
...@@ -464,7 +470,7 @@ GET /projects/:id/issues?state=opened ...@@ -464,7 +470,7 @@ GET /projects/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. | | `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ | | `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_ | `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` | | `iids[]` | integer array | no | Return only the issues having the given `iid` |
......
...@@ -80,7 +80,7 @@ module API ...@@ -80,7 +80,7 @@ module API
desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.' desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc', optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return issues sorted in `asc` or `desc` order.' desc: 'Return issues sorted in `asc` or `desc` order.'
optional :due_date, type: String, values: %w[0 overdue week month next_month_and_previous_two_weeks] << '', optional :due_date, type: String, values: %w[0 any today tomorrow overdue week month next_month_and_previous_two_weeks] << '',
desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`' desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}" optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}"
......
...@@ -141,7 +141,7 @@ RSpec.describe "User sorts issues" do ...@@ -141,7 +141,7 @@ RSpec.describe "User sorts issues" do
page.within '.issues-list' do page.within '.issues-list' do
expect(page).to have_content('foo') expect(page).to have_content('foo')
expect(page).to have_content('bar') expect(page).to have_content('bar')
expect(page).to have_content('baz') expect(page).not_to have_content('baz')
end end
end end
......
...@@ -1018,6 +1018,8 @@ RSpec.describe IssuesFinder do ...@@ -1018,6 +1018,8 @@ RSpec.describe IssuesFinder do
end end
context 'filtering by due date' do context 'filtering by due date' do
let_it_be(:issue_due_today) { create(:issue, project: project1, due_date: Date.current) }
let_it_be(:issue_due_tomorrow) { create(:issue, project: project1, due_date: 1.day.from_now) }
let_it_be(:issue_overdue) { create(:issue, project: project1, due_date: 2.days.ago) } let_it_be(:issue_overdue) { create(:issue, project: project1, due_date: 2.days.ago) }
let_it_be(:issue_due_soon) { create(:issue, project: project1, due_date: 2.days.from_now) } let_it_be(:issue_due_soon) { create(:issue, project: project1, due_date: 2.days.from_now) }
...@@ -1032,6 +1034,30 @@ RSpec.describe IssuesFinder do ...@@ -1032,6 +1034,30 @@ RSpec.describe IssuesFinder do
end end
end end
context 'with param set to any due date' do
let(:params) { base_params.merge(due_date: Issue::AnyDueDate.name) }
it 'returns issues with any due date' do
expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
end
end
context 'with param set to due today' do
let(:params) { base_params.merge(due_date: Issue::DueToday.name) }
it 'returns issues due today' do
expect(issues).to contain_exactly(issue_due_today)
end
end
context 'with param set to due tomorrow' do
let(:params) { base_params.merge(due_date: Issue::DueTomorrow.name) }
it 'returns issues due today' do
expect(issues).to contain_exactly(issue_due_tomorrow)
end
end
context 'with param set to overdue' do context 'with param set to overdue' do
let(:params) { base_params.merge(due_date: Issue::Overdue.name) } let(:params) { base_params.merge(due_date: Issue::Overdue.name) }
...@@ -1043,8 +1069,8 @@ RSpec.describe IssuesFinder do ...@@ -1043,8 +1069,8 @@ RSpec.describe IssuesFinder do
context 'with param set to next month and previous two weeks' do context 'with param set to next month and previous two weeks' do
let(:params) { base_params.merge(due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) } let(:params) { base_params.merge(due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) }
it 'returns issues from the previous two weeks and next month' do it 'returns issues due in the previous two weeks and next month' do
expect(issues).to contain_exactly(issue_overdue, issue_due_soon) expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
end end
end end
......
...@@ -488,6 +488,8 @@ RSpec.describe API::Issues do ...@@ -488,6 +488,8 @@ RSpec.describe API::Issues do
let_it_be(:issue3) { create(:issue, project: project, author: user, due_date: frozen_time + 10.days) } let_it_be(:issue3) { create(:issue, project: project, author: user, due_date: frozen_time + 10.days) }
let_it_be(:issue4) { create(:issue, project: project, author: user, due_date: frozen_time + 34.days) } let_it_be(:issue4) { create(:issue, project: project, author: user, due_date: frozen_time + 34.days) }
let_it_be(:issue5) { create(:issue, project: project, author: user, due_date: frozen_time - 8.days) } let_it_be(:issue5) { create(:issue, project: project, author: user, due_date: frozen_time - 8.days) }
let_it_be(:issue6) { create(:issue, project: project, author: user, due_date: frozen_time) }
let_it_be(:issue7) { create(:issue, project: project, author: user, due_date: frozen_time + 1.day) }
before do before do
travel_to(frozen_time) travel_to(frozen_time)
...@@ -500,7 +502,13 @@ RSpec.describe API::Issues do ...@@ -500,7 +502,13 @@ RSpec.describe API::Issues do
it 'returns them all when argument is empty' do it 'returns them all when argument is empty' do
get api('/issues?due_date=', user) get api('/issues?due_date=', user)
expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id) expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id)
end
it 'returns issues with due date' do
get api('/issues?due_date=any', user)
expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
end end
it 'returns issues without due date' do it 'returns issues without due date' do
...@@ -512,19 +520,31 @@ RSpec.describe API::Issues do ...@@ -512,19 +520,31 @@ RSpec.describe API::Issues do
it 'returns issues due for this week' do it 'returns issues due for this week' do
get api('/issues?due_date=week', user) get api('/issues?due_date=week', user)
expect_paginated_array_response(issue2.id) expect_paginated_array_response(issue7.id, issue6.id, issue2.id)
end end
it 'returns issues due for this month' do it 'returns issues due for this month' do
get api('/issues?due_date=month', user) get api('/issues?due_date=month', user)
expect_paginated_array_response(issue3.id, issue2.id) expect_paginated_array_response(issue7.id, issue6.id, issue3.id, issue2.id)
end end
it 'returns issues that are due previous two weeks and next month' do it 'returns issues that are due previous two weeks and next month' do
get api('/issues?due_date=next_month_and_previous_two_weeks', user) get api('/issues?due_date=next_month_and_previous_two_weeks', user)
expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id) expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
end
it 'returns issues that are due today' do
get api('/issues?due_date=today', user)
expect_paginated_array_response(issue6.id)
end
it 'returns issues that are due tomorrow' do
get api('/issues?due_date=tomorrow', user)
expect_paginated_array_response(issue7.id)
end end
it 'returns issues that are overdue' do it 'returns issues that are overdue' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment