diff --git a/app/models/command/filter_cards.rb b/app/models/command/filter_cards.rb new file mode 100644 index 000000000..65d87c36f --- /dev/null +++ b/app/models/command/filter_cards.rb @@ -0,0 +1,11 @@ +class Command::FilterCards < Command + store_accessor :data, :card_ids, :params + + def title + "Filter cards #{card_ids.join(",")}" + end + + def execute + redirect_to cards_path(**params.without("card_ids").merge(card_ids: card_ids)) + end +end diff --git a/app/models/command/parser.rb b/app/models/command/parser.rb index c56032d91..097c92e56 100644 --- a/app/models/command/parser.rb +++ b/app/models/command/parser.rb @@ -11,14 +11,14 @@ class Command::Parser command_name, *command_arguments = string.strip.split(" ") case command_name - when "/assign", "/assignto" - Command::Assign.new(assignee_ids: assignees_from(command_arguments).collect(&:id), card_ids: cards.ids) - when "/close" - Command::Close.new(card_ids: cards.ids, reason: command_arguments.join(" ")) - when /^@/ - Command::GoToUser.new(user_id: assignee_from(command_name)&.id) - else - search(string) + when "/assign", "/assignto" + Command::Assign.new(assignee_ids: assignees_from(command_arguments).collect(&:id), card_ids: cards.ids) + when "/close" + Command::Close.new(card_ids: cards.ids, reason: command_arguments.join(" ")) + when /^@/ + Command::GoToUser.new(user_id: assignee_from(command_name)&.id) + else + search(string) end end @@ -37,10 +37,21 @@ class Command::Parser end def search(string) - if card = user.accessible_cards.find_by_id(string) + if cards = multiple_cards_from(string) + Command::FilterCards.new(card_ids: cards.ids, params: filter.as_params) + elsif card = user.accessible_cards.find_by_id(string) Command::GoToCard.new(card_id: card.id) else Command::Search.new(query: string, params: filter.as_params) end end + + def multiple_cards_from(string) + if tokens = string.split(/[\s,]+/).filter { it =~ /\A\d+\z/ }.presence + if tokens.many? + cards = user.accessible_cards.where(id: tokens) + cards.any? ? cards : nil + end + end + end end diff --git a/app/models/filter.rb b/app/models/filter.rb index e5ce39383..772e80c8b 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -19,6 +19,7 @@ class Filter < ApplicationRecord def cards @cards ||= begin result = creator.accessible_cards.indexed_by(indexed_by) + result = result.where(id: card_ids) if card_ids.present? && !indexed_by.closed? result = result.open unless indexed_by.closed? result = result.by_engagement_status(engagement_status) if engagement_status.present? result = result.unassigned if assignment_status.unassigned? diff --git a/app/models/filter/fields.rb b/app/models/filter/fields.rb index 9ff9764d4..8c0996649 100644 --- a/app/models/filter/fields.rb +++ b/app/models/filter/fields.rb @@ -16,7 +16,7 @@ module Filter::Fields end included do - store_accessor :fields, :assignment_status, :indexed_by, :terms, :engagement_status + store_accessor :fields, :assignment_status, :indexed_by, :terms, :engagement_status, :card_ids def assignment_status super.to_s.inquiry diff --git a/app/models/filter/params.rb b/app/models/filter/params.rb index c6f0df13e..a7bed80bb 100644 --- a/app/models/filter/params.rb +++ b/app/models/filter/params.rb @@ -5,6 +5,7 @@ module Filter::Params :assignment_status, :indexed_by, :engagement_status, + card_ids: [], assignee_ids: [], creator_ids: [], collection_ids: [], @@ -40,8 +41,9 @@ module Filter::Params params[:assignment_status] = assignment_status params[:terms] = terms params[:tag_ids] = tags.ids - params[:collection_ids] = collections.ids + params[:collection_ids] = collections.ids params[:stage_ids] = stages.ids + params[:card_ids] = card_ids params[:assignee_ids] = assignees.ids params[:creator_ids] = creators.ids end.compact_blank.reject(&method(:default_value?)) diff --git a/test/models/command/filter_cards_test.rb b/test/models/command/filter_cards_test.rb new file mode 100644 index 000000000..0280157fe --- /dev/null +++ b/test/models/command/filter_cards_test.rb @@ -0,0 +1,21 @@ +require "test_helper" + +class Command::FilterCardsTest < ActionDispatch::IntegrationTest + include CommandTestHelper + + setup do + @card_ids = cards(:logo, :layout).collect(&:id) + end + + test "redirects to the cards index filtering by cards" do + result = execute_command "#{@card_ids.join(" ")}" + + assert_equal cards_path(indexed_by: "newest", card_ids: @card_ids), result.url + end + + test "respects existing filters" do + result = execute_command "#{@card_ids.join(",")}", context_url: "http://37signals.fizzy.localhost:3006/cards?collection_ids%5B%5D=#{collections(:writebook).id}" + + assert_equal cards_path(indexed_by: "newest", collection_ids: [ collections(:writebook).id ], card_ids: @card_ids), result.url + end +end diff --git a/test/models/filter_test.rb b/test/models/filter_test.rb index 586fc6b0e..ecc690798 100644 --- a/test/models/filter_test.rb +++ b/test/models/filter_test.rb @@ -31,6 +31,9 @@ class FilterTest < ActiveSupport::TestCase filter = users(:david).filters.new indexed_by: "closed" assert_equal [ cards(:shipping) ], filter.cards + + filter = users(:david).filters.new card_ids: [ cards(:logo, :layout).collect(&:id) ] + assert_equal [ cards(:logo), cards(:layout) ], filter.cards end test "can't see cards in collections that aren't accessible" do