diff --git a/app/controllers/activities_controller.rb b/app/controllers/activities_controller.rb index 51ae3de8f0..c24704f303 100644 --- a/app/controllers/activities_controller.rb +++ b/app/controllers/activities_controller.rb @@ -25,6 +25,8 @@ def activities .where(action: ACTIONS) .for_creators(params[:creator_ids]) .for_boards(params[:board_ids]) + .since_date(params[:since]) + .until_date(params[:until]) .reverse_chronologically end end diff --git a/app/models/event.rb b/app/models/event.rb index 23495326d2..9fb8352c3b 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -12,6 +12,8 @@ class Event < ApplicationRecord scope :reverse_chronologically, -> { order created_at: :desc, id: :desc } scope :for_creators, ->(ids) { where(creator_id: ids) if ids.present? } scope :for_boards, ->(ids) { where(board_id: ids) if ids.present? } + scope :since_date, ->(date) { where("events.created_at >= ?", Date.iso8601(date).beginning_of_day) if date.present? rescue nil } + scope :until_date, ->(date) { where("events.created_at <= ?", Date.iso8601(date).end_of_day) if date.present? rescue nil } scope :preloaded, -> { includes(:creator, :board, { eventable: [ diff --git a/docs/api/sections/activities.md b/docs/api/sections/activities.md index 33bf1bf70b..3edd0b999c 100644 --- a/docs/api/sections/activities.md +++ b/docs/api/sections/activities.md @@ -12,6 +12,8 @@ __Query Parameters:__ |-----------|-------------| | `creator_ids[]` | Filter to activities created by specific user ID(s). Multiple values are ORed. | | `board_ids[]` | Filter to activities on specific board ID(s). Multiple values are ORed. | +| `since` | Return activities created on or after this date (ISO 8601: `YYYY-MM-DD`). | +| `until` | Return activities created on or before this date (ISO 8601: `YYYY-MM-DD`). | Different filter params are ANDed together: `creator_ids[]=A&board_ids[]=X` means activities created by A on board X. diff --git a/test/controllers/activities_controller_test.rb b/test/controllers/activities_controller_test.rb index 82357e3d9f..72c8116dbb 100644 --- a/test/controllers/activities_controller_test.rb +++ b/test/controllers/activities_controller_test.rb @@ -264,6 +264,87 @@ class ActivitiesControllerTest < ActionDispatch::IntegrationTest assert_equal total, all_ids.uniq.count end + test "index filters by since date" do + card = cards(:logo) + board = card.board + + old_event = board.events.create!( + action: "card_published", creator: users(:kevin), + eventable: card, account: accounts("37s"), + created_at: 2.days.ago + ) + matching_event = board.events.create!( + action: "card_published", creator: users(:kevin), + eventable: card, account: accounts("37s"), + created_at: 12.hours.ago + ) + + get activities_path(since: Date.current.iso8601), as: :json + assert_response :success + + ids = @response.parsed_body.map { |e| e["id"] } + assert_includes ids, matching_event.id + assert_not_includes ids, old_event.id + end + + test "index filters by until date" do + card = cards(:logo) + board = card.board + + matching_event = board.events.create!( + action: "card_published", creator: users(:kevin), + eventable: card, account: accounts("37s"), + created_at: 12.hours.ago + ) + future_event = board.events.create!( + action: "card_published", creator: users(:kevin), + eventable: card, account: accounts("37s"), + created_at: 2.days.from_now + ) + + get activities_path(until: Date.current.iso8601), as: :json + assert_response :success + + ids = @response.parsed_body.map { |e| e["id"] } + assert_includes ids, matching_event.id + assert_not_includes ids, future_event.id + end + + test "index filters by since and until together" do + card = cards(:logo) + board = card.board + + old_event = board.events.create!( + action: "card_published", + creator: users(:kevin), + eventable: card, + account: accounts("37s"), + created_at: 5.days.ago + ) + matching_event = board.events.create!( + action: "card_published", + creator: users(:kevin), + eventable: card, + account: accounts("37s"), + created_at: 2.days.ago + ) + future_event = board.events.create!( + action: "card_published", + creator: users(:kevin), + eventable: card, + account: accounts("37s"), + created_at: 2.days.from_now + ) + + get activities_path(since: 3.days.ago.to_date.iso8601, until: Date.today.iso8601), as: :json + assert_response :success + + ids = @response.parsed_body.map { |e| e["id"] } + assert_includes ids, matching_event.id + assert_not_includes ids, old_event.id + assert_not_includes ids, future_event.id + end + private def next_page_from_link_header(link_header) url = link_header&.match(/<([^>]+)>;\s*rel="next"/)&.captures&.first