@@ -279,6 +279,7 @@ All authenticated routes live inside a single `live_session` with three `on_moun
|
|||||||
|
|
||||||
| Module | Purpose |
|
| Module | Purpose |
|
||||||
|--------|---------|
|
|--------|---------|
|
||||||
|
| `ErrorMessages` | Maps internal error terms (atoms, structs) to user-friendly gettext strings via `friendly_message/1` |
|
||||||
| `Markdown` | Markdown-to-HTML conversion with `[[double bracket]]` link syntax |
|
| `Markdown` | Markdown-to-HTML conversion with `[[double bracket]]` link syntax |
|
||||||
| `Duration` | Milliseconds to human-readable duration formatting |
|
| `Duration` | Milliseconds to human-readable duration formatting |
|
||||||
| `LiveHelpers.Params` | Pagination param parsing from URL query params |
|
| `LiveHelpers.Params` | Pagination param parsing from URL query params |
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Rules extracted from commit history that are specific to this project and not al
|
|||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
||||||
- **Toast notifications:** `put_toast/3` (arity 3) in LiveViews, `put_toast!/2` (arity 2) in LiveComponents. `:info` for success, `:error` for failures.
|
- **Toast notifications:** `put_toast/3` (arity 3) in LiveViews, `put_toast!/2` (arity 2) in LiveComponents. `:info` for success, `:error` for failures.
|
||||||
|
- **User-facing error reasons use `ErrorMessages.friendly_message/1`** — never `inspect(reason)`. Call sites keep their contextual prefix (e.g. `gettext("Error refreshing cover")`) and append `": " <> ErrorMessages.friendly_message(reason)` for the reason part. `Logger.error` calls keep `inspect` for debugging.
|
||||||
- **`handle_async` always handles three cases:** `{:ok, {:ok, result}}`, `{:ok, {:error, reason}}`, and `{:exit, reason}`.
|
- **`handle_async` always handles three cases:** `{:ok, {:ok, result}}`, `{:ok, {:error, reason}}`, and `{:exit, reason}`.
|
||||||
- **Data cascade on upstream changes:** When artist metadata changes, regenerate dependent record embeddings.
|
- **Data cascade on upstream changes:** When artist metadata changes, regenerate dependent record embeddings.
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ defmodule MusicLibraryWeb.Components.BarcodeScanner do
|
|||||||
alias MusicBrainz.ReleaseGroupSearchResult
|
alias MusicBrainz.ReleaseGroupSearchResult
|
||||||
alias MusicLibrary.BarcodeScan
|
alias MusicLibrary.BarcodeScan
|
||||||
alias MusicLibrary.Records
|
alias MusicLibrary.Records
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
alias MusicLibraryWeb.RecordComponents
|
alias MusicLibraryWeb.RecordComponents
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
@@ -410,7 +411,7 @@ defmodule MusicLibraryWeb.Components.BarcodeScanner do
|
|||||||
errors ->
|
errors ->
|
||||||
errors_summary =
|
errors_summary =
|
||||||
Enum.map_join(errors, "\n", fn {number, reason} ->
|
Enum.map_join(errors, "\n", fn {number, reason} ->
|
||||||
"#{number}: #{inspect(reason)}"
|
"#{number}: #{ErrorMessages.friendly_message(reason)}"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
put_toast(
|
put_toast(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ defmodule MusicLibraryWeb.Components.RecordForm do
|
|||||||
alias MusicLibrary.{Assets, Records}
|
alias MusicLibrary.{Assets, Records}
|
||||||
alias MusicLibrary.Assets.Image
|
alias MusicLibrary.Assets.Image
|
||||||
alias MusicLibrary.Records.Record
|
alias MusicLibrary.Records.Record
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
@@ -538,14 +539,20 @@ defmodule MusicLibraryWeb.Components.RecordForm do
|
|||||||
def handle_async(:cover_search, {:ok, {:error, reason}}, socket) do
|
def handle_async(:cover_search, {:ok, {:error, reason}}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:cover_search_error, "Search failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:cover_search_error,
|
||||||
|
gettext("Search failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:cover_search_loading, false)}
|
|> assign(:cover_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_async(:cover_search, {:exit, reason}, socket) do
|
def handle_async(:cover_search, {:exit, reason}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:cover_search_error, "Search failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:cover_search_error,
|
||||||
|
gettext("Search failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:cover_search_loading, false)}
|
|> assign(:cover_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -571,14 +578,20 @@ defmodule MusicLibraryWeb.Components.RecordForm do
|
|||||||
def handle_async(:cover_download, {:ok, {:error, reason}}, socket) do
|
def handle_async(:cover_download, {:ok, {:error, reason}}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:cover_search_error, "Download failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:cover_search_error,
|
||||||
|
gettext("Download failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:cover_search_loading, false)}
|
|> assign(:cover_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_async(:cover_download, {:exit, reason}, socket) do
|
def handle_async(:cover_download, {:exit, reason}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:cover_search_error, "Download failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:cover_search_error,
|
||||||
|
gettext("Download failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:cover_search_loading, false)}
|
|> assign(:cover_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ defmodule MusicLibraryWeb.Components.Release do
|
|||||||
alias MusicBrainz.Release
|
alias MusicBrainz.Release
|
||||||
alias MusicLibrary.ScrobbleActivity
|
alias MusicLibrary.ScrobbleActivity
|
||||||
alias MusicLibraryWeb.Duration
|
alias MusicLibraryWeb.Duration
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
alias Phoenix.LiveView.AsyncResult
|
alias Phoenix.LiveView.AsyncResult
|
||||||
|
|
||||||
def open(id), do: Fluxon.open_dialog(id)
|
def open(id), do: Fluxon.open_dialog(id)
|
||||||
@@ -267,7 +268,7 @@ defmodule MusicLibraryWeb.Components.Release do
|
|||||||
|
|
||||||
put_toast!(
|
put_toast!(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling release") <> "," <> inspect(reason)
|
gettext("Error scrobbling release") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)
|
)
|
||||||
|
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
@@ -298,7 +299,7 @@ defmodule MusicLibraryWeb.Components.Release do
|
|||||||
|
|
||||||
put_toast!(
|
put_toast!(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling disc") <> "," <> inspect(reason)
|
gettext("Error scrobbling disc") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)
|
)
|
||||||
|
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
@@ -372,7 +373,8 @@ defmodule MusicLibraryWeb.Components.Release do
|
|||||||
|
|
||||||
put_toast!(
|
put_toast!(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling selected tracks") <> "," <> inspect(reason)
|
gettext("Error scrobbling selected tracks") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)
|
)
|
||||||
|
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
defmodule MusicLibraryWeb.ErrorMessages do
|
||||||
|
@moduledoc """
|
||||||
|
Maps internal error terms to user-friendly messages.
|
||||||
|
|
||||||
|
Used at call sites that previously showed `inspect(reason)` in toasts or assigns.
|
||||||
|
Each call site keeps its own contextual prefix (e.g. "Error refreshing cover")
|
||||||
|
and appends `": " <> friendly_message(reason)` for the reason part.
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Gettext, backend: MusicLibraryWeb.Gettext
|
||||||
|
|
||||||
|
# App error atoms
|
||||||
|
def friendly_message(:cover_not_available), do: gettext("cover art is not available")
|
||||||
|
def friendly_message(:no_duration), do: gettext("release has no track duration information")
|
||||||
|
def friendly_message(:medium_not_found), do: gettext("the specified disc was not found")
|
||||||
|
def friendly_message(:no_session_key), do: gettext("Last.fm session key is not configured")
|
||||||
|
|
||||||
|
def friendly_message(:already_collected),
|
||||||
|
do: gettext("this record is already in your collection")
|
||||||
|
|
||||||
|
def friendly_message(:not_found), do: gettext("the resource was not found")
|
||||||
|
def friendly_message(:no_discogs_data), do: gettext("no Discogs profile available")
|
||||||
|
def friendly_message(:image_not_found), do: gettext("no image could be found")
|
||||||
|
def friendly_message(:invalid_parameters), do: gettext("invalid parameters were provided")
|
||||||
|
def friendly_message(:download_failed), do: gettext("the download failed")
|
||||||
|
|
||||||
|
# Last.fm API error atoms
|
||||||
|
def friendly_message(:authentication_failed), do: gettext("Last.fm authentication failed")
|
||||||
|
|
||||||
|
def friendly_message(:invalid_session_key),
|
||||||
|
do: gettext("Last.fm session has expired, please reconnect")
|
||||||
|
|
||||||
|
def friendly_message(:invalid_api_key), do: gettext("Last.fm API key is invalid")
|
||||||
|
def friendly_message(:suspended_api_key), do: gettext("Last.fm API key has been suspended")
|
||||||
|
|
||||||
|
def friendly_message(:rate_limit_exceeded),
|
||||||
|
do: gettext("rate limit exceeded, please try again later")
|
||||||
|
|
||||||
|
def friendly_message(:service_offline),
|
||||||
|
do: gettext("service is currently offline, please try again later")
|
||||||
|
|
||||||
|
def friendly_message(:transient_error),
|
||||||
|
do: gettext("a temporary error occurred, please try again")
|
||||||
|
|
||||||
|
def friendly_message(:operation_failed), do: gettext("the operation failed, please try again")
|
||||||
|
|
||||||
|
def friendly_message(:invalid_resource),
|
||||||
|
do: gettext("the requested resource does not exist")
|
||||||
|
|
||||||
|
# Structured errors
|
||||||
|
def friendly_message(%Req.TransportError{reason: :timeout}),
|
||||||
|
do: gettext("the request timed out, please try again")
|
||||||
|
|
||||||
|
def friendly_message(%Req.TransportError{reason: :econnrefused}),
|
||||||
|
do: gettext("the service is not reachable")
|
||||||
|
|
||||||
|
def friendly_message(%Req.TransportError{reason: :nxdomain}),
|
||||||
|
do: gettext("the service could not be found")
|
||||||
|
|
||||||
|
def friendly_message(%Req.TransportError{}),
|
||||||
|
do: gettext("a connection error occurred, please try again")
|
||||||
|
|
||||||
|
def friendly_message(%Ecto.Changeset{}), do: gettext("validation failed")
|
||||||
|
|
||||||
|
# Fallback
|
||||||
|
def friendly_message(_), do: gettext("something went wrong, please try again")
|
||||||
|
end
|
||||||
@@ -6,6 +6,7 @@ defmodule MusicLibraryWeb.ArtistLive.Form do
|
|||||||
alias MusicLibrary.Artists
|
alias MusicLibrary.Artists
|
||||||
alias MusicLibrary.Assets
|
alias MusicLibrary.Assets
|
||||||
alias MusicLibrary.Assets.Image
|
alias MusicLibrary.Assets.Image
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
@@ -249,14 +250,20 @@ defmodule MusicLibraryWeb.ArtistLive.Form do
|
|||||||
def handle_async(:image_search, {:ok, {:error, reason}}, socket) do
|
def handle_async(:image_search, {:ok, {:error, reason}}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:image_search_error, "Search failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:image_search_error,
|
||||||
|
gettext("Search failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:image_search_loading, false)}
|
|> assign(:image_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_async(:image_search, {:exit, reason}, socket) do
|
def handle_async(:image_search, {:exit, reason}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:image_search_error, "Search failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:image_search_error,
|
||||||
|
gettext("Search failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:image_search_loading, false)}
|
|> assign(:image_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -283,14 +290,20 @@ defmodule MusicLibraryWeb.ArtistLive.Form do
|
|||||||
def handle_async(:image_download, {:ok, {:error, reason}}, socket) do
|
def handle_async(:image_download, {:ok, {:error, reason}}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:image_search_error, "Download failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:image_search_error,
|
||||||
|
gettext("Download failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:image_search_loading, false)}
|
|> assign(:image_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_async(:image_download, {:exit, reason}, socket) do
|
def handle_async(:image_download, {:exit, reason}, socket) do
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:image_search_error, "Download failed: #{inspect(reason)}")
|
|> assign(
|
||||||
|
:image_search_error,
|
||||||
|
gettext("Download failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)
|
||||||
|> assign(:image_search_loading, false)}
|
|> assign(:image_search_loading, false)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
|
|
||||||
alias MusicLibrary.{Artists, Records}
|
alias MusicLibrary.{Artists, Records}
|
||||||
alias MusicLibrary.Artists.ArtistInfo
|
alias MusicLibrary.Artists.ArtistInfo
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
attr :country, :map, required: true
|
attr :country, :map, required: true
|
||||||
|
|
||||||
@@ -544,7 +545,8 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing artist info") <> "," <> inspect(reason)
|
gettext("Error refreshing artist info") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -563,7 +565,8 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing Wikipedia data") <> "," <> inspect(reason)
|
gettext("Error refreshing Wikipedia data") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -585,7 +588,8 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing Last.fm data") <> "," <> inspect(reason)
|
gettext("Error refreshing Last.fm data") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -603,7 +607,8 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing artist image") <> "," <> inspect(reason)
|
gettext("Error refreshing artist image") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -624,7 +629,7 @@ defmodule MusicLibraryWeb.ArtistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error importing record") <> "," <> inspect(changeset.errors)
|
gettext("Error importing record") <> ": " <> ErrorMessages.friendly_message(changeset)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ defmodule MusicLibraryWeb.CollectionLive.Index do
|
|||||||
alias MusicLibrary.Collection
|
alias MusicLibrary.Collection
|
||||||
alias MusicLibrary.Records
|
alias MusicLibrary.Records
|
||||||
alias MusicLibraryWeb.CollectionLive.Show
|
alias MusicLibraryWeb.CollectionLive.Show
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@default_records_list_params %{
|
@default_records_list_params %{
|
||||||
query: "",
|
query: "",
|
||||||
@@ -272,20 +273,14 @@ defmodule MusicLibraryWeb.CollectionLive.Index do
|
|||||||
|> put_toast(:info, gettext("Record imported successfully"))
|
|> put_toast(:info, gettext("Record imported successfully"))
|
||||||
|> push_navigate(to: ~p"/collection/#{record.id}")}
|
|> push_navigate(to: ~p"/collection/#{record.id}")}
|
||||||
|
|
||||||
{:error, %Ecto.Changeset{} = changeset} ->
|
{:error, reason} ->
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error importing record") <> "," <> inspect(changeset.errors)
|
gettext("Error importing record") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)
|
)
|
||||||
|> push_patch(to: ~p"/collection")}
|
|> push_patch(to: ~p"/collection")}
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> put_toast(:error, gettext("Error importing record") <> "," <> inspect(reason))
|
|
||||||
|> push_patch(to: ~p"/collection")}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
|
|
||||||
alias MusicLibrary.{Records, RecordSets, ScrobbleActivity}
|
alias MusicLibrary.{Records, RecordSets, ScrobbleActivity}
|
||||||
alias MusicLibrary.Records.Similarity
|
alias MusicLibrary.Records.Similarity
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
alias Phoenix.LiveView.JS
|
alias Phoenix.LiveView.JS
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -370,7 +371,8 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing MusicBrainz data") <> "," <> inspect(reason)
|
gettext("Error refreshing MusicBrainz data") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -389,7 +391,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error") <> "," <> inspect(reason)
|
gettext("Error") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -409,7 +411,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing cover") <> "," <> inspect(reason)
|
gettext("Error refreshing cover") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -429,7 +431,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error extracting colors") <> ": " <> inspect(reason)
|
gettext("Error extracting colors") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -448,7 +450,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error") <> "," <> inspect(reason)
|
gettext("Error") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do
|
|||||||
alias MusicLibrary.Artists
|
alias MusicLibrary.Artists
|
||||||
alias MusicLibrary.Maintenance
|
alias MusicLibrary.Maintenance
|
||||||
alias MusicLibrary.Records
|
alias MusicLibrary.Records
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@poll_interval 2_000
|
@poll_interval 2_000
|
||||||
|
|
||||||
@@ -268,7 +269,10 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do
|
|||||||
|
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_toast(:error, "Database vacuum failed: #{inspect(reason)}.")}
|
|> put_toast(
|
||||||
|
:error,
|
||||||
|
gettext("Database vacuum failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -284,7 +288,10 @@ defmodule MusicLibraryWeb.MaintenanceLive.Index do
|
|||||||
|
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_toast(:error, "Database optimize failed: #{inspect(reason)}.")}
|
|> put_toast(
|
||||||
|
:error,
|
||||||
|
gettext("Database optimize failed") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Show do
|
|||||||
import MusicLibraryWeb.RecordComponents, only: [country_label: 1]
|
import MusicLibraryWeb.RecordComponents, only: [country_label: 1]
|
||||||
|
|
||||||
alias MusicLibrary.ScrobbleActivity
|
alias MusicLibrary.ScrobbleActivity
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
@@ -156,7 +157,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling release") <> "," <> inspect(reason)
|
gettext("Error scrobbling release") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -177,7 +178,7 @@ defmodule MusicLibraryWeb.ScrobbleLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling disc") <> "," <> inspect(reason)
|
gettext("Error scrobbling disc") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -205,7 +206,8 @@ defmodule MusicLibraryWeb.ScrobbleLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error scrobbling selected tracks") <> "," <> inspect(reason)
|
gettext("Error scrobbling selected tracks") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
|
|||||||
|
|
||||||
alias MusicLibrary.Assets.Transform
|
alias MusicLibrary.Assets.Transform
|
||||||
alias MusicLibrary.{Collection, ListeningStats, Records, Wishlist}
|
alias MusicLibrary.{Collection, ListeningStats, Records, Wishlist}
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
alias MusicLibraryWeb.StatsLive.{TopAlbums, TopArtists}
|
alias MusicLibraryWeb.StatsLive.{TopAlbums, TopArtists}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -392,18 +393,13 @@ defmodule MusicLibraryWeb.StatsLive.Index do
|
|||||||
|> put_toast(:info, gettext("Record wishlisted successfully"))
|
|> put_toast(:info, gettext("Record wishlisted successfully"))
|
||||||
|> push_navigate(to: ~p"/wishlist/#{record.id}")}
|
|> push_navigate(to: ~p"/wishlist/#{record.id}")}
|
||||||
|
|
||||||
{:error, %Ecto.Changeset{} = changeset} ->
|
{:error, reason} ->
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error wishlisting record") <> "," <> inspect(changeset.errors)
|
gettext("Error wishlisting record") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> put_toast(:error, gettext("Error wishlisting record") <> "," <> inspect(reason))}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ defmodule MusicLibraryWeb.WishlistLive.Index do
|
|||||||
|
|
||||||
alias MusicLibrary.Records
|
alias MusicLibrary.Records
|
||||||
alias MusicLibrary.Wishlist
|
alias MusicLibrary.Wishlist
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
alias MusicLibraryWeb.WishlistLive.Show
|
alias MusicLibraryWeb.WishlistLive.Show
|
||||||
|
|
||||||
@default_records_list_params %{
|
@default_records_list_params %{
|
||||||
@@ -242,20 +243,14 @@ defmodule MusicLibraryWeb.WishlistLive.Index do
|
|||||||
|> put_toast(:info, gettext("Record wishlisted successfully"))
|
|> put_toast(:info, gettext("Record wishlisted successfully"))
|
||||||
|> push_navigate(to: ~p"/wishlist/#{record.id}")}
|
|> push_navigate(to: ~p"/wishlist/#{record.id}")}
|
||||||
|
|
||||||
{:error, %Ecto.Changeset{} = changeset} ->
|
{:error, reason} ->
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error wishlisting record") <> "," <> inspect(changeset.errors)
|
gettext("Error wishlisting record") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)
|
)
|
||||||
|> push_patch(to: ~p"/wishlist")}
|
|> push_patch(to: ~p"/wishlist")}
|
||||||
|
|
||||||
{:error, reason} ->
|
|
||||||
{:noreply,
|
|
||||||
socket
|
|
||||||
|> put_toast(:error, gettext("Error wishlisting record") <> "," <> inspect(reason))
|
|
||||||
|> push_patch(to: ~p"/wishlist")}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
alias MusicLibrary.OnlineStoreTemplates
|
alias MusicLibrary.OnlineStoreTemplates
|
||||||
alias MusicLibrary.{Records, RecordSets}
|
alias MusicLibrary.{Records, RecordSets}
|
||||||
alias MusicLibrary.Records.Similarity
|
alias MusicLibrary.Records.Similarity
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
@@ -319,7 +320,8 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing MusicBrainz data") <> "," <> inspect(reason)
|
gettext("Error refreshing MusicBrainz data") <>
|
||||||
|
": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -339,7 +341,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error refreshing Cover") <> "," <> inspect(reason)
|
gettext("Error refreshing cover") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -358,7 +360,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error") <> "," <> inspect(reason)
|
gettext("Error") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -394,7 +396,7 @@ defmodule MusicLibraryWeb.WishlistLive.Show do
|
|||||||
socket
|
socket
|
||||||
|> put_toast(
|
|> put_toast(
|
||||||
:error,
|
:error,
|
||||||
gettext("Error extracting colors") <> ": " <> inspect(reason)
|
gettext("Error extracting colors") <> ": " <> ErrorMessages.friendly_message(reason)
|
||||||
)}
|
)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+148
-5
@@ -279,12 +279,8 @@ msgstr ""
|
|||||||
msgid "Cover refreshed successfully"
|
msgid "Cover refreshed successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/wishlist_live/show.ex
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Error refreshing Cover"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/music_library_web/live/collection_live/show.ex
|
#: lib/music_library_web/live/collection_live/show.ex
|
||||||
|
#: lib/music_library_web/live/wishlist_live/show.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Error refreshing cover"
|
msgid "Error refreshing cover"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2069,3 +2065,150 @@ msgstr ""
|
|||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Extract colors"
|
msgid "Extract colors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/live/maintenance_live/index.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Database optimize failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/live/maintenance_live/index.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Database vacuum failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/components/record_form.ex
|
||||||
|
#: lib/music_library_web/live/artist_live/form.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Download failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm API key has been suspended"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm API key is invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm authentication failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm session has expired, please reconnect"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm session key is not configured"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/components/record_form.ex
|
||||||
|
#: lib/music_library_web/live/artist_live/form.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Search failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "a connection error occurred, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "a temporary error occurred, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "cover art is not available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "invalid parameters were provided"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "no Discogs profile available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "no image could be found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "rate limit exceeded, please try again later"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "release has no track duration information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "service is currently offline, please try again later"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "something went wrong, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the download failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the operation failed, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the request timed out, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the requested resource does not exist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the resource was not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the service could not be found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the service is not reachable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the specified disc was not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "this record is already in your collection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "validation failed"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -279,12 +279,8 @@ msgstr ""
|
|||||||
msgid "Cover refreshed successfully"
|
msgid "Cover refreshed successfully"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/wishlist_live/show.ex
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Error refreshing Cover"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/music_library_web/live/collection_live/show.ex
|
#: lib/music_library_web/live/collection_live/show.ex
|
||||||
|
#: lib/music_library_web/live/wishlist_live/show.ex
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Error refreshing cover"
|
msgid "Error refreshing cover"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -2069,3 +2065,150 @@ msgstr ""
|
|||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Extract colors"
|
msgid "Extract colors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/live/maintenance_live/index.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Database optimize failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/live/maintenance_live/index.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Database vacuum failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/components/record_form.ex
|
||||||
|
#: lib/music_library_web/live/artist_live/form.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Download failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm API key has been suspended"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm API key is invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm authentication failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm session has expired, please reconnect"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Last.fm session key is not configured"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/components/record_form.ex
|
||||||
|
#: lib/music_library_web/live/artist_live/form.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Search failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "a connection error occurred, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "a temporary error occurred, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "cover art is not available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "invalid parameters were provided"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "no Discogs profile available"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "no image could be found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "rate limit exceeded, please try again later"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "release has no track duration information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "service is currently offline, please try again later"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "something went wrong, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the download failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the operation failed, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the request timed out, please try again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the requested resource does not exist"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the resource was not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the service could not be found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the service is not reachable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "the specified disc was not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "this record is already in your collection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/music_library_web/error_messages.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "validation failed"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
defmodule MusicLibraryWeb.ErrorMessagesTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
alias MusicLibraryWeb.ErrorMessages
|
||||||
|
|
||||||
|
describe "friendly_message/1" do
|
||||||
|
test "maps known app error atoms" do
|
||||||
|
assert ErrorMessages.friendly_message(:cover_not_available) == "cover art is not available"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:no_duration) ==
|
||||||
|
"release has no track duration information"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:medium_not_found) ==
|
||||||
|
"the specified disc was not found"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:no_session_key) ==
|
||||||
|
"Last.fm session key is not configured"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:already_collected) ==
|
||||||
|
"this record is already in your collection"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:not_found) == "the resource was not found"
|
||||||
|
assert ErrorMessages.friendly_message(:no_discogs_data) == "no Discogs profile available"
|
||||||
|
assert ErrorMessages.friendly_message(:image_not_found) == "no image could be found"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:invalid_parameters) ==
|
||||||
|
"invalid parameters were provided"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:download_failed) == "the download failed"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "maps Last.fm API error atoms" do
|
||||||
|
assert ErrorMessages.friendly_message(:authentication_failed) ==
|
||||||
|
"Last.fm authentication failed"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:invalid_session_key) ==
|
||||||
|
"Last.fm session has expired, please reconnect"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:invalid_api_key) == "Last.fm API key is invalid"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:suspended_api_key) ==
|
||||||
|
"Last.fm API key has been suspended"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:rate_limit_exceeded) ==
|
||||||
|
"rate limit exceeded, please try again later"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:service_offline) ==
|
||||||
|
"service is currently offline, please try again later"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:transient_error) ==
|
||||||
|
"a temporary error occurred, please try again"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:operation_failed) ==
|
||||||
|
"the operation failed, please try again"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(:invalid_resource) ==
|
||||||
|
"the requested resource does not exist"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "maps Req.TransportError with common reasons" do
|
||||||
|
assert ErrorMessages.friendly_message(%Req.TransportError{reason: :timeout}) ==
|
||||||
|
"the request timed out, please try again"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(%Req.TransportError{reason: :econnrefused}) ==
|
||||||
|
"the service is not reachable"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(%Req.TransportError{reason: :nxdomain}) ==
|
||||||
|
"the service could not be found"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message(%Req.TransportError{reason: :closed}) ==
|
||||||
|
"a connection error occurred, please try again"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "maps Ecto.Changeset" do
|
||||||
|
changeset = Ecto.Changeset.change(%MusicLibrary.Records.Record{})
|
||||||
|
assert ErrorMessages.friendly_message(changeset) == "validation failed"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns fallback for unknown terms" do
|
||||||
|
assert ErrorMessages.friendly_message(:unknown_error) ==
|
||||||
|
"something went wrong, please try again"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message("some string") ==
|
||||||
|
"something went wrong, please try again"
|
||||||
|
|
||||||
|
assert ErrorMessages.friendly_message({:complex, :term}) ==
|
||||||
|
"something went wrong, please try again"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user