diff --git a/app/controllers/commands_controller.rb b/app/controllers/commands_controller.rb deleted file mode 100644 index 43af3c762..000000000 --- a/app/controllers/commands_controller.rb +++ /dev/null @@ -1,34 +0,0 @@ -class CommandsController < ApplicationController - def create - command = parse_command(params[:command]) - result = command.execute - respond_with_execution_result(result) - end - - private - def parse_command(string) - command_parser.parse(string) - end - - def command_parser - @command_parser ||= Command::Parser.new(user: Current.user, script_name: request.script_name) - end - - def respond_with_execution_result(result) - # This saves unnecessary back and forth between server and client (e.g: to redirect)- - result = result.is_a?(Array) && result.one? ? result.first : result - - case result - when Command::Result::Redirection - redirect_to result.url - when Command::Result::ShowModal - respond_with_turbo_frame_modal(result.turbo_frame, result.url) - else - redirect_back_or_to root_path - end - end - - def respond_with_turbo_frame_modal(turbo_frame, url) - render json: { turbo_frame: turbo_frame, url: url }, status: :accepted - end -end diff --git a/app/javascript/controllers/terminal_controller.js b/app/javascript/controllers/terminal_controller.js deleted file mode 100644 index 2d37ee9e3..000000000 --- a/app/javascript/controllers/terminal_controller.js +++ /dev/null @@ -1,91 +0,0 @@ -import { Controller } from "@hotwired/stimulus" -import { HttpStatus } from "helpers/http_helpers" -import { isMultiLineString } from "helpers/text_helpers"; -import { marked } from "marked" -import { nextFrame } from "helpers/timing_helpers"; - -export default class extends Controller { - static targets = [ "input", "form", "modalTurboFrame" ] - static classes = [ "error", "busy" ] - static outlets = [ "dialog" ] - - // Actions - - async focus() { - await nextFrame() - - this.inputTarget.focus() - this.inputTarget.selection.placeCursorAtTheEnd() - } - - executeCommand(event) { - if (!this.inputTarget.value.trim()) { - event.preventDefault() - } - } - - submitCommand({ target }) { - this.#submitCommand() - } - - handleCommandResponse(event) { - const response = event.detail.fetchResponse?.response - - if (event.detail.success) { - this.#handleSuccessResponse(response) - } else if (response) { - this.#handleErrorResponse(response) - } - } - - hideError() { - this.element.classList.remove(this.errorClass) - } - - commandSubmitted() { - this.element.classList.add(this.busyClass) - } - - #reset(inputValue = "") { - this.inputTarget.value = inputValue - - this.element.classList.remove(this.errorClass) - this.element.classList.remove(this.busyClass) - } - - #handleSuccessResponse(response) { - if (response.headers.get("Content-Type")?.includes("application/json")) { - response.json().then((responseJson) => { - this.#handleJsonResponse(responseJson) - }) - } - this.#reset() - } - - async #handleErrorResponse(response) { - this.element.classList.add(this.errorClass) - } - - #handleJsonResponse(responseJson) { - const { redirect_to, turbo_frame, url } = responseJson - - if (redirect_to) { - Turbo.visit(redirect_to) - } - - if (turbo_frame && url) { - this.#showTurboFrameModal(turbo_frame, url) - } - } - - #submitCommand() { - this.formTarget.requestSubmit() - } - - #showTurboFrameModal(name, url) { - this.inputTarget.blur() - this.modalTurboFrameTarget.id = name - this.modalTurboFrameTarget.src = url - this.dialogOutlet.open() - } -} diff --git a/app/models/command.rb b/app/models/command.rb deleted file mode 100644 index 740aa3a47..000000000 --- a/app/models/command.rb +++ /dev/null @@ -1,12 +0,0 @@ -class Command - include Rails.application.routes.url_helpers - - def execute - raise NotImplementedError - end - - private - def redirect_to(...) - Command::Result::Redirection.new(...) - end -end diff --git a/app/models/command/ask.rb b/app/models/command/ask.rb deleted file mode 100644 index 243ba0237..000000000 --- a/app/models/command/ask.rb +++ /dev/null @@ -1,14 +0,0 @@ -class Command::Ask < Command - attr_reader :question - - def initialize(question) - @question = question - end - - def execute - conversation = Conversation.create_or_find_by(user: Current.user) - conversation.ask(question) if question.present? - - Command::Result::ShowModal.new(turbo_frame: "conversation", url: conversation_path) - end -end diff --git a/app/models/command/go_to_card.rb b/app/models/command/go_to_card.rb deleted file mode 100644 index bee418648..000000000 --- a/app/models/command/go_to_card.rb +++ /dev/null @@ -1,11 +0,0 @@ -class Command::GoToCard < Command - attr_reader :card - - def initialize(card) - @card = card - end - - def execute - redirect_to card - end -end diff --git a/app/models/command/parser.rb b/app/models/command/parser.rb deleted file mode 100644 index b953fcd32..000000000 --- a/app/models/command/parser.rb +++ /dev/null @@ -1,51 +0,0 @@ -class Command::Parser - attr_reader :user, :script_name - - def initialize(user: user, script_name:) - @user = user - @script_name = script_name - end - - def parse(string) - parse_command(string).tap do |command| - command.default_url_options[:script_name] = script_name - end - end - - private - def parse_command(string) - parse_rich_text_command as_plain_text_with_attachable_references(string) - end - - def as_plain_text_with_attachable_references(string) - ActionText::Content.new(string).render_attachments(&:to_gid).fragment.to_plain_text - end - - def parse_rich_text_command(string) - command_name, *command_arguments = string.strip.split(" ") - combined_arguments = command_arguments.join(" ") - - case command_name - when "/ask" - Command::Ask.new(combined_arguments) - else - parse_free_string(string) - end - end - - def parse_free_string(string) - if card = single_card_from(string) - Command::GoToCard.new(card) - else - parse_with_fallback(string) - end - end - - def single_card_from(string) - user.accessible_cards.find_by_id(string) - end - - def parse_with_fallback(string) - Command::Search.new(string) - end -end diff --git a/app/models/command/result/redirection.rb b/app/models/command/result/redirection.rb deleted file mode 100644 index 3796558e5..000000000 --- a/app/models/command/result/redirection.rb +++ /dev/null @@ -1,11 +0,0 @@ -class Command::Result::Redirection - attr_reader :url - - def initialize(url) - @url = url - end - - def as_json - { redirect_to: url } - end -end diff --git a/app/models/command/result/show_modal.rb b/app/models/command/result/show_modal.rb deleted file mode 100644 index 19922ab5f..000000000 --- a/app/models/command/result/show_modal.rb +++ /dev/null @@ -1,12 +0,0 @@ -class Command::Result::ShowModal - attr_reader :url, :turbo_frame - - def initialize(url:, turbo_frame:) - @url = url - @turbo_frame = turbo_frame - end - - def as_json - { turbo_frame: turbo_frame, url: url } - end -end diff --git a/app/models/command/search.rb b/app/models/command/search.rb deleted file mode 100644 index 09befa32a..000000000 --- a/app/models/command/search.rb +++ /dev/null @@ -1,12 +0,0 @@ -class Command::Search < Command - attr_reader :terms - - def initialize(terms) - @terms = terms - end - - - def execute - redirect_to search_path(q: terms) - end -end diff --git a/app/views/commands/_form.html.erb b/app/views/commands/_form.html.erb deleted file mode 100644 index cc5bf65a7..000000000 --- a/app/views/commands/_form.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<%= form_tag commands_path, - id: "commands_form", - class: [ "flex align-center gap-half" ], - data: { - controller: "form", - terminal_target: "form", - action: " - keydown.enter->terminal#submitCommand - turbo:submit-start->terminal#commandSubmitted - turbo:submit-end->terminal#focus - keydown.meta+k@document->terminal#focus:prevent - keydown.ctrl+k@document->terminal#focus:prevent - turbo:submit-end->terminal#handleCommandResponse - " - } do %> - <%= rich_textarea_tag "command", nil, - toolbar: false, - class: "terminal__input input hide-focus-ring fill-transparent unpad", - "single-line": true, - id: "command", - attachments: false, - data: { - terminal_target: "input" - }, - placeholder: platform.desktop? ? "Press #{ hotkey_label(["ctrl", "K"]) } to search or type /commands…" : "Search or type /commands…", - spellcheck: "false" do %> - <%= global_mentions_prompt %> - <%= tags_prompt %> - <% end %> -<% end %> diff --git a/app/views/commands/_help.html.erb b/app/views/commands/_help.html.erb deleted file mode 100644 index 0f0135663..000000000 --- a/app/views/commands/_help.html.erb +++ /dev/null @@ -1,37 +0,0 @@ -
-

