Skip to content

Commit

Permalink
Add basic text search of conversations (#576)
Browse files Browse the repository at this point in the history
Co-authored-by: Keith Schacht <krschacht@gmail.com>
  • Loading branch information
mattlindsey and krschacht authored Dec 10, 2024
1 parent de9eafc commit da4b146
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 30 deletions.
10 changes: 5 additions & 5 deletions app/controllers/conversations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
class ConversationsController < ApplicationController
before_action :set_conversation, only: [:show, :edit, :update, :destroy]
before_action :set_nav_conversations
before_action :set_nav_assistants

def index
@query = params[:query]
@nav_conversations = Conversation.grouped_by_increasing_time_interval_for_user(Current.user, @query)
end

def show
end

Expand All @@ -28,10 +32,6 @@ def destroy

private

def set_nav_conversations
@nav_conversations = Conversation.grouped_by_increasing_time_interval_for_user(Current.user)
end

def set_nav_assistants
@nav_assistants = Current.user.assistants.ordered
end
Expand Down
6 changes: 0 additions & 6 deletions app/controllers/messages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class MessagesController < ApplicationController
before_action :set_conversation, only: [:index]
before_action :set_assistant, only: [:index, :new, :edit, :create]
before_action :set_message, only: [:show, :edit, :update]
before_action :set_nav_conversations, only: [:index, :new]
before_action :set_nav_assistants, only: [:index, :new]
before_action :set_conversation_starters, only: [:new]

Expand Down Expand Up @@ -46,7 +45,6 @@ def create
redirect_to conversation_messages_path(@message.conversation, version: @message.version), status: :see_other
else
# what's the right flow for a failed message create? it's not this, but hacking it so tests pass until we have a plan
set_nav_conversations
set_nav_assistants
@new_message = @assistant.messages.new

Expand Down Expand Up @@ -82,10 +80,6 @@ def set_message
redirect_to root_url, status: :unauthorized if @message.conversation.user != Current.user
end

def set_nav_conversations
@nav_conversations = Conversation.grouped_by_increasing_time_interval_for_user(Current.user)
end

def set_nav_assistants
@nav_assistants = Current.user.assistants.ordered
end
Expand Down
37 changes: 37 additions & 0 deletions app/javascript/stimulus/search_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = [ "input", "clear" ]

inputTargetConnected() {
this.setSearchClearIcon()
}

disconnect() {
clearTimeout(this.timeout)
}

clear() {
this.inputTarget.value = ""
this.element.requestSubmit()
}

unfocus() {
this.inputTarget.autofocus = false
}

search() {
clearTimeout(this.timeout)
this.setSearchClearIcon()
this.timeout = setTimeout(() => {
this.element.requestSubmit()
}, 500)
}

setSearchClearIcon() {
if (this.inputTarget.value.length > 0)
this.clearTarget.classList.remove("hidden")
else
this.clearTarget.classList.add("hidden")
}
}
10 changes: 8 additions & 2 deletions app/models/conversation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ class Conversation < ApplicationRecord
# "Last Month" => relation,
# "Older" => relation
# }
def self.grouped_by_increasing_time_interval_for_user(user)
nav_conversations = user.conversations.ordered
def self.grouped_by_increasing_time_interval_for_user(user, query = nil)
if query.blank?
nav_conversations = user.conversations.ordered
else
nav_conversations = user.conversations.joins(:messages).ordered.where("messages.content_text ILIKE ?", "%#{query}%").
or(user.conversations.ordered.where("title ILIKE ?", "%#{query}%")).
select("DISTINCT conversations.*")
end

