Start extracting a Collection context
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
defmodule MusicLibrary.Collection do
|
||||||
|
import Ecto.Query, warn: false
|
||||||
|
|
||||||
|
alias MusicLibrary.Repo
|
||||||
|
alias MusicLibrary.Records
|
||||||
|
alias MusicLibrary.Records.Record
|
||||||
|
|
||||||
|
def search_records(query, opts \\ []) do
|
||||||
|
limit = Keyword.get(opts, :limit, 20)
|
||||||
|
offset = Keyword.get(opts, :offset, 0)
|
||||||
|
|
||||||
|
Records.search_records(base_search(), query, limit: limit, offset: offset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_records_count(query) do
|
||||||
|
Records.search_records_count(base_search(), query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_records_by_format do
|
||||||
|
q =
|
||||||
|
from r in base_search(),
|
||||||
|
group_by: r.format,
|
||||||
|
order_by: [desc: count(r.id)],
|
||||||
|
select: {r.format, count(r.id)}
|
||||||
|
|
||||||
|
Repo.all(q)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count_records_by_type do
|
||||||
|
q =
|
||||||
|
from r in base_search(),
|
||||||
|
group_by: r.type,
|
||||||
|
order_by: [desc: count(r.id)],
|
||||||
|
select: {r.type, count(r.id)}
|
||||||
|
|
||||||
|
Repo.all(q)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_latest_record! do
|
||||||
|
fields = Records.minimal_record_fields()
|
||||||
|
|
||||||
|
q =
|
||||||
|
from r in base_search(),
|
||||||
|
order_by: [desc: r.purchased_at],
|
||||||
|
limit: 1,
|
||||||
|
select: ^fields
|
||||||
|
|
||||||
|
Repo.one!(q)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp base_search do
|
||||||
|
from r in Record,
|
||||||
|
where: not is_nil(r.purchased_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -6,13 +6,15 @@ defmodule MusicLibrary.Records do
|
|||||||
|
|
||||||
@fields [:id, :type, :artists, :format, :title, :release, :genres, :musicbrainz_id, :cover_hash]
|
@fields [:id, :type, :artists, :format, :title, :release, :genres, :musicbrainz_id, :cover_hash]
|
||||||
|
|
||||||
def search_records(query, opts \\ []) do
|
def minimal_record_fields, do: @fields
|
||||||
limit = Keyword.get(opts, :limit, 20)
|
|
||||||
offset = Keyword.get(opts, :offset, 0)
|
def search_records(initial_search, query, opts) do
|
||||||
|
limit = Keyword.fetch!(opts, :limit)
|
||||||
|
offset = Keyword.fetch!(opts, :offset)
|
||||||
|
|
||||||
search =
|
search =
|
||||||
query
|
initial_search
|
||||||
|> build_search()
|
|> build_search(query)
|
||||||
|> limit(^limit)
|
|> limit(^limit)
|
||||||
|> offset(^offset)
|
|> offset(^offset)
|
||||||
|> select(^@fields)
|
|> select(^@fields)
|
||||||
@@ -20,24 +22,24 @@ defmodule MusicLibrary.Records do
|
|||||||
Repo.all(search)
|
Repo.all(search)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_records_count(query) do
|
def search_records_count(initial_search, query) do
|
||||||
search = build_search(query)
|
search = build_search(initial_search, query)
|
||||||
|
|
||||||
Repo.aggregate(search, :count)
|
Repo.aggregate(search, :count)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_search(query) do
|
defp build_search(initial_search, query) do
|
||||||
{:ok, parsed_query} = SearchParser.parse(query)
|
{:ok, parsed_query} = SearchParser.parse(query)
|
||||||
|
|
||||||
base_search =
|
search_with_order =
|
||||||
from r in Record,
|
initial_search
|
||||||
where: not is_nil(r.purchased_at),
|
|> order_by(
|
||||||
order_by:
|
fragment(
|
||||||
fragment(
|
"json_extract(artists, '$[0].sort_name') COLLATE NOCASE ASC, title COLLATE NOCASE ASC"
|
||||||
"json_extract(artists, '$[0].sort_name') COLLATE NOCASE ASC, title COLLATE NOCASE ASC"
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Enum.reduce(parsed_query, base_search, fn
|
Enum.reduce(parsed_query, search_with_order, fn
|
||||||
{:artist, artist}, search ->
|
{:artist, artist}, search ->
|
||||||
search |> where([r], like(r.artists, ^"%#{artist}%"))
|
search |> where([r], like(r.artists, ^"%#{artist}%"))
|
||||||
|
|
||||||
@@ -62,41 +64,8 @@ defmodule MusicLibrary.Records do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def count_records_by_format do
|
|
||||||
q =
|
|
||||||
from r in Record,
|
|
||||||
where: not is_nil(r.purchased_at),
|
|
||||||
group_by: r.format,
|
|
||||||
order_by: [desc: count(r.id)],
|
|
||||||
select: {r.format, count(r.id)}
|
|
||||||
|
|
||||||
Repo.all(q)
|
|
||||||
end
|
|
||||||
|
|
||||||
def count_records_by_type do
|
|
||||||
q =
|
|
||||||
from r in Record,
|
|
||||||
where: not is_nil(r.purchased_at),
|
|
||||||
group_by: r.type,
|
|
||||||
order_by: [desc: count(r.id)],
|
|
||||||
select: {r.type, count(r.id)}
|
|
||||||
|
|
||||||
Repo.all(q)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_record!(id), do: Repo.get!(Record, id)
|
def get_record!(id), do: Repo.get!(Record, id)
|
||||||
|
|
||||||
def get_latest_record! do
|
|
||||||
q =
|
|
||||||
from r in Record,
|
|
||||||
where: not is_nil(r.purchased_at),
|
|
||||||
order_by: [desc: r.purchased_at],
|
|
||||||
limit: 1,
|
|
||||||
select: ^@fields
|
|
||||||
|
|
||||||
Repo.one!(q)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_cover(id) do
|
def get_cover(id) do
|
||||||
q =
|
q =
|
||||||
from r in Record,
|
from r in Record,
|
||||||
|
|||||||
@@ -2,71 +2,26 @@ defmodule MusicLibrary.Wishlist do
|
|||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
|
|
||||||
alias MusicLibrary.Repo
|
alias MusicLibrary.Repo
|
||||||
alias MusicLibrary.Records.{Record, SearchParser}
|
alias MusicLibrary.Records
|
||||||
|
alias MusicLibrary.Records.Record
|
||||||
@fields [:id, :type, :artists, :format, :title, :release, :genres, :musicbrainz_id, :cover_hash]
|
|
||||||
|
|
||||||
def search_records(query, opts \\ []) do
|
def search_records(query, opts \\ []) do
|
||||||
limit = Keyword.get(opts, :limit, 20)
|
limit = Keyword.get(opts, :limit, 20)
|
||||||
offset = Keyword.get(opts, :offset, 0)
|
offset = Keyword.get(opts, :offset, 0)
|
||||||
|
|
||||||
search =
|
Records.search_records(base_search(), query, limit: limit, offset: offset)
|
||||||
query
|
|
||||||
|> build_search()
|
|
||||||
|> limit(^limit)
|
|
||||||
|> offset(^offset)
|
|
||||||
|> select(^@fields)
|
|
||||||
|
|
||||||
Repo.all(search)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def search_records_count(query) do
|
def search_records_count(query) do
|
||||||
search = build_search(query)
|
Records.search_records_count(base_search(), query)
|
||||||
|
|
||||||
Repo.aggregate(search, :count)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def count do
|
def count do
|
||||||
q =
|
Repo.aggregate(base_search(), :count)
|
||||||
from r in Record,
|
|
||||||
where: is_nil(r.purchased_at)
|
|
||||||
|
|
||||||
Repo.aggregate(q, :count)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_search(query) do
|
defp base_search do
|
||||||
{:ok, parsed_query} = SearchParser.parse(query)
|
from r in Record,
|
||||||
|
where: is_nil(r.purchased_at)
|
||||||
base_search =
|
|
||||||
from r in Record,
|
|
||||||
where: is_nil(r.purchased_at),
|
|
||||||
order_by:
|
|
||||||
fragment(
|
|
||||||
"json_extract(artists, '$[0].sort_name') COLLATE NOCASE ASC, title COLLATE NOCASE ASC"
|
|
||||||
)
|
|
||||||
|
|
||||||
Enum.reduce(parsed_query, base_search, fn
|
|
||||||
{:artist, artist}, search ->
|
|
||||||
search |> where([r], like(r.artists, ^"%#{artist}%"))
|
|
||||||
|
|
||||||
{:album, album}, search ->
|
|
||||||
search |> where([r], like(r.title, ^"%#{album}%"))
|
|
||||||
|
|
||||||
{:mbid, mbid}, search ->
|
|
||||||
search |> where([r], r.musicbrainz_id == ^mbid or like(r.artists, ^"%#{mbid}%"))
|
|
||||||
|
|
||||||
{:format, format}, search ->
|
|
||||||
search |> where([r], r.format == ^format)
|
|
||||||
|
|
||||||
{:type, type}, search ->
|
|
||||||
search |> where([r], r.type == ^type)
|
|
||||||
|
|
||||||
{:query, raw_query}, search ->
|
|
||||||
search
|
|
||||||
|> where(
|
|
||||||
[r],
|
|
||||||
like(r.title, ^"%#{raw_query}%") or like(r.artists, ^"%#{raw_query}%")
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ defmodule MusicLibraryWeb.RecordLive.Index do
|
|||||||
import MusicLibraryWeb.Pagination
|
import MusicLibraryWeb.Pagination
|
||||||
|
|
||||||
alias MusicLibrary.Records
|
alias MusicLibrary.Records
|
||||||
|
alias MusicLibrary.Collection
|
||||||
|
|
||||||
@default_records_list_params %{
|
@default_records_list_params %{
|
||||||
query: "",
|
query: "",
|
||||||
@@ -57,7 +58,7 @@ defmodule MusicLibraryWeb.RecordLive.Index do
|
|||||||
|
|
||||||
defp apply_action(socket, :index, params) do
|
defp apply_action(socket, :index, params) do
|
||||||
query = params["query"] || ""
|
query = params["query"] || ""
|
||||||
total_records = Records.search_records_count(query)
|
total_records = Collection.search_records_count(query)
|
||||||
|
|
||||||
record_list_params =
|
record_list_params =
|
||||||
@default_records_list_params
|
@default_records_list_params
|
||||||
@@ -65,7 +66,9 @@ defmodule MusicLibraryWeb.RecordLive.Index do
|
|||||||
|> merge_pagination(params, total_records)
|
|> merge_pagination(params, total_records)
|
||||||
|
|
||||||
offset = page_to_offset(record_list_params.page, record_list_params.page_size)
|
offset = page_to_offset(record_list_params.page, record_list_params.page_size)
|
||||||
records = Records.search_records(query, limit: record_list_params.page_size, offset: offset)
|
|
||||||
|
records =
|
||||||
|
Collection.search_records(query, limit: record_list_params.page_size, offset: offset)
|
||||||
|
|
||||||
socket
|
socket
|
||||||
|> assign(:page_title, gettext("Collection"))
|
|> assign(:page_title, gettext("Collection"))
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ defmodule MusicLibraryWeb.StatsLive.Index do
|
|||||||
|
|
||||||
import MusicLibraryWeb.StatsLive.DataComponents
|
import MusicLibraryWeb.StatsLive.DataComponents
|
||||||
|
|
||||||
alias MusicLibrary.{Records, Wishlist}
|
alias MusicLibrary.{Collection, Records, Wishlist}
|
||||||
alias Records.Record
|
alias Records.Record
|
||||||
|
|
||||||
def mount(_params, _session, socket) do
|
def mount(_params, _session, socket) do
|
||||||
collection_count_by_format = Records.count_records_by_format()
|
collection_count_by_format = Collection.count_records_by_format()
|
||||||
|
|
||||||
collection_count_by_type = Records.count_records_by_type()
|
collection_count_by_type = Collection.count_records_by_type()
|
||||||
|
|
||||||
collection_count =
|
collection_count =
|
||||||
Enum.reduce(collection_count_by_format, 0, fn {_, count}, acc -> acc + count end)
|
Enum.reduce(collection_count_by_format, 0, fn {_, count}, acc -> acc + count end)
|
||||||
|
|
||||||
wishlist_count = Wishlist.count()
|
wishlist_count = Wishlist.count()
|
||||||
|
|
||||||
latest_record = Records.get_latest_record!()
|
latest_record = Collection.get_latest_record!()
|
||||||
|
|
||||||
recent_tracks = LastFm.Feed.all()
|
recent_tracks = LastFm.Feed.all()
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ msgid "Choose a value"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/components/layouts/app.html.heex:13
|
#: lib/music_library_web/components/layouts/app.html.heex:13
|
||||||
#: lib/music_library_web/live/record_live/index.ex:71
|
#: lib/music_library_web/live/record_live/index.ex:74
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Collection"
|
msgid "Collection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -69,7 +69,7 @@ msgstr ""
|
|||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/record_live/index.ex:54
|
#: lib/music_library_web/live/record_live/index.ex:55
|
||||||
#: lib/music_library_web/live/record_live/index.html.heex:144
|
#: lib/music_library_web/live/record_live/index.html.heex:144
|
||||||
#: lib/music_library_web/live/record_live/show.ex:50
|
#: lib/music_library_web/live/record_live/show.ex:50
|
||||||
#: lib/music_library_web/live/record_live/show.html.heex:4
|
#: lib/music_library_web/live/record_live/show.html.heex:4
|
||||||
@@ -81,7 +81,7 @@ msgstr ""
|
|||||||
msgid "Edit"
|
msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/record_live/index.ex:118
|
#: lib/music_library_web/live/record_live/index.ex:121
|
||||||
#: lib/music_library_web/live/stats_live/index.ex:60
|
#: lib/music_library_web/live/stats_live/index.ex:60
|
||||||
#: lib/music_library_web/live/stats_live/index.ex:66
|
#: lib/music_library_web/live/stats_live/index.ex:66
|
||||||
#: lib/music_library_web/live/wishlist_live/index.ex:117
|
#: lib/music_library_web/live/wishlist_live/index.ex:117
|
||||||
@@ -122,7 +122,7 @@ msgstr ""
|
|||||||
msgid "Import"
|
msgid "Import"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/record_live/index.ex:40
|
#: lib/music_library_web/live/record_live/index.ex:41
|
||||||
#: lib/music_library_web/live/wishlist_live/index.ex:41
|
#: lib/music_library_web/live/wishlist_live/index.ex:41
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Import from MusicBrainz"
|
msgid "Import from MusicBrainz"
|
||||||
@@ -209,7 +209,7 @@ msgstr ""
|
|||||||
msgid "Purchased on"
|
msgid "Purchased on"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/record_live/index.ex:109
|
#: lib/music_library_web/live/record_live/index.ex:112
|
||||||
#: lib/music_library_web/live/stats_live/index.ex:52
|
#: lib/music_library_web/live/stats_live/index.ex:52
|
||||||
#: lib/music_library_web/live/wishlist_live/index.ex:109
|
#: lib/music_library_web/live/wishlist_live/index.ex:109
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
@@ -283,7 +283,7 @@ msgstr ""
|
|||||||
msgid "Success!"
|
msgid "Success!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/music_library_web/live/record_live/index.ex:17
|
#: lib/music_library_web/live/record_live/index.ex:18
|
||||||
#: lib/music_library_web/live/record_live/show.ex:19
|
#: lib/music_library_web/live/record_live/show.ex:19
|
||||||
#: lib/music_library_web/live/wishlist_live/index.ex:18
|
#: lib/music_library_web/live/wishlist_live/index.ex:18
|
||||||
#: lib/music_library_web/live/wishlist_live/show.ex:19
|
#: lib/music_library_web/live/wishlist_live/show.ex:19
|
||||||
|
|||||||
Reference in New Issue
Block a user