From 738e61a6c0ae05b048a38ba7ea11b1c22ff5a66e Mon Sep 17 00:00:00 2001 From: Kieran Eglin Date: Thu, 29 Feb 2024 15:24:59 -0800 Subject: [PATCH] Improves UI for media items, associated tasks --- lib/pinchflat/media_source/source.ex | 2 + .../custom_components/text_components.ex | 2 +- .../media_items/media_item_controller.ex | 6 +- .../media_item_html/show.html.heex | 60 +++++-- .../output_template_help.html.heex | 8 +- .../controllers/sources/source_controller.ex | 6 +- .../sources/source_html/show.html.heex | 154 +++++++++--------- 7 files changed, 139 insertions(+), 99 deletions(-) diff --git a/lib/pinchflat/media_source/source.ex b/lib/pinchflat/media_source/source.ex index 1c94d64..ed77c7b 100644 --- a/lib/pinchflat/media_source/source.ex +++ b/lib/pinchflat/media_source/source.ex @@ -7,6 +7,7 @@ defmodule Pinchflat.Sources.Source do import Ecto.Changeset import Pinchflat.Utils.ChangesetUtils + alias Pinchflat.Tasks.Task alias Pinchflat.Media.MediaItem alias Pinchflat.Profiles.MediaProfile @@ -47,6 +48,7 @@ defmodule Pinchflat.Sources.Source do belongs_to :media_profile, MediaProfile + has_many :tasks, Task has_many :media_items, MediaItem, foreign_key: :source_id timestamps(type: :utc_datetime) diff --git a/lib/pinchflat_web/components/custom_components/text_components.ex b/lib/pinchflat_web/components/custom_components/text_components.ex index e362110..6ba9771 100644 --- a/lib/pinchflat_web/components/custom_components/text_components.ex +++ b/lib/pinchflat_web/components/custom_components/text_components.ex @@ -23,7 +23,7 @@ defmodule PinchflatWeb.CustomComponents.TextComponents do attr :href, :string, required: true slot :inner_block - def reference_link(assigns) do + def inline_link(assigns) do ~H""" <.link href={@href} target="_blank" class="text-blue-500 hover:text-blue-300"> <%= render_slot(@inner_block) %> diff --git a/lib/pinchflat_web/controllers/media_items/media_item_controller.ex b/lib/pinchflat_web/controllers/media_items/media_item_controller.ex index 6d705b5..95847dd 100644 --- a/lib/pinchflat_web/controllers/media_items/media_item_controller.ex +++ b/lib/pinchflat_web/controllers/media_items/media_item_controller.ex @@ -1,10 +1,14 @@ defmodule PinchflatWeb.MediaItems.MediaItemController do use PinchflatWeb, :controller + alias Pinchflat.Repo alias Pinchflat.Media def show(conn, %{"id" => id}) do - media_item = Media.get_media_item!(id) + media_item = + id + |> Media.get_media_item!() + |> Repo.preload([:source, tasks: [:job]]) render(conn, :show, media_item: media_item) end diff --git a/lib/pinchflat_web/controllers/media_items/media_item_html/show.html.heex b/lib/pinchflat_web/controllers/media_items/media_item_html/show.html.heex index 9c5dce2..95da677 100644 --- a/lib/pinchflat_web/controllers/media_items/media_item_html/show.html.heex +++ b/lib/pinchflat_web/controllers/media_items/media_item_html/show.html.heex @@ -8,23 +8,51 @@ -
+
-
-

Attributes

- <.list_items_from_map map={Map.from_struct(@media_item)} /> -
+ <.tabbed_layout> + <:tab title="Attributes"> +
+

Attributes

+
+ Source: + <.inline_link href={~p"/sources/#{@media_item.source_id}"}> + <%= @media_item.source.friendly_name %> + +
-
- <.link - href={~p"/sources/#{@media_item.source_id}/media/#{@media_item}?delete_files=true"} - method="delete" - data-confirm="Are you sure you want to delete this record and all associated files on disk? This cannot be undone." - > - <.button color="bg-meta-1" rounding="rounded-full"> - Delete Files - - -
+ <.list_items_from_map map={Map.from_struct(@media_item)} /> +
+ +
+ <.link + href={~p"/sources/#{@media_item.source_id}/media/#{@media_item}?delete_files=true"} + method="delete" + data-confirm="Are you sure you want to delete this record and all associated files on disk? This cannot be undone." + > + <.button color="bg-meta-1" rounding="rounded-full"> + Delete Files + + +
+ + <:tab title="Tasks"> + <%= if match?([_|_], @media_item.tasks) do %> + <.table rows={@media_item.tasks} table_class="text-black dark:text-white"> + <:col :let={task} label="Worker"> + <%= task.job.worker %> + + <:col :let={task} label="State"> + <%= task.job.state %> + + <:col :let={task} label="Scheduled At"> + <%= Calendar.strftime(task.job.scheduled_at, "%y-%m-%d %I:%M:%S %p %Z") %> + + + <% else %> +

Nothing Here!

+ <% end %> + +
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/output_template_help.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/output_template_help.html.heex index c98fb21..7b11b1d 100644 --- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/output_template_help.html.heex +++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/output_template_help.html.heex @@ -10,9 +10,9 @@
  • yt-dlp-style - <.reference_link href="https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#output-template"> + <.inline_link href="https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#output-template"> <.icon name="hero-arrow-top-right-on-square" class="h-4 w-4" /> - : + : <.inline_code>/%(channel)s/%(duration>%H-%M-%S)s-%(id)s.%(ext)s
  • @@ -50,9 +50,9 @@

    Any single-word yt-dlp option - <.reference_link href="https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#output-template"> + <.inline_link href="https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#output-template"> <.icon name="hero-arrow-top-right-on-square" class="h-4 w-4" /> - + can be used with the curly braced liquid-style syntax. This is just a list of the most common options as well as some custom aliases

    diff --git a/lib/pinchflat_web/controllers/sources/source_controller.ex b/lib/pinchflat_web/controllers/sources/source_controller.ex index 5ecfbc7..f2cb342 100644 --- a/lib/pinchflat_web/controllers/sources/source_controller.ex +++ b/lib/pinchflat_web/controllers/sources/source_controller.ex @@ -54,10 +54,10 @@ defmodule PinchflatWeb.Sources.SourceController do source = id |> Sources.get_source!() - |> Repo.preload(:media_profile) + |> Repo.preload([:media_profile, tasks: [:job]]) - pending_media = Media.list_pending_media_items_for(source) - downloaded_media = Media.list_downloaded_media_items_for(source) + pending_media = Media.list_pending_media_items_for(source, limit: 100) + downloaded_media = Media.list_downloaded_media_items_for(source, limit: 100) render(conn, :show, source: source, pending_media: pending_media, downloaded_media: downloaded_media) end diff --git a/lib/pinchflat_web/controllers/sources/source_html/show.html.heex b/lib/pinchflat_web/controllers/sources/source_html/show.html.heex index b5fa0e3..d8c69d2 100644 --- a/lib/pinchflat_web/controllers/sources/source_html/show.html.heex +++ b/lib/pinchflat_web/controllers/sources/source_html/show.html.heex @@ -18,83 +18,89 @@
  • -
    -

    Attributes for "<%= @source.friendly_name %>"

    + <.tabbed_layout> + <:tab title="Attributes"> +
    +

    Attributes

    +
    + Media Profile: + <.inline_link href={~p"/media_profiles/#{@source.media_profile_id}"}> + <%= @source.media_profile.name %> + +
    -

    Relationships

    - <.list> - <:item title="media_profile"> + <.list_items_from_map map={Map.from_struct(@source)} /> +
    + +
    <.link - navigate={~p"/media_profiles/#{@source.media_profile_id}"} - class="hover:text-secondary duration-200 ease-in-out" + href={~p"/sources/#{@source}"} + method="delete" + data-confirm="Are you sure you want to delete this source (leaving files in place)? This cannot be undone." > - <%= @source.media_profile.name %> + <.button color="bg-meta-1" rounding="rounded-full"> + Delete Source + - - - -

    Attributes

    - <.list_items_from_map map={Map.from_struct(@source)} /> - -

    Downloaded Media

    - <%= if match?([_|_], @downloaded_media) do %> - <.table rows={@downloaded_media} table_class="text-black dark:text-white"> - <:col :let={media_item} label="Title"> - <%= StringUtils.truncate(media_item.title, 50) %> - - <:col :let={media_item} label="" class="flex place-content-evenly"> - <.link - navigate={~p"/sources/#{@source.id}/media/#{media_item.id}"} - class="hover:text-secondary duration-200 ease-in-out mx-0.5" - > - <.icon name="hero-eye" /> - - - - <% else %> -

    Nothing Here!

    - <% end %> - -

    Pending Media

    - <%= if match?([_|_], @pending_media) do %> - <.table rows={@pending_media} table_class="text-black dark:text-white"> - <:col :let={media_item} label="Title"> - <%= StringUtils.truncate(media_item.title, 50) %> - - <:col :let={media_item} label="" class="flex place-content-evenly"> - <.link - navigate={~p"/sources/#{@source.id}/media/#{media_item.id}"} - class="hover:text-secondary duration-200 ease-in-out mx-0.5" - > - <.icon name="hero-eye" /> - - - - <% else %> -

    Nothing Here!

    - <% end %> -
    - -
    - <.link - href={~p"/sources/#{@source}"} - method="delete" - data-confirm="Are you sure you want to delete this source (leaving files in place)? This cannot be undone." - > - <.button color="bg-meta-1" rounding="rounded-full"> - Delete Source - - - <.link - href={~p"/sources/#{@source}?delete_files=true"} - method="delete" - data-confirm="Are you sure you want to delete this source and it's files on disk? This cannot be undone." - class="mt-5 md:mt-0" - > - <.button color="bg-meta-1" rounding="rounded-full"> - Delete Source and Files - - -
    + <.link + href={~p"/sources/#{@source}?delete_files=true"} + method="delete" + data-confirm="Are you sure you want to delete this source and it's files on disk? This cannot be undone." + class="mt-5 md:mt-0" + > + <.button color="bg-meta-1" rounding="rounded-full"> + Delete Source and Files + + + + + <:tab title="Pending Media"> + <%= if match?([_|_], @pending_media) do %> +

    Shows a maximum of 100 media items

    + <.table rows={@pending_media} table_class="text-black dark:text-white"> + <:col :let={media_item} label="Title"> + <%= StringUtils.truncate(media_item.title, 50) %> + + <:col :let={media_item} label="" class="flex place-content-evenly"> + <.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" /> + + + <% else %> +

    Nothing Here!

    + <% end %> + + <:tab title="Downloaded Media"> + <%= if match?([_|_], @downloaded_media) do %> +

    Shows a maximum of 100 media items

    + <.table rows={@downloaded_media} table_class="text-black dark:text-white"> + <:col :let={media_item} label="Title"> + <%= StringUtils.truncate(media_item.title, 50) %> + + <:col :let={media_item} label="" class="flex place-content-evenly"> + <.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" /> + + + <% else %> +

    Nothing Here!

    + <% end %> + + <:tab title="Tasks"> + <%= if match?([_|_], @source.tasks) do %> + <.table rows={@source.tasks} table_class="text-black dark:text-white"> + <:col :let={task} label="Worker"> + <%= task.job.worker %> + + <:col :let={task} label="State"> + <%= task.job.state %> + + <:col :let={task} label="Scheduled At"> + <%= Calendar.strftime(task.job.scheduled_at, "%y-%m-%d %I:%M:%S %p %Z") %> + + + <% else %> +

    Nothing Here!

    + <% end %> + +