From f1dd45e43843e7ecd94156c9665d5eeb831621d5 Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Tue, 29 Apr 2025 09:58:06 +0100 Subject: [PATCH] Show country flag for artist --- lib/music_library/artists.ex | 14 +++++---- lib/music_library/records/artist_info.ex | 6 ++++ .../live/artist_live/show.ex | 12 ++++++++ .../live/artist_live/show.html.heex | 1 + mix.exs | 1 + mix.lock | 1 + .../live/artist_live/show_test.exs | 29 +++++++++++++++++- test/support/fixtures/discogs/artist.ex | 7 +++++ .../fixtures/discogs/steven wilson.jpeg | Bin 0 -> 6377 bytes .../support/fixtures/music_library/records.ex | 15 +++++++++ 10 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 test/support/fixtures/discogs/steven wilson.jpeg diff --git a/lib/music_library/artists.ex b/lib/music_library/artists.ex index 3baa714f..e4ef55c5 100644 --- a/lib/music_library/artists.ex +++ b/lib/music_library/artists.ex @@ -51,24 +51,20 @@ defmodule MusicLibrary.Artists do if discogs_id = MusicBrainz.Artist.get_discogs_id(musicbrainz_artist) do case Discogs.get_artist(discogs_id) do {:ok, discogs_artist} -> - %ArtistInfo{} - |> ArtistInfo.changeset(%{ + create_artist_info(%{ id: musicbrainz_artist.id, musicbrainz_data: musicbrainz_artist.musicbrainz_data, discogs_data: discogs_artist }) - |> Repo.insert(on_conflict: {:replace, [:musicbrainz_data, :discogs_data]}) error -> error end else - %ArtistInfo{} - |> ArtistInfo.changeset(%{ + create_artist_info(%{ id: musicbrainz_artist.id, musicbrainz_data: musicbrainz_artist.musicbrainz_data }) - |> Repo.insert(on_conflict: {:replace, [:musicbrainz_data, :discogs_data]}) end error -> @@ -76,6 +72,12 @@ defmodule MusicLibrary.Artists do end end + def create_artist_info(attrs) do + %ArtistInfo{} + |> ArtistInfo.changeset(attrs) + |> Repo.insert(on_conflict: {:replace, [:musicbrainz_data, :discogs_data]}) + end + def get_artist_info!(artist_id) do Repo.get!(ArtistInfo, artist_id) end diff --git a/lib/music_library/records/artist_info.ex b/lib/music_library/records/artist_info.ex index b5ada484..fa7b1cf1 100644 --- a/lib/music_library/records/artist_info.ex +++ b/lib/music_library/records/artist_info.ex @@ -28,6 +28,12 @@ defmodule MusicLibrary.Records.ArtistInfo do |> generate_image_hash() end + def country(artist_info) do + %{"area" => area} = artist_info.musicbrainz_data + [country_code | _rest] = area["iso-3166-1-codes"] + %{name: area["name"], code: country_code} + end + def generate_image_hash(%__MODULE__{image_data: image_data} = artist_info) do change(artist_info, image_data_hash: Cover.hash(image_data)) end diff --git a/lib/music_library_web/live/artist_live/show.ex b/lib/music_library_web/live/artist_live/show.ex index 4dfaf48b..eed9b0b9 100644 --- a/lib/music_library_web/live/artist_live/show.ex +++ b/lib/music_library_web/live/artist_live/show.ex @@ -2,8 +2,18 @@ defmodule MusicLibraryWeb.ArtistLive.Show do use MusicLibraryWeb, :live_view alias MusicLibrary.{Artists, Records} + alias MusicLibrary.Records.ArtistInfo import MusicLibraryWeb.RecordComponents, only: [record_grid: 1] + attr :country, :map, required: true + + def country_flag(assigns) do + ~H""" + {Flagmojis.by_iso(@country.code).emoji} + {@country.name} + """ + end + @impl true def mount(_params, _session, socket) do {:ok, socket} @@ -45,6 +55,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do defp apply_action(socket, :show, %{"musicbrainz_id" => musicbrainz_id}) do artist = Artists.get_artist!(musicbrainz_id) + artist_info = Artists.get_artist_info!(musicbrainz_id) %{collection: collection_records, wishlist: wishlist_records} = musicbrainz_id @@ -54,6 +65,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do socket |> assign(:nav_section, :artists) |> assign(:artist, artist) + |> assign(:country, ArtistInfo.country(artist_info)) |> stream(:collection_records, collection_records, reset: true) |> stream(:wishlist_records, wishlist_records, reset: true) |> assign(:collection_records_count, Enum.count(collection_records)) diff --git a/lib/music_library_web/live/artist_live/show.html.heex b/lib/music_library_web/live/artist_live/show.html.heex index 9cf1077c..16facd41 100644 --- a/lib/music_library_web/live/artist_live/show.html.heex +++ b/lib/music_library_web/live/artist_live/show.html.heex @@ -2,6 +2,7 @@

{@artist.name} + <.country_flag country={@country} />

diff --git a/mix.exs b/mix.exs index 4a20a6a4..cfde288d 100644 --- a/mix.exs +++ b/mix.exs @@ -63,6 +63,7 @@ defmodule MusicLibrary.MixProject do compile: false, depth: 1}, {:fluxon, "~> 1.1.0", repo: :fluxon}, + {:flagmojis, "~> 1.0"}, # Dev tooling {:phoenix_live_reload, "~> 1.2", only: :dev}, diff --git a/mix.lock b/mix.lock index 246bc16f..aaf3e237 100644 --- a/mix.lock +++ b/mix.lock @@ -20,6 +20,7 @@ "fast_html": {:hex, :fast_html, "2.4.1", "73142526cee294b0ec8cf122483f32c861e4a9d988c60cd04f63ce7fd9e5a620", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "767a63ecc941d3fc0e0e9609ded1a5e798398e5b1bf4d2f47bcb5992a86b32cf"}, "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, + "flagmojis": {:hex, :flagmojis, "1.0.0", "d2b411d9d2c150180103a4d605ee394cabc23c2b6ddf7a0011a9a55a23575281", [:mix], [], "hexpm", "9d9916575cf9dcbe6f0199b410994bec9d19d47971f70089eb7f210f823cd293"}, "floki": {:hex, :floki, "0.37.1", "d7aaee758c8a5b4a7495799a4260754fec5530d95b9c383c03b27359dea117cf", [:mix], [], "hexpm", "673d040cb594d31318d514590246b6dd587ed341d3b67e17c1c0eb8ce7ca6f04"}, "fluxon": {:hex, :fluxon, "1.1.1", "79195863f5d62362cb296c6fe8c5ec739f0766f90a4e5d2fda7665d492f575b5", [:mix], [{:phoenix_live_view, ">= 1.0.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "fluxon", "b49d4a8688a32650f90c363fc8f5cedae36d1d4be023b380068bde1a3043b9ce"}, "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"}, diff --git a/test/music_library_web/live/artist_live/show_test.exs b/test/music_library_web/live/artist_live/show_test.exs index b12f7e86..6433c8e2 100644 --- a/test/music_library_web/live/artist_live/show_test.exs +++ b/test/music_library_web/live/artist_live/show_test.exs @@ -13,7 +13,13 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do [artist] = collection_record.artists - %{collection_record: collection_record, artist_musicbrainz_id: artist.musicbrainz_id} + artist_info = artist_info(artist.musicbrainz_id) + + %{ + collection_record: collection_record, + artist_musicbrainz_id: artist.musicbrainz_id, + artist_info: artist_info + } end describe "Show artist" do @@ -64,6 +70,27 @@ defmodule MusicLibraryWeb.ArtistLive.ShowTest do |> assert_has("div", text: "Error loading biography") end + test "it shows the artist country", %{ + conn: conn, + artist_musicbrainz_id: artist_musicbrainz_id + } do + Req.Test.stub(LastFm.API, fn conn -> + case Map.get(conn.params, "method") do + "artist.getInfo" -> + Req.Test.json(conn, Fixtures.Artist.get_info()) + + "artist.getSimilar" -> + Req.Test.json(conn, Fixtures.Artist.get_similar_artists()) + end + end) + + conn + |> visit(~p"/artists/#{artist_musicbrainz_id}") + |> unwrap(&render_async/1) + |> assert_has("span", text: "United Kingdom") + |> assert_has("span", text: "🇬🇧") + end + test "it shows records from the collection and the wishlist", %{ conn: conn, collection_record: collection_record, diff --git a/test/support/fixtures/discogs/artist.ex b/test/support/fixtures/discogs/artist.ex index 2e65d80b..2fe451ca 100644 --- a/test/support/fixtures/discogs/artist.ex +++ b/test/support/fixtures/discogs/artist.ex @@ -6,4 +6,11 @@ defmodule Discogs.Fixtures.Artist do |> File.read!() |> JSON.decode!() end + + def image_data do + Path.join([@fixtures_folder, "steven wilson.jpeg"]) + |> File.read!() + end + + def image_width, do: 225 end diff --git a/test/support/fixtures/discogs/steven wilson.jpeg b/test/support/fixtures/discogs/steven wilson.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..134041457c529d2125f4fc206462f7afa5dab4d4 GIT binary patch literal 6377 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 RfEJL&u`=+v^1 literal 0 HcmV?d00001 diff --git a/test/support/fixtures/music_library/records.ex b/test/support/fixtures/music_library/records.ex index 31384026..01215daf 100644 --- a/test/support/fixtures/music_library/records.ex +++ b/test/support/fixtures/music_library/records.ex @@ -75,6 +75,21 @@ defmodule MusicLibrary.Fixtures.Records do record end + def artist_info(musicbrainz_id, attrs \\ %{}) do + {:ok, artist_info} = + attrs + |> Enum.into(%{ + id: musicbrainz_id, + musicbrainz_data: MusicBrainz.Fixtures.Artist.get_artist(), + discogs_data: Discogs.Fixtures.Artist.get_artist(), + image_data: Discogs.Fixtures.Artist.image_data(), + image_width: Discogs.Fixtures.Artist.image_width() + }) + |> MusicLibrary.Artists.create_artist_info() + + artist_info + end + def record_with_artist(artist_name, record_attrs \\ %{}) do record_attrs |> Map.put(:artists, [artist_attrs(artist_name)])