keys = ["Today", "Yesterday", "This Week", "This Month", "Last Month", "Older"]
values = [
Expand Down
57 changes: 57 additions & 0 deletions app/views/conversations/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<turbo-frame data-turbo-permanent id="nav-conversations">
<section id="search"
class="pt-6 text-gray-950 dark:text-gray-100 select-none"
>
<%= form_with(url: conversations_path,
data: { turbo_frame: "nav_conversations", controller: "search" },
class: "contents",
method: :get
) do |form| %>
<div class="relative ml-2 mr-5">
<%= form.text_field :query,
value: @query,
placeholder: "Search",
id: "search-input",
autofocus: @query.nil? ? false : true,
class: %|
w-full
p-2 py-1
border border-gray-200 rounded-lg
text-black dark:text-gray-800
|,
data: {
search_target: "input",
turbo_permanent: true,
action: %|
blur->search#unfocus
input->search#search
%|
}
%>
<%= icon "x-circle",
variant: :mini,
size: 18,
class: "cursor-pointer text-gray-800 absolute right-1 top-1/2 transform -translate-y-1/2",
data: { search_target: "clear", action: "click->search#clear" }
%>
</div>
<% end %>
</section>

<section class="text-gray-950 dark:text-gray-100 select-none">
<turbo-frame id="conversations"
target="conversation"
data-controller="radio-behavior"
data-radio-behavior-selected-class="relationship"
class="block mb-24" <%# ensures the last conversation's menu has room to open %>
>
<% @nav_conversations.each do |named_time_span, conversations| %>
<header class="mx-2 mt-6 mb-2 text-xs font-semibold text-gray-300 text-opacity-1 dark:text-gray-500">
<%= named_time_span %>
</header>

<%= render conversations %>
<% end %>
</turbo-frame>
</section>
</turbo-frame>
21 changes: 5 additions & 16 deletions app/views/messages/_nav_column.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,8 @@
<% end %>
</section>

<section class="text-gray-950 dark:text-gray-100 select-none">
<turbo-frame id="conversations"
target="conversation"
data-controller="radio-behavior"
data-radio-behavior-selected-class="relationship"
class="block mb-24" <%# ensures the last conversation's menu has room to open %>
>
<% @nav_conversations.each do |named_time_span, conversations| %>
<header class="mx-2 mt-10 mb-2 text-xs font-semibold text-gray-300 text-opacity-1 dark:text-gray-500">
<%= named_time_span %>
</header>

<%= render conversations %>
<% end %>
</turbo-frame>
</section>
<turbo-frame id="nav-conversations"
src="<%= conversations_path %>"
loading="lazy"
data-turbo-permanent
/>
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
resources :messages, only: [:new, :create, :edit]
end

resources :conversations, only: [:show, :edit, :update, :destroy] do
resources :conversations, only: [:index, :show, :edit, :update, :destroy] do
resources :messages, only: [:index]
end

Expand Down
34 changes: 34 additions & 0 deletions test/models/conversation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,38 @@ class ConversationTest < ActiveSupport::TestCase
assert_equal 3, grouped_conversations["Older"].count
end
end

test "#grouped_by_increasing_time_interval_for_user with a query returning a single conversation title" do
user = users(:keith)
query = "Ruby"

grouped_conversations = Conversation.grouped_by_increasing_time_interval_for_user(user, query).values.flatten

assert_equal 1, grouped_conversations.count
assert_equal conversations(:ruby_version), grouped_conversations.first, "Should have returned this conversation based on title"
end

test "#grouped_by_increasing_time_interval_for_user with a query returning a single conversation message" do
user = users(:keith)
query = "alive"

grouped_conversations = Conversation.grouped_by_increasing_time_interval_for_user(user, query).values.flatten

assert_equal 1, grouped_conversations.count
assert_equal conversations(:greeting), grouped_conversations.first, "Should have returned this conversation based on message content"
end

test "#grouped_by_increasing_time_interval_for_user with a query returning matching conversation titles and a message" do
user = users(:keith)
query = "test"

grouped_conversations = Conversation.grouped_by_increasing_time_interval_for_user(user, query).values.flatten

assert_equal 3, grouped_conversations.count
assert_equal [
conversations(:attachment).id, # matches title
conversations(:attachments).id, # matches title
conversations(:ruby_version).id # matches "latest" in messages
].sort, grouped_conversations.map(&:id).sort, "Should have returned these conversations based on title and message content"
end
end

0 comments on commit da4b146

Please sign in to comment.