From 72ffcfac8b6c57d58e2892de97f6ef7e3daf4f7e Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Tue, 6 May 2025 06:42:26 +0200 Subject: [PATCH] Assignments working --- app/controllers/commands_controller.rb | 10 ++++- .../controllers/commands_controller.js | 1 - app/models/command/assign.rb | 36 +++++++++++++++++ app/models/command/go_to_card.rb | 4 -- app/models/command/parser.rb | 40 +++++++++++++++---- app/models/command/parser/context.rb | 28 +++++++++++++ app/views/cards/show.html.erb | 2 +- 7 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 app/models/command/assign.rb create mode 100644 app/models/command/parser/context.rb diff --git a/app/controllers/commands_controller.rb b/app/controllers/commands_controller.rb index 143ff514d..d26202aec 100644 --- a/app/controllers/commands_controller.rb +++ b/app/controllers/commands_controller.rb @@ -18,8 +18,16 @@ class CommandsController < ApplicationController private def parse_command(string) - Command::Parser.new(Current.user).parse(string).tap do |command| + Command::Parser.new(parsing_context).parse(string).tap do |command| Current.user.commands << command if command end end + + def parsing_context + Command::Parser::Context.new(Current.user, url: request.referrer) + end + + def card_ids_from_header + request.headers["X-Cards"].to_s.split(",").map(&:to_i) if request.headers["X-Card-Ids"] + end end diff --git a/app/javascript/controllers/commands_controller.js b/app/javascript/controllers/commands_controller.js index 98eaa7598..71560576b 100644 --- a/app/javascript/controllers/commands_controller.js +++ b/app/javascript/controllers/commands_controller.js @@ -4,5 +4,4 @@ export default class extends Controller { static targets = [ "input" ] // Actions - } diff --git a/app/models/command/assign.rb b/app/models/command/assign.rb new file mode 100644 index 000000000..f629c8dd6 --- /dev/null +++ b/app/models/command/assign.rb @@ -0,0 +1,36 @@ +class Command::Assign < Command + store_accessor :data, :card_ids, :assignee_ids + + def execute + Rails.logger.info "*** #{assignees.collect(&:name)}" + + transaction do + cards.each do |card| + assignees.each do |assignee| + card.toggle_assignment(assignee) unless card.assigned_to?(assignee) + end + end + end + end + + def undo + raise "pending" + end + + def description + raise "pending" + end + + def to_command + raise "pending" + end + + private + def assignees + User.where(id: assignee_ids) + end + + def cards + user.accessible_cards.where(id: card_ids) + end +end diff --git a/app/models/command/go_to_card.rb b/app/models/command/go_to_card.rb index b3e3122c5..3595c8422 100644 --- a/app/models/command/go_to_card.rb +++ b/app/models/command/go_to_card.rb @@ -1,10 +1,6 @@ class Command::GoToCard < Command store_accessor :data, :card_id - def card=(card) - self.card_id = card.id - end - def execute redirect_to card end diff --git a/app/models/command/parser.rb b/app/models/command/parser.rb index 1f173c0cb..309127180 100644 --- a/app/models/command/parser.rb +++ b/app/models/command/parser.rb @@ -1,15 +1,41 @@ class Command::Parser - attr_reader :user + attr_reader :context - def initialize(user) - @user = user + delegate :user, :cards, to: :context + + def initialize(context) + @context = context end def parse(string) - if card = user.accessible_cards.find_by_id(string) - Command::GoToCard.new(card: card) - else - Command::Search.new(query: string) + command_name, *command_arguments = string.split(" ") + + case command_name + when "/assign", "/assign_to" + Command::Assign.new(assignee_ids: assignees_from(command_arguments).collect(&:id), card_ids: cards.ids) + else + search(string) end end + + private + def search(string) + if card = user.accessible_cards.find_by_id(string) + Command::GoToCard.new(card_id: card.id) + else + Command::Search.new(query: string) + end + end + + def assignees_from(strings) + Array(strings).filter_map do |string| + assignee_from(string) + end + end + + # TODO: This is temporary as it can be ambiguous. We should inject the user ID in the command + # instead, as determined by the user picker. + def assignee_from(string) + User.all.find { |user| user.mentionable_handles.include?(string) } + end end diff --git a/app/models/command/parser/context.rb b/app/models/command/parser/context.rb new file mode 100644 index 000000000..12b92293c --- /dev/null +++ b/app/models/command/parser/context.rb @@ -0,0 +1,28 @@ +class Command::Parser::Context + attr_reader :user, :url + + def initialize(user, url:) + @user = user + @url = url + end + + def cards + route = Rails.application.routes.recognize_path(url) + + controller = route[:controller] + action = route[:action] + params = route.except(:controller, :action) + + cards_from(controller, action, params) + end + + private + def cards_from(controller, action, params) + if controller == "cards" && action == "show" + user.accessible_cards.where id: params[:id] + elsif controller == "cards" && action == "index" + filter = user.filters.from_params params.reverse_merge(**FilterScoped::DEFAULT_PARAMS) + filter.cards + end + end +end diff --git a/app/views/cards/show.html.erb b/app/views/cards/show.html.erb index 56ca920bb..c3886a3bb 100644 --- a/app/views/cards/show.html.erb +++ b/app/views/cards/show.html.erb @@ -29,7 +29,7 @@ <% end %> -
+
<%= render "cards/container", card: @card %> <% if @card.published? %>