Fizzy do > Help

-
-

Search

-
Type keywords to search cards and comments
-
"CSS bug"
- -

Navigate

-
Type a card ID to go to it
-
"137"
-
Type a name to see someone’s profile
-
"@jason"
- -

Filter

-
Type card IDs to isolate them
-
"131, 137, 39"
-
Type a tag to see just tagged cards
-
"#design"
- -

Commands

-
Type / to issue commands
-
"/move to Doing"
- -
Type @ to match people
-
"/assign to @jason"
- -
Type # to match tags
-
"/tag this #design"
- -

Tips

-
Combine for powerful actions
-
"/move to Doing and /assign to @jason"
- -
Or use natural language
-
"Show cards added by Jason this month"
-
-
diff --git a/app/views/commands/_terminal.html.erb b/app/views/commands/_terminal.html.erb deleted file mode 100644 index 4c7ad5fe5..000000000 --- a/app/views/commands/_terminal.html.erb +++ /dev/null @@ -1,27 +0,0 @@ -<%= tag.div \ - id: "command-terminal", - class: "terminal full-width flex flex-column justify-end", - data: { - controller: "terminal", - terminal_dialog_outlet: "#terminal-modal", - terminal_error_class: "terminal--error", - terminal_confirmation_class: "terminal--confirmation", - terminal_help_class: "terminal--showing-help", - terminal_output_class: "terminal--showing-output", - terminal_busy_class: "terminal--busy", - toggle_class_toggle_class: "terminal--open" - } do %> - <%= tag.dialog \ - id: "terminal-modal", - class: "terminal__modal panel shadow", - data: { - controller: "dialog", - dialog_target: "dialog", - dialog_modal_value: "true", - action: "keydown.esc->dialog#close click@document->dialog#closeOnClickOutside" } do %> - <%= turbo_frame_tag "terminal-turbo-frame", refresh: :morph, data: { terminal_target: "modalTurboFrame" }, target: "_top" %> - <% end %> - - <%= render "commands/form" %> -<% end %> - diff --git a/test/controllers/commands_controller_test.rb b/test/controllers/commands_controller_test.rb deleted file mode 100644 index f5c691594..000000000 --- a/test/controllers/commands_controller_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "test_helper" - -class CommandsControllerTest < ActionDispatch::IntegrationTest - setup do - sign_in_as :kevin - end - - test "command that results in a redirect" do - post commands_path, params: { command: "#{cards(:logo).id}" } - - assert_redirected_to cards(:logo) - end - - test "command that triggers a redirect back" do - post commands_path, params: { command: "design" } - - assert_redirected_to search_path(q: "design") - end -end diff --git a/test/models/command/go_to_card_test.rb b/test/models/command/go_to_card_test.rb deleted file mode 100644 index d4609d5f1..000000000 --- a/test/models/command/go_to_card_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "test_helper" - -class Command::GoToCardTest < ActionDispatch::IntegrationTest - include CommandTestHelper - - setup do - @card = cards(:logo) - end - - test "redirect to the card perma" do - result = execute_command "#{@card.id}" - - assert_equal @card, result.url - end - - test "result in a regular search if the card does not exist" do - command = parse_command "123" - - result = command.execute - assert_equal search_path(q: "123"), result.url - end -end