Update to new interpolation syntax

Includes a fix to a brittle test that failed due to changes in the
number of linebreaks.
This commit is contained in:
Claudio Ortolina
2024-12-02 23:28:11 +00:00
parent 9448e77e23
commit ccefc6e697
16 changed files with 191 additions and 191 deletions
@@ -84,7 +84,7 @@ defmodule MusicLibraryWeb.CoreComponents do
</button> </button>
</div> </div>
<div id={"#{@id}-content"}> <div id={"#{@id}-content"}>
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</div> </div>
</.focus_wrap> </.focus_wrap>
</div> </div>
@@ -129,9 +129,9 @@ defmodule MusicLibraryWeb.CoreComponents do
<p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6"> <p :if={@title} class="flex items-center gap-1.5 text-sm font-semibold leading-6">
<.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" /> <.icon :if={@kind == :info} name="hero-information-circle-mini" class="h-4 w-4" />
<.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" /> <.icon :if={@kind == :error} name="hero-exclamation-circle-mini" class="h-4 w-4" />
<%= @title %> {@title}
</p> </p>
<p class="mt-2 text-sm leading-5"><%= msg %></p> <p class="mt-2 text-sm leading-5">{msg}</p>
<button type="button" class="group absolute top-1 right-1 p-2" aria-label={gettext("close")}> <button type="button" class="group absolute top-1 right-1 p-2" aria-label={gettext("close")}>
<.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" /> <.icon name="hero-x-mark-solid" class="h-5 w-5 opacity-40 group-hover:opacity-70" />
</button> </button>
@@ -162,7 +162,7 @@ defmodule MusicLibraryWeb.CoreComponents do
phx-connected={hide("#client-error")} phx-connected={hide("#client-error")}
hidden hidden
> >
<%= gettext("Attempting to reconnect") %> {gettext("Attempting to reconnect")}
<.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" /> <.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" />
</.flash> </.flash>
@@ -174,7 +174,7 @@ defmodule MusicLibraryWeb.CoreComponents do
phx-connected={hide("#server-error")} phx-connected={hide("#server-error")}
hidden hidden
> >
<%= gettext("Hang in there while we get back on track") %> {gettext("Hang in there while we get back on track")}
<.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" /> <.icon name="hero-arrow-path" class="ml-1 h-3 w-3 animate-spin" />
</.flash> </.flash>
</div> </div>
@@ -208,9 +208,9 @@ defmodule MusicLibraryWeb.CoreComponents do
~H""" ~H"""
<.form :let={f} for={@for} as={@as} {@rest}> <.form :let={f} for={@for} as={@as} {@rest}>
<div class="mt-10 space-y-8 bg-white dark:bg-zinc-800"> <div class="mt-10 space-y-8 bg-white dark:bg-zinc-800">
<%= render_slot(@inner_block, f) %> {render_slot(@inner_block, f)}
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6"> <div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
<%= render_slot(action, f) %> {render_slot(action, f)}
</div> </div>
</div> </div>
</.form> </.form>
@@ -245,7 +245,7 @@ defmodule MusicLibraryWeb.CoreComponents do
]} ]}
{@rest} {@rest}
> >
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</button> </button>
""" """
end end
@@ -330,9 +330,9 @@ defmodule MusicLibraryWeb.CoreComponents do
class="rounded border-zinc-300 text-zinc-900 focus:ring-0" class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
{@rest} {@rest}
/> />
<%= @label %> {@label}
</label> </label>
<.error :for={msg <- @errors}><%= msg %></.error> <.error :for={msg <- @errors}>{msg}</.error>
</div> </div>
""" """
end end
@@ -340,7 +340,7 @@ defmodule MusicLibraryWeb.CoreComponents do
def input(%{type: "select"} = assigns) do def input(%{type: "select"} = assigns) do
~H""" ~H"""
<div> <div>
<.label for={@id}><%= @label %></.label> <.label for={@id}>{@label}</.label>
<select <select
id={@id} id={@id}
name={@name} name={@name}
@@ -358,10 +358,10 @@ defmodule MusicLibraryWeb.CoreComponents do
multiple={@multiple} multiple={@multiple}
{@rest} {@rest}
> >
<option :if={@prompt} value=""><%= @prompt %></option> <option :if={@prompt} value="">{@prompt}</option>
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %> {Phoenix.HTML.Form.options_for_select(@options, @value)}
</select> </select>
<.error :for={msg <- @errors}><%= msg %></.error> <.error :for={msg <- @errors}>{msg}</.error>
</div> </div>
""" """
end end
@@ -369,7 +369,7 @@ defmodule MusicLibraryWeb.CoreComponents do
def input(%{type: "textarea"} = assigns) do def input(%{type: "textarea"} = assigns) do
~H""" ~H"""
<div> <div>
<.label for={@id}><%= @label %></.label> <.label for={@id}>{@label}</.label>
<textarea <textarea
id={@id} id={@id}
name={@name} name={@name}
@@ -380,7 +380,7 @@ defmodule MusicLibraryWeb.CoreComponents do
]} ]}
{@rest} {@rest}
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea> ><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
<.error :for={msg <- @errors}><%= msg %></.error> <.error :for={msg <- @errors}>{msg}</.error>
</div> </div>
""" """
end end
@@ -389,7 +389,7 @@ defmodule MusicLibraryWeb.CoreComponents do
def input(assigns) do def input(assigns) do
~H""" ~H"""
<div> <div>
<.label for={@id}><%= @label %></.label> <.label for={@id}>{@label}</.label>
<input <input
type={@type} type={@type}
name={@name} name={@name}
@@ -410,7 +410,7 @@ defmodule MusicLibraryWeb.CoreComponents do
]} ]}
{@rest} {@rest}
/> />
<.error :for={msg <- @errors}><%= msg %></.error> <.error :for={msg <- @errors}>{msg}</.error>
</div> </div>
""" """
end end
@@ -424,7 +424,7 @@ defmodule MusicLibraryWeb.CoreComponents do
def label(assigns) do def label(assigns) do
~H""" ~H"""
<label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800 dark:text-zinc-400"> <label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800 dark:text-zinc-400">
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</label> </label>
""" """
end end
@@ -438,7 +438,7 @@ defmodule MusicLibraryWeb.CoreComponents do
~H""" ~H"""
<p class="mt-3 flex gap-3 text-sm leading-6 text-rose-600"> <p class="mt-3 flex gap-3 text-sm leading-6 text-rose-600">
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" /> <.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</p> </p>
""" """
end end
@@ -460,13 +460,13 @@ defmodule MusicLibraryWeb.CoreComponents do
]}> ]}>
<div class="font-semibold"> <div class="font-semibold">
<h1 class="text-sm md:text-base lg:text-2xl text-zinc-900"> <h1 class="text-sm md:text-base lg:text-2xl text-zinc-900">
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</h1> </h1>
<h2 :if={@subtitle != []} class="mt-2 text-sm md:text-base text-zinc-600"> <h2 :if={@subtitle != []} class="mt-2 text-sm md:text-base text-zinc-600">
<%= render_slot(@subtitle) %> {render_slot(@subtitle)}
</h2> </h2>
</div> </div>
<div class="flex justify-center gap-2 sm:flex-none mt-4 mb-4"><%= render_slot(@actions) %></div> <div class="flex justify-center gap-2 sm:flex-none mt-4 mb-4">{render_slot(@actions)}</div>
</header> </header>
""" """
end end
@@ -507,9 +507,9 @@ defmodule MusicLibraryWeb.CoreComponents do
<table class="md:w-full"> <table class="md:w-full">
<thead class="text-sm text-left leading-6 text-zinc-500"> <thead class="text-sm text-left leading-6 text-zinc-500">
<tr> <tr>
<th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal"><%= col[:label] %></th> <th :for={col <- @col} class="p-0 pb-4 pr-6 font-normal">{col[:label]}</th>
<th :if={@action != []} class="relative p-0 pb-4"> <th :if={@action != []} class="relative p-0 pb-4">
<span class="sr-only"><%= gettext("Actions") %></span> <span class="sr-only">{gettext("Actions")}</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@@ -527,7 +527,7 @@ defmodule MusicLibraryWeb.CoreComponents do
<div class="block py-4 pr-6"> <div class="block py-4 pr-6">
<span class="absolute -inset-y-px right-0 -left-4 sm:rounded-l-xl" /> <span class="absolute -inset-y-px right-0 -left-4 sm:rounded-l-xl" />
<span class={["relative", i == 0 && "font-semibold text-zinc-900"]}> <span class={["relative", i == 0 && "font-semibold text-zinc-900"]}>
<%= render_slot(col, @row_item.(row)) %> {render_slot(col, @row_item.(row))}
</span> </span>
</div> </div>
</td> </td>
@@ -538,7 +538,7 @@ defmodule MusicLibraryWeb.CoreComponents do
:for={action <- @action} :for={action <- @action}
class="relative ml-4 max-sm:ml-2 max-sm:text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700" class="relative ml-4 max-sm:ml-2 max-sm:text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700"
> >
<%= render_slot(action, @row_item.(row)) %> {render_slot(action, @row_item.(row))}
</span> </span>
</div> </div>
</td> </td>
@@ -568,8 +568,8 @@ defmodule MusicLibraryWeb.CoreComponents do
<div class="mt-14"> <div class="mt-14">
<dl class="-my-4 divide-y divide-zinc-100"> <dl class="-my-4 divide-y divide-zinc-100">
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8"> <div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt> <dt class="w-1/4 flex-none text-zinc-500">{item.title}</dt>
<dd class="text-zinc-700"><%= render_slot(item) %></dd> <dd class="text-zinc-700">{render_slot(item)}</dd>
</div> </div>
</dl> </dl>
</div> </div>
@@ -594,7 +594,7 @@ defmodule MusicLibraryWeb.CoreComponents do
class="text-sm font-semibold leading-6 text-zinc-900 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300" class="text-sm font-semibold leading-6 text-zinc-900 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300"
> >
<.icon name="hero-arrow-left-solid" class="h-3 w-3" /> <.icon name="hero-arrow-left-solid" class="h-3 w-3" />
<%= render_slot(@inner_block) %> {render_slot(@inner_block)}
</.link> </.link>
</div> </div>
""" """
@@ -4,28 +4,28 @@
<div class="flex"> <div class="flex">
<div class="flex space-x-4 md:space-x-8"> <div class="flex space-x-4 md:space-x-8">
<.link navigate={~p"/"} class={section_link_classes(assigns[:nav_section], :stats)}> <.link navigate={~p"/"} class={section_link_classes(assigns[:nav_section], :stats)}>
<%= gettext("Stats") %> {gettext("Stats")}
</.link> </.link>
<.link <.link
navigate={~p"/collection"} navigate={~p"/collection"}
class={section_link_classes(assigns[:nav_section], :records)} class={section_link_classes(assigns[:nav_section], :records)}
> >
<%= gettext("Collection") %> {gettext("Collection")}
</.link> </.link>
<.link <.link
navigate={~p"/wishlist"} navigate={~p"/wishlist"}
class={section_link_classes(assigns[:nav_section], :wishlist)} class={section_link_classes(assigns[:nav_section], :wishlist)}
> >
<%= gettext("Wishlist") %> {gettext("Wishlist")}
</.link> </.link>
</div> </div>
</div> </div>
<div class="flex space-x-8"> <div class="flex space-x-8">
<a class={["max-sm:hidden" | nav_link_classes()]} } href={~p"/dev/dashboard"}> <a class={["max-sm:hidden" | nav_link_classes()]} } href={~p"/dev/dashboard"}>
<%= gettext("Dev dashboard") %> {gettext("Dev dashboard")}
</a> </a>
<a class={nav_link_classes()} } href={~p"/login"}> <a class={nav_link_classes()} } href={~p"/login"}>
<%= gettext("Logout") %> {gettext("Logout")}
</a> </a>
</div> </div>
</div> </div>
@@ -34,6 +34,6 @@
<main class="px-4 py-4 max-sm:pb-20 sm:px-6 lg:px-8"> <main class="px-4 py-4 max-sm:pb-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-screen-xl"> <div class="mx-auto max-w-screen-xl">
<.flash_group flash={@flash} /> <.flash_group flash={@flash} />
<%= @inner_content %> {@inner_content}
</div> </div>
</main> </main>
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} /> <meta name="csrf-token" content={get_csrf_token()} />
<.live_title suffix=" · Music Library"> <.live_title suffix=" · Music Library">
<%= assigns[:page_title] || assigns.conn.request_path %> {assigns[:page_title] || assigns.conn.request_path}
</.live_title> </.live_title>
<link rel="preconnect" href="https://rsms.me/" /> <link rel="preconnect" href="https://rsms.me/" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" /> <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
@@ -35,7 +35,7 @@
</script> </script>
</head> </head>
<body class="bg-white dark:bg-zinc-900"> <body class="bg-white dark:bg-zinc-900">
<%= @inner_content %> {@inner_content}
<footer class="mt-8 border-t border-slate-900/10 dark:border-slate-300/10"> <footer class="mt-8 border-t border-slate-900/10 dark:border-slate-300/10">
<div class="mx-auto max-w-7xl px-6 pb-8 lg:px-8"> <div class="mx-auto max-w-7xl px-6 pb-8 lg:px-8">
<div class="pt-8 flex items-center justify-between"> <div class="pt-8 flex items-center justify-between">
@@ -55,7 +55,7 @@
</a> </a>
</div> </div>
<p class="text-sm/6 text-zinc-600 dark:text-zinc-400 order-1"> <p class="text-sm/6 text-zinc-600 dark:text-zinc-400 order-1">
<span><%= gettext("Made by") %></span> <span>{gettext("Made by")}</span>
<a <a
class="font-medium text-zinc-500 hover:border-zinc-300 hover:text-zinc-700 dark:text-zinc-300 dark:hover:text-zinc-200" class="font-medium text-zinc-500 hover:border-zinc-300 hover:text-zinc-700 dark:text-zinc-300 dark:hover:text-zinc-200"
href="https://claudio-ortolina.org" href="https://claudio-ortolina.org"
@@ -1,6 +1,6 @@
<main class="px-4 py-8 max-sm:pb-20 sm:px-6 lg:px-8"> <main class="px-4 py-8 max-sm:pb-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-5xl"> <div class="mx-auto max-w-5xl">
<.flash_group flash={@flash} /> <.flash_group flash={@flash} />
<%= @inner_content %> {@inner_content}
</div> </div>
</main> </main>
@@ -32,7 +32,7 @@ defmodule MusicLibraryWeb.Pagination do
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600" "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600"
]} ]}
> >
<%= gettext("Previous") %> {gettext("Previous")}
</.link> </.link>
<.link <.link
:if={@page_links.next_page} :if={@page_links.next_page}
@@ -45,7 +45,7 @@ defmodule MusicLibraryWeb.Pagination do
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600" "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600"
]} ]}
> >
<%= gettext("Next") %> {gettext("Next")}
</.link> </.link>
</div> </div>
<div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-items-center sm:justify-center"> <div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-items-center sm:justify-center">
@@ -108,7 +108,7 @@ defmodule MusicLibraryWeb.Pagination do
]} ]}
patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)} patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)}
> >
<span class="sr-only"><%= gettext("Next") %></span> <span class="sr-only">{gettext("Next")}</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path <path
fill-rule="evenodd" fill-rule="evenodd"
@@ -130,7 +130,7 @@ defmodule MusicLibraryWeb.Pagination do
class="relative inline-flex items-center rounded-l-md px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 hover:bg-zinc-50 focus:z-20 focus:outline-offset-0" class="relative inline-flex items-center rounded-l-md px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 hover:bg-zinc-50 focus:z-20 focus:outline-offset-0"
patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)} patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)}
> >
<span class="sr-only"><%= gettext("Previous") %></span> <span class="sr-only">{gettext("Previous")}</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path <path
fill-rule="evenodd" fill-rule="evenodd"
@@ -158,7 +158,7 @@ defmodule MusicLibraryWeb.Pagination do
defp numbered_link(assigns) when assigns.active do defp numbered_link(assigns) when assigns.active do
~H""" ~H"""
<span class="relative z-10 inline-flex items-center first:rounded-l-md last:rounded-r-md bg-zinc-600 dark:bg-zinc-300 px-4 py-2 text-sm font-semibold text-white dark:text-zinc-700 focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600"> <span class="relative z-10 inline-flex items-center first:rounded-l-md last:rounded-r-md bg-zinc-600 dark:bg-zinc-300 px-4 py-2 text-sm font-semibold text-white dark:text-zinc-700 focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600">
<%= @page_number %> {@page_number}
</span> </span>
""" """
end end
@@ -169,7 +169,7 @@ defmodule MusicLibraryWeb.Pagination do
class="relative hidden items-center first:rounded-l-md last:rounded-r-md px-4 py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-400 ring-1 ring-inset ring-zinc-300 hover:bg-zinc-300 hover:text-zinc-500 focus:z-20 focus:outline-offset-0 md:inline-flex" class="relative hidden items-center first:rounded-l-md last:rounded-r-md px-4 py-2 text-sm font-semibold text-zinc-900 dark:text-zinc-400 ring-1 ring-inset ring-zinc-300 hover:bg-zinc-300 hover:text-zinc-500 focus:z-20 focus:outline-offset-0 md:inline-flex"
patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)} patch={"?" <> encode_query(page: @page_number, page_size: @page_size, query: @query)}
> >
<%= @page_number %> {@page_number}
</.link> </.link>
""" """
end end
@@ -2,13 +2,13 @@
<div class="w-full max-w-sm space-y-10"> <div class="w-full max-w-sm space-y-10">
<div> <div>
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-zinc-900 dark:text-zinc-200"> <h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-zinc-900 dark:text-zinc-200">
<%= gettext("Welcome to your Music Library") %> {gettext("Welcome to your Music Library")}
</h2> </h2>
</div> </div>
<.form class="space-y-6" for={@form} action={~p"/sessions/create"}> <.form class="space-y-6" for={@form} action={~p"/sessions/create"}>
<div class="relative -space-y-px rounded-md shadow-sm"> <div class="relative -space-y-px rounded-md shadow-sm">
<div> <div>
<label for="password" class="sr-only"><%= gettext("Password") %></label> <label for="password" class="sr-only">{gettext("Password")}</label>
<input <input
id="password" id="password"
name="password" name="password"
@@ -41,7 +41,7 @@
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600" "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600"
]} ]}
> >
<%= gettext("Login") %> {gettext("Login")}
</button> </button>
</div> </div>
</.form> </.form>
@@ -1,17 +1,17 @@
<div class="mt-4 px-4 sm:px-6 lg:px-8"> <div class="mt-4 px-4 sm:px-6 lg:px-8">
<h1 class="mt-1 flex font-semibold text-base lg:text-2xl leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h1 class="mt-1 flex font-semibold text-base lg:text-2xl leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= @artist.name %> {@artist.name}
</h1> </h1>
<p <p
:if={artist_info = @artist_info.ok? && @artist_info.result} :if={artist_info = @artist_info.ok? && @artist_info.result}
class="bio mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400" class="bio mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400"
> >
<%= (artist_info.bio || gettext("Biography not available")) |> raw() %> {(artist_info.bio || gettext("Biography not available")) |> raw()}
</p> </p>
<div :if={@artist_records.collection !== []} class="mt-4"> <div :if={@artist_records.collection !== []} class="mt-4">
<h2 class="font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300"> <h2 class="font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300">
<%= gettext("Collection") %> {gettext("Collection")}
</h2> </h2>
<ul <ul
role="list" role="list"
@@ -29,19 +29,19 @@
class="absolute inset-0 focus:outline-none" class="absolute inset-0 focus:outline-none"
phx-click={JS.navigate(~p"/collection/#{record}")} phx-click={JS.navigate(~p"/collection/#{record}")}
> >
<span class="sr-only"><%= gettext("View details") %></span> <span class="sr-only">{gettext("View details")}</span>
</button> </button>
</div> </div>
<p class="pointer-events-none mt-2 block truncate text-sm font-medium text-zinc-900 dark:text-zinc-300"> <p class="pointer-events-none mt-2 block truncate text-sm font-medium text-zinc-900 dark:text-zinc-300">
<%= record.title %> {record.title}
</p> </p>
<p class="pointer-events-none block text-sm font-medium text-zinc-500"> <p class="pointer-events-none block text-sm font-medium text-zinc-500">
<%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
</p> </p>
<p class="pointer-events-none block text-sm font-medium text-zinc-500"> <p class="pointer-events-none block text-sm font-medium text-zinc-500">
<%= Records.Record.format_release(record.release) %> {Records.Record.format_release(record.release)}
</p> </p>
</li> </li>
</ul> </ul>
@@ -49,7 +49,7 @@
<div :if={@artist_records.wishlist !== []} class="mt-4"> <div :if={@artist_records.wishlist !== []} class="mt-4">
<h2 class="font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300"> <h2 class="font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300">
<%= gettext("Wishlist") %> {gettext("Wishlist")}
</h2> </h2>
<ul <ul
role="list" role="list"
@@ -67,19 +67,19 @@
class="absolute inset-0 focus:outline-none" class="absolute inset-0 focus:outline-none"
phx-click={JS.navigate(~p"/wishlist/#{record}")} phx-click={JS.navigate(~p"/wishlist/#{record}")}
> >
<span class="sr-only"><%= gettext("View details") %></span> <span class="sr-only">{gettext("View details")}</span>
</button> </button>
</div> </div>
<p class="pointer-events-none mt-2 block truncate text-sm font-medium text-zinc-900 dark:text-zinc-300"> <p class="pointer-events-none mt-2 block truncate text-sm font-medium text-zinc-900 dark:text-zinc-300">
<%= record.title %> {record.title}
</p> </p>
<p class="pointer-events-none block text-sm font-medium text-zinc-500"> <p class="pointer-events-none block text-sm font-medium text-zinc-500">
<%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
</p> </p>
<p class="pointer-events-none block text-sm font-medium text-zinc-500"> <p class="pointer-events-none block text-sm font-medium text-zinc-500">
<%= Records.Record.format_release(record.release) %> {Records.Record.format_release(record.release)}
</p> </p>
</li> </li>
</ul> </ul>
@@ -14,17 +14,17 @@
/> />
</form> </form>
<.link patch={~p"/collection/import"}> <.link patch={~p"/collection/import"}>
<.button><%= gettext("Import") %></.button> <.button>{gettext("Import")}</.button>
</.link> </.link>
</div> </div>
</header> </header>
<p class="text-right text-sm max-sm:text-xs mt-8 text-zinc-900 dark:text-zinc-400"> <p class="text-right text-sm max-sm:text-xs mt-8 text-zinc-900 dark:text-zinc-400">
<%= gettext( {gettext(
"Showing <b>%{visible}</b> of <b>%{total}</b> records", "Showing <b>%{visible}</b> of <b>%{total}</b> records",
%{visible: Enum.count(@streams.records), total: @record_list_params.total_entries} %{visible: Enum.count(@streams.records), total: @record_list_params.total_entries}
) )
|> raw() %> |> raw()}
</p> </p>
</div> </div>
@@ -53,22 +53,22 @@
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/artists/#{artist.musicbrainz_id}"} patch={~p"/artists/#{artist.musicbrainz_id}"}
> >
<%= artist.name %> {artist.name}
</.link> </.link>
</h1> </h1>
<h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= record.title %> {record.title}
</h2> </h2>
<p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400"> <p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400">
<%= Records.Record.format_release(record.release) %> {Records.Record.format_release(record.release)}
<span class="sm:hidden"> <span class="sm:hidden">
· <%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( · {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
<span :if={Records.Record.child_release_groups_count(record) > 0}> <span :if={Records.Record.child_release_groups_count(record) > 0}>
· ·
<span class="sr-only"> <span class="sr-only">
<%= gettext("Number of included records") %> {gettext("Number of included records")}
</span> </span>
<span class={[ <span class={[
"inline-flex items-center rounded-full", "inline-flex items-center rounded-full",
@@ -78,7 +78,7 @@
"text-gray-600 dark:text-gray-500", "text-gray-600 dark:text-gray-500",
"ring-gray-500/10 dark:ring-gray-400/20" "ring-gray-500/10 dark:ring-gray-400/20"
]}> ]}>
<%= Records.Record.child_release_groups_count(record) %> {Records.Record.child_release_groups_count(record)}
</span> </span>
</span> </span>
</span> </span>
@@ -88,13 +88,13 @@
<div class="flex shrink-0 items-center gap-x-6"> <div class="flex shrink-0 items-center gap-x-6">
<div class="hidden sm:flex sm:flex-col sm:items-end"> <div class="hidden sm:flex sm:flex-col sm:items-end">
<p class="text-xs leading-6 text-zinc-900 dark:text-zinc-300"> <p class="text-xs leading-6 text-zinc-900 dark:text-zinc-300">
<%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
<span :if={Records.Record.child_release_groups_count(record) > 0}> <span :if={Records.Record.child_release_groups_count(record) > 0}>
· ·
<span class="sr-only"> <span class="sr-only">
<%= gettext("Number of included records") %> {gettext("Number of included records")}
</span> </span>
<span class={[ <span class={[
"inline-flex items-center rounded-full", "inline-flex items-center rounded-full",
@@ -104,7 +104,7 @@
"text-gray-600 dark:text-gray-500", "text-gray-600 dark:text-gray-500",
"ring-gray-500/10 dark:ring-gray-400/20" "ring-gray-500/10 dark:ring-gray-400/20"
]}> ]}>
<%= Records.Record.child_release_groups_count(record) %> {Records.Record.child_release_groups_count(record)}
</span> </span>
</span> </span>
</p> </p>
@@ -118,7 +118,7 @@
phx-click={toggle_actions_menu(record.id)} phx-click={toggle_actions_menu(record.id)}
phx-click-away={close_actions_menu(record.id)} phx-click-away={close_actions_menu(record.id)}
> >
<span class="sr-only"><%= gettext("Open options") %></span> <span class="sr-only">{gettext("Open options")}</span>
<.icon <.icon
name="hero-ellipsis-vertical" name="hero-ellipsis-vertical"
class="-mt-1 h-5 w-5" class="-mt-1 h-5 w-5"
@@ -153,7 +153,7 @@
id={"actions-#{record.id}-show"} id={"actions-#{record.id}-show"}
navigate={~p"/collection/#{record}"} navigate={~p"/collection/#{record}"}
> >
<%= gettext("Show") %> {gettext("Show")}
</.link> </.link>
<a <a
href={musicbrainz_url(record)} href={musicbrainz_url(record)}
@@ -163,7 +163,7 @@
tabindex="-1" tabindex="-1"
id={"actions-#{record.id}-musicbrainz"} id={"actions-#{record.id}-musicbrainz"}
> >
<%= gettext("View on MusicBrainz") %> {gettext("View on MusicBrainz")}
</a> </a>
<.link <.link
@@ -173,7 +173,7 @@
id={"actions-#{record.id}-edit"} id={"actions-#{record.id}-edit"}
patch={~p"/collection/#{record}/edit"} patch={~p"/collection/#{record}/edit"}
> >
<%= gettext("Edit") %> {gettext("Edit")}
</.link> </.link>
<.link <.link
@@ -184,7 +184,7 @@
phx-click={JS.push("delete", value: %{id: record.id}) |> hide("##{id}")} phx-click={JS.push("delete", value: %{id: record.id}) |> hide("##{id}")}
data-confirm={gettext("Are you sure?")} data-confirm={gettext("Are you sure?")}
> >
<%= gettext("Delete") %> {gettext("Delete")}
</.link> </.link>
</.focus_wrap> </.focus_wrap>
</div> </div>
@@ -14,46 +14,46 @@
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/artists/#{artist.musicbrainz_id}"} patch={~p"/artists/#{artist.musicbrainz_id}"}
> >
<%= artist.name %> {artist.name}
</.link> </.link>
</h1> </h1>
<h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= @record.title %> {@record.title}
</h2> </h2>
<p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400"> <p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400">
<%= Records.Record.format_release(@record.release) %> · <%= Records.Record.format_long_label( {Records.Record.format_release(@record.release)} · {Records.Record.format_long_label(
@record.format @record.format
) %> · <%= Records.Record.type_long_label(@record.type) %> )} · {Records.Record.type_long_label(@record.type)}
</p> </p>
<!-- TODO: extract to a component --> <!-- TODO: extract to a component -->
<nav class="mt-5 isolate inline-flex rounded-md shadow-sm"> <nav class="mt-5 isolate inline-flex rounded-md shadow-sm">
<.link patch={~p"/collection/#{@record}/show/edit"} phx-click={JS.push_focus()}> <.link patch={~p"/collection/#{@record}/show/edit"} phx-click={JS.push_focus()}>
<.button type="button" class="relative inline-flex items-center rounded-r-none"> <.button type="button" class="relative inline-flex items-center rounded-r-none">
<%= gettext("Edit") %> {gettext("Edit")}
</.button> </.button>
</.link> </.link>
<.link phx-click={JS.push("refresh_cover", value: %{id: @record.id})}> <.link phx-click={JS.push("refresh_cover", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none"> <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only"><%= gettext("Refresh") %></span> <span class="sr-only">{gettext("Refresh")}</span>
<.icon <.icon
name="hero-arrow-path" name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin" class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true" aria-hidden="true"
data-slot="icon" data-slot="icon"
/> />
<%= gettext("Cover") %> {gettext("Cover")}
</.button> </.button>
</.link> </.link>
<.link phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}> <.link phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none"> <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only"><%= gettext("Refresh") %></span> <span class="sr-only">{gettext("Refresh")}</span>
<.icon <.icon
name="hero-arrow-path" name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin" class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true" aria-hidden="true"
data-slot="icon" data-slot="icon"
/> />
<%= gettext("MB Data") %> {gettext("MB Data")}
</.button> </.button>
</.link> </.link>
<.link <.link
@@ -64,7 +64,7 @@
type="button" type="button"
class="relative -ml-px inline-flex items-center rounded-l-none !text-red-600 hover:!text-red-500 dark:!text-red-700 hover:dark:!text-red-500" class="relative -ml-px inline-flex items-center rounded-l-none !text-red-600 hover:!text-red-500 dark:!text-red-700 hover:dark:!text-red-500"
> >
<%= gettext("Delete") %> {gettext("Delete")}
</.button> </.button>
</.link> </.link>
</nav> </nav>
@@ -74,7 +74,7 @@
<dl class="mt-4 divide-y divide-zinc-100 dark:divide-slate-300/30"> <dl class="mt-4 divide-y divide-zinc-100 dark:divide-slate-300/30">
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Genres") %> {gettext("Genres")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<.link <.link
@@ -82,23 +82,23 @@
class="mr-2 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="mr-2 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/collection?#{%{query: ~s(genre:"#{genre}")}}"} patch={~p"/collection?#{%{query: ~s(genre:"#{genre}")}}"}
> >
<%= genre %> {genre}
</.link> </.link>
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("MusicBrainz ID") %> {gettext("MusicBrainz ID")}
</dt> </dt>
<dd class="mt-1 text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<a href={musicbrainz_url(@record)}> <a href={musicbrainz_url(@record)}>
<code id={"mb-#{@record.musicbrainz_id}"}><%= @record.musicbrainz_id %></code> <code id={"mb-#{@record.musicbrainz_id}"}>{@record.musicbrainz_id}</code>
</a> </a>
<button phx-click={ <button phx-click={
JS.dispatch("music_library:clipcopy", to: "#mb-" <> @record.musicbrainz_id) JS.dispatch("music_library:clipcopy", to: "#mb-" <> @record.musicbrainz_id)
|> JS.transition("animate-shake") |> JS.transition("animate-shake")
}> }>
<span class="sr-only"><%= gettext("Copy MusicBrainz ID to clipboard") %></span> <span class="sr-only">{gettext("Copy MusicBrainz ID to clipboard")}</span>
<.icon <.icon
name="hero-clipboard-document" name="hero-clipboard-document"
class="-mt-1 h-5 w-5" class="-mt-1 h-5 w-5"
@@ -110,10 +110,10 @@
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Purchased on") %> {gettext("Purchased on")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<%= human_datetime(@record.purchased_at) %> {human_datetime(@record.purchased_at)}
</dd> </dd>
</div> </div>
<div <div
@@ -121,30 +121,30 @@
class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0" class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"
> >
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Includes") %> {gettext("Includes")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<ul> <ul>
<li :for={child_release_group <- Records.Record.child_release_groups(@record)}> <li :for={child_release_group <- Records.Record.child_release_groups(@record)}>
<%= child_release_group.artists %> - <%= child_release_group.title %> {child_release_group.artists} - {child_release_group.title}
</li> </li>
</ul> </ul>
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Inserted at") %> {gettext("Inserted at")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<%= human_datetime(@record.inserted_at) %> {human_datetime(@record.inserted_at)}
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Updated at") %> {gettext("Updated at")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<%= human_datetime(@record.updated_at) %> {human_datetime(@record.updated_at)}
</dd> </dd>
</div> </div>
</dl> </dl>
@@ -152,13 +152,13 @@
</div> </div>
<!-- TODO: extract to a component --> <!-- TODO: extract to a component -->
<details class="mt-4 px-4 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"> <details class="mt-4 px-4 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300">
<summary class="text-xs sm:text-sm"><%= gettext("MusicBrainz data") %></summary> <summary class="text-xs sm:text-sm">{gettext("MusicBrainz data")}</summary>
<pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre> <pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre>
</details> </details>
<div class="mt-4"> <div class="mt-4">
<.back navigate={@back_url}> <.back navigate={@back_url}>
<%= gettext("Back to records") %> {gettext("Back to records")}
</.back> </.back>
</div> </div>
@@ -17,7 +17,7 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do
<div> <div>
<header> <header>
<h1 class="text-base font-medium leading-6 text-zinc-700 dark:text-zinc-400"> <h1 class="text-base font-medium leading-6 text-zinc-700 dark:text-zinc-400">
<%= @title %> {@title}
</h1> </h1>
</header> </header>
@@ -54,16 +54,16 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do
/> />
<div phx-drop-target={@uploads.cover_data.ref}> <div phx-drop-target={@uploads.cover_data.ref}>
<.label for={@uploads.cover_data.ref}> <.label for={@uploads.cover_data.ref}>
<%= gettext("Cover art") %> {gettext("Cover art")}
</.label> </.label>
<span <span
:if={@uploads.cover_data.entries == []} :if={@uploads.cover_data.entries == []}
class="float-right text-zinc-700 dark:text-zinc-400" class="float-right text-zinc-700 dark:text-zinc-400"
> >
<%= gettext("No cover selected") %> {gettext("No cover selected")}
</span> </span>
<%= for entry <- @uploads.cover_data.entries do %> <%= for entry <- @uploads.cover_data.entries do %>
<span class="float-right text-zinc-700 dark:text-zinc-400"><%= entry.progress %>%</span> <span class="float-right text-zinc-700 dark:text-zinc-400">{entry.progress}%</span>
<% end %> <% end %>
<.live_file_input <.live_file_input
class="mt-2 block w-full rounded-lg text-zinc-900 dark:text-zinc-200 focus:ring-0 sm:text-sm sm:leading-6" class="mt-2 block w-full rounded-lg text-zinc-900 dark:text-zinc-200 focus:ring-0 sm:text-sm sm:leading-6"
@@ -71,7 +71,7 @@ defmodule MusicLibraryWeb.RecordLive.FormComponent do
/> />
</div> </div>
<:actions> <:actions>
<.button phx-disable-with={gettext("Saving...")}><%= gettext("Save") %></.button> <.button phx-disable-with={gettext("Saving...")}>{gettext("Save")}</.button>
</:actions> </:actions>
</.simple_form> </.simple_form>
</div> </div>
@@ -42,7 +42,7 @@ defmodule MusicLibraryWeb.RecordLive.ImportComponent do
:if={@release_groups == []} :if={@release_groups == []}
class="flex items-center justify-center h-32 text-md text-zinc-500" class="flex items-center justify-center h-32 text-md text-zinc-500"
> >
<%= gettext("No results") %> {gettext("No results")}
</div> </div>
</div> </div>
""" """
@@ -57,15 +57,15 @@ defmodule MusicLibraryWeb.RecordLive.ImportComponent do
<div class="shrink-0 flex items-center justify-between w-full px-4"> <div class="shrink-0 flex items-center justify-between w-full px-4">
<div class="min-w-0 flex-auto"> <div class="min-w-0 flex-auto">
<h1 class="text-sm leading-6 text-zinc-700 dark:text-zinc-400"> <h1 class="text-sm leading-6 text-zinc-700 dark:text-zinc-400">
<%= @release_group.artists %> {@release_group.artists}
</h1> </h1>
<h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= @release_group.title %> {@release_group.title}
</h2> </h2>
<p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400"> <p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400">
<%= Records.Record.format_release(@release_group.release) %> · <%= Records.Record.type_long_label( {Records.Record.format_release(@release_group.release)} · {Records.Record.type_long_label(
@release_group.type @release_group.type
) %> )}
</p> </p>
</div> </div>
<div class="relative flex-none"> <div class="relative flex-none">
@@ -77,7 +77,7 @@ defmodule MusicLibraryWeb.RecordLive.ImportComponent do
phx-click={toggle_actions_menu(@release_group.id)} phx-click={toggle_actions_menu(@release_group.id)}
phx-click-away={close_actions_menu(@release_group.id)} phx-click-away={close_actions_menu(@release_group.id)}
> >
<span class="sr-only"><%= gettext("Choose which format to import") %></span> <span class="sr-only">{gettext("Choose which format to import")}</span>
<.icon name={@icon_name} class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" /> <.icon name={@icon_name} class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
</button> </button>
<!-- <!--
@@ -110,7 +110,7 @@ defmodule MusicLibraryWeb.RecordLive.ImportComponent do
JS.push("import", value: %{id: @release_group.id, format: format}, page_loading: true) JS.push("import", value: %{id: @release_group.id, format: format}, page_loading: true)
} }
> >
<%= Records.Record.format_long_label(format) %> {Records.Record.format_long_label(format)}
</.link> </.link>
</.focus_wrap> </.focus_wrap>
</div> </div>
@@ -124,7 +124,7 @@ defmodule MusicLibraryWeb.RecordLive.ImportComponent do
defp type_badge(assigns) do defp type_badge(assigns) do
~H""" ~H"""
<span class="inline-flex items-center rounded-md bg-zinc-50 px-2 py-1 text-xs font-medium text-zinc-600 ring-1 ring-inset ring-zinc-500/10"> <span class="inline-flex items-center rounded-md bg-zinc-50 px-2 py-1 text-xs font-medium text-zinc-600 ring-1 ring-inset ring-zinc-500/10">
<%= @type %> {@type}
</span> </span>
""" """
end end
@@ -21,7 +21,7 @@ defmodule MusicLibraryWeb.StatsLive.DataComponents do
alt={@record.title} alt={@record.title}
/> />
<p class="ml-24 truncate text-xs sm:text-sm font-medium text-zinc-500 dark:text-zinc-400"> <p class="ml-24 truncate text-xs sm:text-sm font-medium text-zinc-500 dark:text-zinc-400">
<%= @title %> {@title}
</p> </p>
</dt> </dt>
<dd class="ml-24 flex items-baseline pb-6 sm:pb-7"> <dd class="ml-24 flex items-baseline pb-6 sm:pb-7">
@@ -31,10 +31,10 @@ defmodule MusicLibraryWeb.StatsLive.DataComponents do
class="text-sm md:text-base lg:text-2xl text-zinc-900 hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200" class="text-sm md:text-base lg:text-2xl text-zinc-900 hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
patch={~p"/artists/#{artist.musicbrainz_id}"} patch={~p"/artists/#{artist.musicbrainz_id}"}
> >
<%= artist.name %> {artist.name}
</.link> </.link>
<span class="text-sm md:text-base block text-zinc-600 dark:text-zinc-200"> <span class="text-sm md:text-base block text-zinc-600 dark:text-zinc-200">
<%= @record.title %> {@record.title}
</span> </span>
</p> </p>
</dd> </dd>
@@ -51,7 +51,7 @@ defmodule MusicLibraryWeb.StatsLive.DataComponents do
<div class="overflow-hidden rounded-md bg-white dark:bg-zinc-800 px-4 pb-3 pt-5 shadow sm:px-6 sm:pt-6"> <div class="overflow-hidden rounded-md bg-white dark:bg-zinc-800 px-4 pb-3 pt-5 shadow sm:px-6 sm:pt-6">
<dt> <dt>
<p class="truncate text-sm font-medium text-zinc-500 dark:text-zinc-400"> <p class="truncate text-sm font-medium text-zinc-500 dark:text-zinc-400">
<%= @title %> {@title}
</p> </p>
</dt> </dt>
<dd class="flex items-baseline mt-1 pb-6 sm:pb-7"> <dd class="flex items-baseline mt-1 pb-6 sm:pb-7">
@@ -59,7 +59,7 @@ defmodule MusicLibraryWeb.StatsLive.DataComponents do
href={@path} href={@path}
class="text-2xl font-semibold text-zinc-900 hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200" class="text-2xl font-semibold text-zinc-900 hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
> >
<%= @count %> {@count}
</a> </a>
</dd> </dd>
</div> </div>
@@ -1,6 +1,6 @@
<div> <div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold"> <h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
<%= gettext("Basics") %> {gettext("Basics")}
</h1> </h1>
<dl class="mt-5 grid grid-cols-2 gap-5 sm:grid-cols-5"> <dl class="mt-5 grid grid-cols-2 gap-5 sm:grid-cols-5">
<.album_preview <.album_preview
@@ -19,7 +19,7 @@
<div> <div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold"> <h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
<%= gettext("Formats") %> {gettext("Formats")}
</h1> </h1>
<dl class={[ <dl class={[
"mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x", "mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x",
@@ -27,14 +27,14 @@
]}> ]}>
<div :for={{format, count} <- @collection_count_by_format} class="px-2 py-5 sm:px-4"> <div :for={{format, count} <- @collection_count_by_format} class="px-2 py-5 sm:px-4">
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep"> <dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
<%= Record.format_long_label(format) %> {Record.format_long_label(format)}
</dt> </dt>
<dd class="mt-1 text-center"> <dd class="mt-1 text-center">
<a <a
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200" class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
href={~p"/collection?query=format:#{format}"} href={~p"/collection?query=format:#{format}"}
> >
<%= count %> {count}
</a> </a>
</dd> </dd>
</div> </div>
@@ -43,7 +43,7 @@
<div> <div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold"> <h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
<%= gettext("Types") %> {gettext("Types")}
</h1> </h1>
<dl class={[ <dl class={[
"mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x", "mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x",
@@ -51,14 +51,14 @@
]}> ]}>
<div :for={{type, count} <- @collection_count_by_type} class="px-2 py-5 sm:px-4"> <div :for={{type, count} <- @collection_count_by_type} class="px-2 py-5 sm:px-4">
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep"> <dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
<%= Record.type_long_label(type) %> {Record.type_long_label(type)}
</dt> </dt>
<dd class="mt-1 text-center"> <dd class="mt-1 text-center">
<a <a
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200" class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
href={~p"/collection?query=type:#{type}"} href={~p"/collection?query=type:#{type}"}
> >
<%= count %> {count}
</a> </a>
</dd> </dd>
</div> </div>
@@ -68,14 +68,14 @@
<div class="flow-root"> <div class="flow-root">
<div class="mt-5 flex justify-between items-center"> <div class="mt-5 flex justify-between items-center">
<h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold"> <h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
<%= gettext("Scrobble activity") %> {gettext("Scrobble activity")}
</h1> </h1>
<button <button
type="button" type="button"
class="phx-click-loading:animate-spin text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300" class="phx-click-loading:animate-spin text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300"
phx-click={JS.push("refresh_lastfm_feed")} phx-click={JS.push("refresh_lastfm_feed")}
> >
<span class="sr-only"><%= gettext("Refresh LastFm Feed") %></span> <span class="sr-only">{gettext("Refresh LastFm Feed")}</span>
<.icon name="hero-arrow-path" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" /> <.icon name="hero-arrow-path" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
</button> </button>
</div> </div>
@@ -97,19 +97,19 @@
<img class="h-12 w-12 rounded-md shadow" src={track.cover_url} alt={track.title} /> <img class="h-12 w-12 rounded-md shadow" src={track.cover_url} alt={track.title} />
<div> <div>
<p class="font-semibold text-sm block text-zinc-500 dark:text-zinc-400"> <p class="font-semibold text-sm block text-zinc-500 dark:text-zinc-400">
<%= track.artist.name %> {track.artist.name}
</p> </p>
<p class="font-semibold text-sm md:text-base text-zinc-700 dark:text-zinc-300"> <p class="font-semibold text-sm md:text-base text-zinc-700 dark:text-zinc-300">
<%= track.title %> {track.title}
</p> </p>
<p class="font-semibold text-sm text-zinc-500 dark:text-zinc-400"> <p class="font-semibold text-sm text-zinc-500 dark:text-zinc-400">
<%= track.album.title %> {track.album.title}
</p> </p>
<time <time
datetime={format_scrobbled_at_uts(track.scrobbled_at_uts)} datetime={format_scrobbled_at_uts(track.scrobbled_at_uts)}
class="whitespace-nowrap text-right text-xs sm:text-sm text-zinc-500 dark:text-zinc-400" class="whitespace-nowrap text-right text-xs sm:text-sm text-zinc-500 dark:text-zinc-400"
> >
<%= track.scrobbled_at_label %> {track.scrobbled_at_label}
</time> </time>
</div> </div>
</div> </div>
@@ -125,7 +125,7 @@
"ring-zinc-600/20 dark:ring-zinc-500/20" "ring-zinc-600/20 dark:ring-zinc-500/20"
]} ]}
> >
<%= gettext("No MB ID") %> {gettext("No MB ID")}
</span> </span>
<span <span
:if={track.album.musicbrainz_id in @collected_release_ids} :if={track.album.musicbrainz_id in @collected_release_ids}
@@ -138,7 +138,7 @@
"ring-green-600/20 dark:ring-green-500/20" "ring-green-600/20 dark:ring-green-500/20"
]} ]}
> >
<%= gettext("Collected") %> {gettext("Collected")}
</span> </span>
<span <span
:if={track.album.musicbrainz_id in @wishlisted_release_ids} :if={track.album.musicbrainz_id in @wishlisted_release_ids}
@@ -151,7 +151,7 @@
"ring-yellow-600/20 dark:ring-yellow-400/20" "ring-yellow-600/20 dark:ring-yellow-400/20"
]} ]}
> >
<%= gettext("Wishlisted") %> {gettext("Wishlisted")}
</span> </span>
<div <div
@@ -170,7 +170,7 @@
phx-click={toggle_actions_menu(track.scrobbled_at_uts)} phx-click={toggle_actions_menu(track.scrobbled_at_uts)}
phx-click-away={close_actions_menu(track.scrobbled_at_uts)} phx-click-away={close_actions_menu(track.scrobbled_at_uts)}
> >
<span class="sr-only"><%= gettext("Choose which format to import") %></span> <span class="sr-only">{gettext("Choose which format to import")}</span>
<.icon name="hero-star" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" /> <.icon name="hero-star" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
</button> </button>
<!-- <!--
@@ -206,7 +206,7 @@
) )
} }
> >
<%= Records.Record.format_long_label(format) %> {Records.Record.format_long_label(format)}
</.link> </.link>
</.focus_wrap> </.focus_wrap>
</div> </div>
@@ -14,17 +14,17 @@
/> />
</form> </form>
<.link patch={~p"/wishlist/import"}> <.link patch={~p"/wishlist/import"}>
<.button><%= gettext("Import") %></.button> <.button>{gettext("Import")}</.button>
</.link> </.link>
</div> </div>
</header> </header>
<p class="text-right text-sm max-sm:text-xs mt-8 text-zinc-900 dark:text-zinc-400"> <p class="text-right text-sm max-sm:text-xs mt-8 text-zinc-900 dark:text-zinc-400">
<%= gettext( {gettext(
"Showing <b>%{visible}</b> of <b>%{total}</b> records", "Showing <b>%{visible}</b> of <b>%{total}</b> records",
%{visible: Enum.count(@streams.records), total: @record_list_params.total_entries} %{visible: Enum.count(@streams.records), total: @record_list_params.total_entries}
) )
|> raw() %> |> raw()}
</p> </p>
</div> </div>
@@ -53,22 +53,22 @@
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/artists/#{artist.musicbrainz_id}"} patch={~p"/artists/#{artist.musicbrainz_id}"}
> >
<%= artist.name %> {artist.name}
</.link> </.link>
</h1> </h1>
<h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h2 class="mt-1 flex font-semibold text-sm sm:text-base leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= record.title %> {record.title}
</h2> </h2>
<p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400"> <p class="mt-1 text-xs leading-5 text-zinc-500 dark:text-zinc-400">
<%= Records.Record.format_release(record.release) %> {Records.Record.format_release(record.release)}
<span class="sm:hidden"> <span class="sm:hidden">
· <%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( · {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
<span :if={Records.Record.child_release_groups_count(record) > 0}> <span :if={Records.Record.child_release_groups_count(record) > 0}>
· ·
<span class="sr-only"> <span class="sr-only">
<%= gettext("Number of included records") %> {gettext("Number of included records")}
</span> </span>
<span class={[ <span class={[
"inline-flex items-center rounded-full", "inline-flex items-center rounded-full",
@@ -78,7 +78,7 @@
"text-gray-600 dark:text-gray-500", "text-gray-600 dark:text-gray-500",
"ring-gray-500/10 dark:ring-gray-400/20" "ring-gray-500/10 dark:ring-gray-400/20"
]}> ]}>
<%= Records.Record.child_release_groups_count(record) %> {Records.Record.child_release_groups_count(record)}
</span> </span>
</span> </span>
</span> </span>
@@ -88,13 +88,13 @@
<div class="flex shrink-0 items-center gap-x-6"> <div class="flex shrink-0 items-center gap-x-6">
<div class="hidden sm:flex sm:flex-col sm:items-end"> <div class="hidden sm:flex sm:flex-col sm:items-end">
<p class="text-xs leading-6 text-zinc-900 dark:text-zinc-300"> <p class="text-xs leading-6 text-zinc-900 dark:text-zinc-300">
<%= Records.Record.format_long_label(record.format) %> · <%= Records.Record.type_long_label( {Records.Record.format_long_label(record.format)} · {Records.Record.type_long_label(
record.type record.type
) %> )}
<span :if={Records.Record.child_release_groups_count(record) > 0}> <span :if={Records.Record.child_release_groups_count(record) > 0}>
· ·
<span class="sr-only"> <span class="sr-only">
<%= gettext("Number of included records") %> {gettext("Number of included records")}
</span> </span>
<span class={[ <span class={[
"inline-flex items-center rounded-full", "inline-flex items-center rounded-full",
@@ -104,7 +104,7 @@
"text-gray-600 dark:text-gray-500", "text-gray-600 dark:text-gray-500",
"ring-gray-500/10 dark:ring-gray-400/20" "ring-gray-500/10 dark:ring-gray-400/20"
]}> ]}>
<%= Records.Record.child_release_groups_count(record) %> {Records.Record.child_release_groups_count(record)}
</span> </span>
</span> </span>
</p> </p>
@@ -118,7 +118,7 @@
phx-click={toggle_actions_menu(record.id)} phx-click={toggle_actions_menu(record.id)}
phx-click-away={close_actions_menu(record.id)} phx-click-away={close_actions_menu(record.id)}
> >
<span class="sr-only"><%= gettext("Open options") %></span> <span class="sr-only">{gettext("Open options")}</span>
<.icon <.icon
name="hero-ellipsis-vertical" name="hero-ellipsis-vertical"
class="-mt-1 h-5 w-5" class="-mt-1 h-5 w-5"
@@ -153,7 +153,7 @@
id={"actions-#{record.id}-show"} id={"actions-#{record.id}-show"}
navigate={~p"/wishlist/#{record}"} navigate={~p"/wishlist/#{record}"}
> >
<%= gettext("Show") %> {gettext("Show")}
</.link> </.link>
<a <a
href={musicbrainz_url(record)} href={musicbrainz_url(record)}
@@ -163,7 +163,7 @@
tabindex="-1" tabindex="-1"
id={"actions-#{record.id}-musicbrainz"} id={"actions-#{record.id}-musicbrainz"}
> >
<%= gettext("View on MusicBrainz") %> {gettext("View on MusicBrainz")}
</a> </a>
<.link <.link
@@ -173,7 +173,7 @@
id={"actions-#{record.id}-edit"} id={"actions-#{record.id}-edit"}
patch={~p"/wishlist/#{record}/edit"} patch={~p"/wishlist/#{record}/edit"}
> >
<%= gettext("Edit") %> {gettext("Edit")}
</.link> </.link>
<.link <.link
@@ -183,7 +183,7 @@
id={"actions-#{record.id}-purchase"} id={"actions-#{record.id}-purchase"}
phx-click={JS.push("purchase", value: %{id: record.id})} phx-click={JS.push("purchase", value: %{id: record.id})}
> >
<%= gettext("Purchase") %> {gettext("Purchase")}
</.link> </.link>
<.link <.link
@@ -194,7 +194,7 @@
phx-click={JS.push("delete", value: %{id: record.id}) |> hide("##{id}")} phx-click={JS.push("delete", value: %{id: record.id}) |> hide("##{id}")}
data-confirm={gettext("Are you sure?")} data-confirm={gettext("Are you sure?")}
> >
<%= gettext("Delete") %> {gettext("Delete")}
</.link> </.link>
</.focus_wrap> </.focus_wrap>
</div> </div>
@@ -14,46 +14,46 @@
class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/artists/#{artist.musicbrainz_id}"} patch={~p"/artists/#{artist.musicbrainz_id}"}
> >
<%= artist.name %> {artist.name}
</.link> </.link>
</h1> </h1>
<h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap"> <h2 class="mt-1 flex font-semibold text-base sm:text-lg leading-5 text-zinc-700 dark:text-zinc-300 text-wrap">
<%= @record.title %> {@record.title}
</h2> </h2>
<p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400"> <p class="mt-2 text-sm leading-5 text-zinc-500 dark:text-zinc-400">
<%= Records.Record.format_release(@record.release) %> · <%= Records.Record.format_long_label( {Records.Record.format_release(@record.release)} · {Records.Record.format_long_label(
@record.format @record.format
) %> · <%= Records.Record.type_long_label(@record.type) %> )} · {Records.Record.type_long_label(@record.type)}
</p> </p>
<!-- TODO: extract to a component --> <!-- TODO: extract to a component -->
<nav class="mt-5 isolate inline-flex rounded-md shadow-sm"> <nav class="mt-5 isolate inline-flex rounded-md shadow-sm">
<.link patch={~p"/wishlist/#{@record}/show/edit"} phx-click={JS.push_focus()}> <.link patch={~p"/wishlist/#{@record}/show/edit"} phx-click={JS.push_focus()}>
<.button type="button" class="relative inline-flex items-center rounded-r-none"> <.button type="button" class="relative inline-flex items-center rounded-r-none">
<%= gettext("Edit") %> {gettext("Edit")}
</.button> </.button>
</.link> </.link>
<.link phx-click={JS.push("refresh_cover", value: %{id: @record.id})}> <.link phx-click={JS.push("refresh_cover", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none"> <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only"><%= gettext("Refresh") %></span> <span class="sr-only">{gettext("Refresh")}</span>
<.icon <.icon
name="hero-arrow-path" name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin" class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true" aria-hidden="true"
data-slot="icon" data-slot="icon"
/> />
<%= gettext("Cover") %> {gettext("Cover")}
</.button> </.button>
</.link> </.link>
<.link phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}> <.link phx-click={JS.push("refresh_musicbrainz_data", value: %{id: @record.id})}>
<.button type="button" class="relative -ml-px inline-flex items-center rounded-none"> <.button type="button" class="relative -ml-px inline-flex items-center rounded-none">
<span class="sr-only"><%= gettext("Refresh") %></span> <span class="sr-only">{gettext("Refresh")}</span>
<.icon <.icon
name="hero-arrow-path" name="hero-arrow-path"
class="h-4 w-4 mr-1 phx-click-loading:animate-spin" class="h-4 w-4 mr-1 phx-click-loading:animate-spin"
aria-hidden="true" aria-hidden="true"
data-slot="icon" data-slot="icon"
/> />
<%= gettext("MB Data") %> {gettext("MB Data")}
</.button> </.button>
</.link> </.link>
<.link <.link
@@ -64,7 +64,7 @@
type="button" type="button"
class="relative -ml-px inline-flex items-center rounded-l-none !text-red-600 hover:!text-red-500 dark:!text-red-700 hover:dark:!text-red-500" class="relative -ml-px inline-flex items-center rounded-l-none !text-red-600 hover:!text-red-500 dark:!text-red-700 hover:dark:!text-red-500"
> >
<%= gettext("Delete") %> {gettext("Delete")}
</.button> </.button>
</.link> </.link>
</nav> </nav>
@@ -75,7 +75,7 @@
<dl class="mt-4 divide-y divide-zinc-100 dark:divide-slate-300/30"> <dl class="mt-4 divide-y divide-zinc-100 dark:divide-slate-300/30">
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Genres") %> {gettext("Genres")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<.link <.link
@@ -83,23 +83,23 @@
class="mr-2 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300" class="mr-2 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"
patch={~p"/wishlist?#{%{query: ~s(genre:"#{genre}")}}"} patch={~p"/wishlist?#{%{query: ~s(genre:"#{genre}")}}"}
> >
<%= genre %> {genre}
</.link> </.link>
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("MusicBrainz ID") %> {gettext("MusicBrainz ID")}
</dt> </dt>
<dd class="mt-1 text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm flex justify-between leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<a href={musicbrainz_url(@record)}> <a href={musicbrainz_url(@record)}>
<code id={"mb-#{@record.musicbrainz_id}"}><%= @record.musicbrainz_id %></code> <code id={"mb-#{@record.musicbrainz_id}"}>{@record.musicbrainz_id}</code>
</a> </a>
<button phx-click={ <button phx-click={
JS.dispatch("music_library:clipcopy", to: "#mb-" <> @record.musicbrainz_id) JS.dispatch("music_library:clipcopy", to: "#mb-" <> @record.musicbrainz_id)
|> JS.transition("animate-shake") |> JS.transition("animate-shake")
}> }>
<span class="sr-only"><%= gettext("Copy MusicBrainz ID to clipboard") %></span> <span class="sr-only">{gettext("Copy MusicBrainz ID to clipboard")}</span>
<.icon <.icon
name="hero-clipboard-document" name="hero-clipboard-document"
class="-mt-1 h-5 w-5" class="-mt-1 h-5 w-5"
@@ -114,30 +114,30 @@
class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0" class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"
> >
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Includes") %> {gettext("Includes")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<ul> <ul>
<li :for={child_release_group <- Records.Record.child_release_groups(@record)}> <li :for={child_release_group <- Records.Record.child_release_groups(@record)}>
<%= child_release_group.artists %> - <%= child_release_group.title %> {child_release_group.artists} - {child_release_group.title}
</li> </li>
</ul> </ul>
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Inserted at") %> {gettext("Inserted at")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<%= human_datetime(@record.inserted_at) %> {human_datetime(@record.inserted_at)}
</dd> </dd>
</div> </div>
<div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <div class="py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
<dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400"> <dt class="text-sm font-medium leading-6 text-zinc-900 dark:text-zinc-400">
<%= gettext("Updated at") %> {gettext("Updated at")}
</dt> </dt>
<dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0"> <dd class="mt-1 text-sm leading-6 text-zinc-700 dark:text-zinc-300 sm:col-span-2 sm:mt-0">
<%= human_datetime(@record.updated_at) %> {human_datetime(@record.updated_at)}
</dd> </dd>
</div> </div>
</dl> </dl>
@@ -145,13 +145,13 @@
</div> </div>
<!-- TODO: extract to a component --> <!-- TODO: extract to a component -->
<details class="mt-4 px-4 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300"> <details class="mt-4 px-4 text-zinc-700 hover:text-zinc-500 dark:text-zinc-400 dark:hover:text-zinc-300">
<summary class="text-xs sm:text-sm"><%= gettext("MusicBrainz data") %></summary> <summary class="text-xs sm:text-sm">{gettext("MusicBrainz data")}</summary>
<pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre> <pre><code class="text-xs sm:text-sm"><%= Jason.encode!(@record.musicbrainz_data, pretty: true) %></code></pre>
</details> </details>
<div class="mt-4"> <div class="mt-4">
<.back navigate={@back_url}> <.back navigate={@back_url}>
<%= gettext("Back to wishlist") %> {gettext("Back to wishlist")}
</.back> </.back>
</div> </div>
@@ -30,22 +30,22 @@ defmodule MusicLibraryWeb.StatsLive.IndexTest do
conn: conn, conn: conn,
collection: collection collection: collection
} do } do
{:ok, _stats_live, html} = live(conn, "/") {:ok, stats_live, html} = live(conn, "/")
assert html =~ collection |> length() |> Integer.to_string() assert html =~ collection |> length() |> Integer.to_string()
collection collection
|> Enum.frequencies_by(& &1.format) |> Enum.frequencies_by(& &1.format)
|> Enum.each(fn {format, count} -> |> Enum.each(fn {format, count} ->
assert html =~ "\n#{count}\n" assert has_element?(stats_live, "a", to_string(count))
assert html =~ "\n#{Record.format_long_label(format)}\n" assert has_element?(stats_live, "dt", Record.format_long_label(format))
end) end)
collection collection
|> Enum.frequencies_by(& &1.type) |> Enum.frequencies_by(& &1.type)
|> Enum.each(fn {type, count} -> |> Enum.each(fn {type, count} ->
assert html =~ "\n#{count}\n" assert has_element?(stats_live, "a", to_string(count))
assert html =~ "\n#{Record.type_long_label(type)}\n" assert has_element?(stats_live, "dt", Record.type_long_label(type))
end) end)
end end