diff --git a/lib/music_library/chats.ex b/lib/music_library/chats.ex index 2cb3224c..c3eb68cd 100644 --- a/lib/music_library/chats.ex +++ b/lib/music_library/chats.ex @@ -25,6 +25,14 @@ defmodule MusicLibrary.Chats do |> Repo.all() end + @spec count_chats(atom(), String.t()) :: non_neg_integer() + def count_chats(entity, musicbrainz_id) do + from(c in Chat, + where: c.entity == ^entity and c.musicbrainz_id == ^musicbrainz_id + ) + |> Repo.aggregate(:count) + end + @spec has_any_chats?(atom(), String.t()) :: boolean() def has_any_chats?(entity, musicbrainz_id) do from(c in Chat, diff --git a/lib/music_library_web/components/chat.ex b/lib/music_library_web/components/chat.ex index d1e758fc..6dd1b3ee 100644 --- a/lib/music_library_web/components/chat.ex +++ b/lib/music_library_web/components/chat.ex @@ -336,6 +336,7 @@ defmodule MusicLibraryWeb.Components.Chat do def handle_event("delete_chat", %{"id" => id}, socket) do chat = Chats.get_chat!(id) {:ok, _} = Chats.delete_chat(chat) + send(self(), {__MODULE__, :chats_changed}) chats = Chats.list_chats(socket.assigns.entity, socket.assigns.musicbrainz_id) @@ -418,6 +419,7 @@ defmodule MusicLibraryWeb.Components.Chat do %{role: user_message.role, content: user_message.content} ) + send(self(), {__MODULE__, :chats_changed}) chat chat -> diff --git a/lib/music_library_web/live/artist_live/show.ex b/lib/music_library_web/live/artist_live/show.ex index 4c96c630..88c4e4ed 100644 --- a/lib/music_library_web/live/artist_live/show.ex +++ b/lib/music_library_web/live/artist_live/show.ex @@ -4,7 +4,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do import MusicLibraryWeb.RecordComponents, only: [record_grid: 1, country_label: 1, artist_image: 1] - alias MusicLibrary.{Artists, Records} + alias MusicLibrary.{Artists, Chats, Records} alias MusicLibrary.Artists.ArtistInfo alias MusicLibraryWeb.ErrorMessages @@ -120,6 +120,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do aria-hidden="true" data-slot="icon" /> + 0} class="text-xs font-medium">{@chat_count} <.button variant="soft" @@ -646,6 +647,16 @@ defmodule MusicLibraryWeb.ArtistLive.Show do |> put_toast(:info, gettext("Record deleted"))} end + @impl true + def handle_info({MusicLibraryWeb.Components.Chat, :chats_changed}, socket) do + {:noreply, + assign( + socket, + :chat_count, + Chats.count_chats(:artist, socket.assigns.artist.musicbrainz_id) + )} + end + defp apply_action(socket, :show, %{"musicbrainz_id" => musicbrainz_id}) do artist = Artists.get_artist!(musicbrainz_id) artist_info = Artists.get_artist_info!(musicbrainz_id) @@ -655,6 +666,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do |> assign(:current_section, :artists) |> assign(:artist, artist) |> assign(:artist_info, artist_info) + |> assign(:chat_count, Chats.count_chats(:artist, musicbrainz_id)) |> assign(:biography, build_biography(artist_info)) |> assign(:external_links, ArtistInfo.external_links(artist_info)) |> assign(:country, ArtistInfo.country(artist_info)) diff --git a/lib/music_library_web/live/collection_live/show.ex b/lib/music_library_web/live/collection_live/show.ex index 8742ba59..33bbffef 100644 --- a/lib/music_library_web/live/collection_live/show.ex +++ b/lib/music_library_web/live/collection_live/show.ex @@ -20,7 +20,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do release_summary: 1 ] - alias MusicLibrary.{ListeningStats, Records, RecordSets, ScrobbleActivity} + alias MusicLibrary.{Chats, ListeningStats, Records, RecordSets, ScrobbleActivity} alias MusicLibrary.Records.Similarity alias MusicLibraryWeb.ErrorMessages alias Phoenix.LiveView.JS @@ -70,6 +70,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do aria-hidden="true" data-slot="icon" /> + 0} class="text-xs font-medium">{@chat_count} <.button :if={@record.selected_release_id} @@ -354,6 +355,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do |> assign(:last_listened_track, last_listened_track) |> assign(:play_count, play_count) |> assign(:record_sets, record_sets) + |> assign(:chat_count, Chats.count_chats(:record, record.musicbrainz_id)) |> assign_embedding_text() |> assign_similar_records()} end @@ -511,6 +513,11 @@ defmodule MusicLibraryWeb.CollectionLive.Show do |> assign_embedding_text()} end + def handle_info({MusicLibraryWeb.Components.Chat, :chats_changed}, socket) do + {:noreply, + assign(socket, :chat_count, Chats.count_chats(:record, socket.assigns.record.musicbrainz_id))} + end + @impl true def handle_info({:update, record}, socket) do {:noreply, diff --git a/lib/music_library_web/live/wishlist_live/show.ex b/lib/music_library_web/live/wishlist_live/show.ex index 9bb0e13b..7f952ec2 100644 --- a/lib/music_library_web/live/wishlist_live/show.ex +++ b/lib/music_library_web/live/wishlist_live/show.ex @@ -16,6 +16,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do release_summary: 1 ] + alias MusicLibrary.Chats alias MusicLibrary.OnlineStoreTemplates alias MusicLibrary.{Records, RecordSets} alias MusicLibrary.Records.Similarity @@ -51,6 +52,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do aria-hidden="true" data-slot="icon" /> + 0} class="text-xs font-medium">{@chat_count} <.dropdown id={"actions-#{@record.id}"} placement="bottom-end"> <:toggle> @@ -304,6 +306,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do |> assign(:record, record) |> assign(:online_store_templates, online_store_templates) |> assign(:record_sets, record_sets) + |> assign(:chat_count, Chats.count_chats(:record, record.musicbrainz_id)) |> assign_embedding_text()} end @@ -418,6 +421,11 @@ defmodule MusicLibraryWeb.WishlistLive.Show do |> assign_embedding_text()} end + def handle_info({MusicLibraryWeb.Components.Chat, :chats_changed}, socket) do + {:noreply, + assign(socket, :chat_count, Chats.count_chats(:record, socket.assigns.record.musicbrainz_id))} + end + @impl true def handle_info({:update, record}, socket) do {:noreply, diff --git a/test/music_library/chats_test.exs b/test/music_library/chats_test.exs index f9159f00..01117f96 100644 --- a/test/music_library/chats_test.exs +++ b/test/music_library/chats_test.exs @@ -16,6 +16,35 @@ defmodule MusicLibrary.ChatsTest do %{chat: chat} end + describe "count_chats/2" do + test "returns 0 when no chats exist" do + assert Chats.count_chats(:record, Ecto.UUID.generate()) == 0 + end + + test "returns the number of chats for an entity" do + Chats.create_chat_with_message( + %{entity: :record, musicbrainz_id: @musicbrainz_id}, + %{role: "user", content: "First chat"} + ) + + Chats.create_chat_with_message( + %{entity: :record, musicbrainz_id: @musicbrainz_id}, + %{role: "user", content: "Second chat"} + ) + + assert Chats.count_chats(:record, @musicbrainz_id) == 2 + end + + test "does not count chats for different entity" do + Chats.create_chat_with_message( + %{entity: :record, musicbrainz_id: @musicbrainz_id}, + %{role: "user", content: "A chat"} + ) + + assert Chats.count_chats(:artist, @musicbrainz_id) == 0 + end + end + describe "list_chats/2" do setup [:create_chat]