Files
music_library/lib/music_library_web/live/collection_live/index.ex
T
2024-11-27 11:11:36 +00:00

178 lines
4.9 KiB
Elixir

defmodule MusicLibraryWeb.CollectionLive.Index do
use MusicLibraryWeb, :live_view
import MusicLibraryWeb.Pagination
alias MusicLibrary.Records
alias MusicLibrary.Collection
alias MusicLibraryWeb.CollectionLive.Show
@default_records_list_params %{
query: "",
page: 1,
page_size: 100
}
@impl true
def mount(_params, _session, socket) do
socket =
if static_changed?(socket) do
put_flash(socket, :warning, gettext("The application has been updated, please reload."))
else
socket
end
{:ok, assign(socket, :nav_section, :records)}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :import, params) do
socket =
if get_in(socket.assigns, [:streams, :records]) == nil do
socket
|> apply_action(:index, params)
else
socket
end
socket
|> assign(:page_title, gettext("Import from MusicBrainz · Collection"))
|> assign(:record, nil)
end
defp apply_action(socket, :edit, params = %{"id" => id}) do
socket =
if get_in(socket.assigns, [:streams, :records]) == nil do
socket
|> apply_action(:index, params)
else
socket
end
record = Records.get_record!(id)
socket
|> assign(:page_title, Show.page_title(socket.assigns.live_action, record))
|> assign(:record, record)
end
defp apply_action(socket, :index, params) do
query = params["query"] || ""
total_records = Collection.search_records_count(query)
record_list_params =
@default_records_list_params
|> merge_query(query)
|> merge_pagination(params, total_records)
offset = page_to_offset(record_list_params.page, record_list_params.page_size)
records =
Collection.search_records(query, limit: record_list_params.page_size, offset: offset)
socket
|> assign(:page_title, gettext("Collection"))
|> assign(:record, nil)
|> assign(:record_list_params, record_list_params)
|> stream(:records, records, reset: true)
end
@impl true
def handle_info({MusicLibraryWeb.RecordLive.FormComponent, {:saved, record}}, socket) do
{:noreply, stream_insert(socket, :records, record)}
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
record = Records.get_record!(id)
{:ok, _} = Records.delete_record(record)
{:noreply, stream_delete(socket, :records, record)}
end
def handle_event("search", %{"query" => query}, socket) do
qs =
@default_records_list_params
|> Map.put(:query, query)
|> Map.take([:query, :page, :page_size])
{:noreply, push_patch(socket, to: ~p"/collection?#{qs}")}
end
def handle_event("import", %{"id" => musicbrainz_id, "format" => format}, socket) do
current_time = DateTime.utc_now()
case Records.import_from_musicbrainz_release_group(musicbrainz_id,
format: format,
purchased_at: current_time
) do
{:ok, record} ->
{:noreply,
socket
|> put_flash(:info, gettext("Record imported successfully"))
|> push_navigate(to: ~p"/collection/#{record.id}")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply,
socket
|> put_flash(
:error,
gettext("Error importing record") <> "," <> inspect(changeset.errors)
)
|> push_patch(to: ~p"/collection")}
{:error, reason} ->
{:noreply,
socket
|> put_flash(:error, gettext("Error importing record") <> "," <> inspect(reason))
|> push_patch(to: ~p"/collection")}
end
end
defp merge_query(record_list_params, query) do
Map.put(record_list_params, :query, query)
end
defp merge_pagination(record_list_params, params, total_records) do
record_list_params
|> Map.put(:page, parse_int_or_default(params["page"], record_list_params.page))
|> Map.put(
:page_size,
parse_int_or_default(params["page_size"], record_list_params.page_size)
)
|> Map.put(:total_entries, total_records)
end
defp parse_int_or_default(nil, default), do: default
defp parse_int_or_default(value, _default) when is_binary(value) do
String.to_integer(value)
end
defp back_path(record_list_params) do
qs =
record_list_params
|> Map.take([:query, :page, :page_size])
|> Enum.filter(fn {_, v} -> v not in ["", nil] end)
~p"/collection?#{qs}"
end
defp musicbrainz_url(record) do
"https://musicbrainz.org/release-group/#{record.musicbrainz_id}"
end
defp toggle_actions_menu(record_id) do
JS.toggle(to: "#actions-#{record_id}")
|> JS.toggle_class("pointer-events-none", to: "#records > li")
end
def close_actions_menu(record_id) do
JS.hide(to: "#actions-#{record_id}")
|> JS.remove_class("pointer-events-none", to: "#records > li")
end
end