@@ -49,12 +51,12 @@ defmodule Pinchflat.Sources.MediaItemTableLive do
<%= StringUtils.truncate(media_item.title, 50) %>
- <:col :let={media_item} label="Upload Date">
- <%= DateTime.to_date(media_item.uploaded_at) %>
-
<:col :let={media_item} :if={@media_state == "other"} label="Manually Ignored?">
<.icon name={if media_item.prevent_download, do: "hero-check", else: "hero-x-mark"} />
+ <:col :let={media_item} label="Upload Date">
+ <%= DateTime.to_date(media_item.uploaded_at) %>
+
<:col :let={media_item} label="" class="flex justify-end">
<.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}/edit"} icon="hero-pencil-square" class="mr-4" />
@@ -117,14 +119,40 @@ defmodule Pinchflat.Sources.MediaItemTableLive do
{:noreply, assign(socket, new_assigns)}
end
+ defp fetch_pagination_attributes(base_query, page, ""), do: fetch_pagination_attributes(base_query, page, nil)
+
+ defp fetch_pagination_attributes(base_query, page, nil) do
+ total_record_count = Repo.aggregate(base_query, :count, :id)
+ total_pages = max(ceil(total_record_count / @limit), 1)
+ page = NumberUtils.clamp(page, 1, total_pages)
+
+ records =
+ fetch_records(base_query, page)
+ |> order_by(desc: :uploaded_at)
+ |> Repo.all()
+
+ %{
+ page: page,
+ total_pages: total_pages,
+ records: records,
+ search_term: nil,
+ total_record_count: total_record_count,
+ filtered_record_count: total_record_count
+ }
+ end
+
defp fetch_pagination_attributes(base_query, page, search_term) do
- filtered_base_query = filter_base_query(base_query, search_term)
+ filtered_base_query = filtered_base_query(base_query, search_term)
total_record_count = Repo.aggregate(base_query, :count, :id)
filtered_record_count = Repo.aggregate(filtered_base_query, :count, :id)
total_pages = max(ceil(filtered_record_count / @limit), 1)
page = NumberUtils.clamp(page, 1, total_pages)
- records = fetch_records(filtered_base_query, page)
+
+ records =
+ fetch_records(filtered_base_query, page)
+ |> order_by(desc: fragment("rank"), desc: :uploaded_at)
+ |> Repo.all()
%{
page: page,
@@ -142,39 +170,41 @@ defmodule Pinchflat.Sources.MediaItemTableLive do
base_query
|> limit(^@limit)
|> offset(^offset)
- |> Repo.all()
end
defp generate_base_query(source, "pending") do
MediaQuery.new()
+ |> select(^select_fields())
|> MediaQuery.require_assoc(:media_profile)
- |> MediaQuery.require_assoc(:media_items_search_index)
|> where(^dynamic(^MediaQuery.for_source(source) and ^MediaQuery.pending()))
- |> order_by(desc: fragment("rank"), desc: :uploaded_at)
end
defp generate_base_query(source, "downloaded") do
MediaQuery.new()
- |> MediaQuery.require_assoc(:media_items_search_index)
+ |> select(^select_fields())
|> where(^dynamic(^MediaQuery.for_source(source) and ^MediaQuery.downloaded()))
- |> order_by(desc: fragment("rank"), desc: :uploaded_at)
end
defp generate_base_query(source, "other") do
MediaQuery.new()
+ |> select(^select_fields())
|> MediaQuery.require_assoc(:media_profile)
- |> MediaQuery.require_assoc(:media_items_search_index)
|> where(
^dynamic(
^MediaQuery.for_source(source) and
(not (^MediaQuery.downloaded()) and not (^MediaQuery.pending()))
)
)
- |> order_by(desc: fragment("rank"), desc: :uploaded_at)
end
- defp filter_base_query(base_query, search_term) do
+ defp filtered_base_query(base_query, search_term) do
base_query
+ |> MediaQuery.require_assoc(:media_items_search_index)
|> where(^MediaQuery.matches_search_term(search_term))
end
+
+ # Selecting only what we need GREATLY speeds up queries on large tables
+ defp select_fields do
+ [:id, :title, :uploaded_at, :prevent_download]
+ end
end
diff --git a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
index 6a53a3a..88b584d 100644
--- a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
+++ b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
@@ -95,7 +95,8 @@
type="number"
label="Retention Period (days)"
min="0"
- help="Days between when media is *downloaded* and when it's deleted. Leave blank to keep media indefinitely"
+ help="Days between when media is downloaded and when it's deleted. Leave blank to keep media indefinitely"
+ html_help={true}
/>
diff --git a/priv/repo/erd.png b/priv/repo/erd.png
index 5f66b70..30d3e8a 100644
Binary files a/priv/repo/erd.png and b/priv/repo/erd.png differ
diff --git a/priv/repo/migrations/20240529000015_modify_upload_date_index.exs b/priv/repo/migrations/20240529000015_modify_upload_date_index.exs
new file mode 100644
index 0000000..a9be455
--- /dev/null
+++ b/priv/repo/migrations/20240529000015_modify_upload_date_index.exs
@@ -0,0 +1,8 @@
+defmodule Pinchflat.Repo.Migrations.ModifyUploadDateIndex do
+ use Ecto.Migration
+
+ def change do
+ drop index("media_items", [:upload_date])
+ create index("media_items", [:uploaded_at])
+ end
+end
diff --git a/priv/repo/migrations/20240529153838_add_indexes_for_large_collections.exs b/priv/repo/migrations/20240529153838_add_indexes_for_large_collections.exs
new file mode 100644
index 0000000..8c60aed
--- /dev/null
+++ b/priv/repo/migrations/20240529153838_add_indexes_for_large_collections.exs
@@ -0,0 +1,19 @@
+defmodule Pinchflat.Repo.Migrations.AddIndexesForLargeCollections do
+ use Ecto.Migration
+
+ def change do
+ create index(
+ "media_items",
+ [
+ :source_id,
+ :media_filepath,
+ :uploaded_at,
+ :prevent_download,
+ :livestream,
+ :short_form_content,
+ :title
+ ],
+ name: "media_items_pending_and_downloaded_index"
+ )
+ end
+end
diff --git a/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs b/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs
index f584377..772e305 100644
--- a/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs
+++ b/test/pinchflat_web/controllers/sources/media_item_table_live_test.exs
@@ -27,7 +27,7 @@ defmodule PinchflatWeb.Sources.MediaItemTableLiveTest do
{:ok, _view, html} = live_isolated(conn, MediaItemTableLive, session: create_session(source))
- assert html =~ "Showing 1 of 1"
+ assert html =~ "Showing"
assert html =~ "Title"
assert html =~ media_item.title
end