Improves UI for media items, associated tasks

This commit is contained in:
Kieran Eglin 2024-02-29 15:24:59 -08:00
parent 6ba9b2f28e
commit 738e61a6c0
No known key found for this signature in database
GPG key ID: 193984967FCF432D
7 changed files with 139 additions and 99 deletions

View file

@ -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)

View file

@ -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) %>

View file

@ -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

View file

@ -8,23 +8,51 @@
</h2>
</div>
</div>
<div class="rounded-sm border border-stroke bg-white px-5 pb-2.5 pt-6 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5 xl:pb-1">
<div class="rounded-sm border border-stroke bg-white py-5 pt-6 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5">
<div class="max-w-full overflow-x-auto">
<div class="flex flex-col gap-10 dark:text-white">
<h3 class="font-bold text-xl">Attributes</h3>
<.list_items_from_map map={Map.from_struct(@media_item)} />
</div>
<.tabbed_layout>
<:tab title="Attributes">
<div class="flex flex-col gap-10 dark:text-white">
<h3 class="font-bold text-xl">Attributes</h3>
<section>
<strong>Source:</strong>
<.inline_link href={~p"/sources/#{@media_item.source_id}"}>
<%= @media_item.source.friendly_name %>
</.inline_link>
</section>
<section class="flex justify-center my-10">
<.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
</.button>
</.link>
</section>
<.list_items_from_map map={Map.from_struct(@media_item)} />
</div>
<section class="flex justify-center my-10">
<.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
</.button>
</.link>
</section>
</:tab>
<: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>
<:col :let={task} label="State">
<%= task.job.state %>
</:col>
<:col :let={task} label="Scheduled At">
<%= Calendar.strftime(task.job.scheduled_at, "%y-%m-%d %I:%M:%S %p %Z") %>
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
</:tab>
</.tabbed_layout>
</div>
</div>

View file

@ -10,9 +10,9 @@
</li>
<li>
<code class="text-sm">yt-dlp</code>-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" />
</.reference_link>:
</.inline_link>:
<.inline_code>/%(channel)s/%(duration>%H-%M-%S)s-%(id)s.%(ext)s</.inline_code>
</li>
<li>
@ -50,9 +50,9 @@
<p>
Any single-word <code class="text-sm">yt-dlp</code>
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" />
</.reference_link>
</.inline_link>
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
</p>

View file

@ -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

View file

@ -18,83 +18,89 @@
</div>
<div class="rounded-sm border border-stroke bg-white px-5 py-5 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5">
<div class="max-w-full overflow-x-auto">
<div class="flex flex-col gap-10 dark:text-white">
<h3 class="font-bold text-xl">Attributes for "<%= @source.friendly_name %>"</h3>
<.tabbed_layout>
<:tab title="Attributes">
<div class="flex flex-col gap-10 text-white">
<h3 class="font-bold text-lg">Attributes</h3>
<section>
<strong>Media Profile:</strong>
<.inline_link href={~p"/media_profiles/#{@source.media_profile_id}"}>
<%= @source.media_profile.name %>
</.inline_link>
</section>
<h3 class="font-bold text-lg">Relationships</h3>
<.list>
<:item title="media_profile">
<.list_items_from_map map={Map.from_struct(@source)} />
</div>
<section class="flex flex-col md:flex-row items-center md:justify-around mt-10">
<.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
</.button>
</.link>
</:item>
</.list>
<h3 class="font-bold text-lg">Attributes</h3>
<.list_items_from_map map={Map.from_struct(@source)} />
<h3 class="font-bold text-xl">Downloaded Media</h3>
<%= 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>
<: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" />
</.link>
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
<h3 class="font-bold text-xl">Pending Media</h3>
<%= 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>
<: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" />
</.link>
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
</div>
<section class="flex flex-col md:flex-row items-center md:justify-around mt-10">
<.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
</.button>
</.link>
<.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
</.button>
</.link>
</section>
<.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
</.button>
</.link>
</section>
</:tab>
<:tab title="Pending Media">
<%= if match?([_|_], @pending_media) do %>
<h4 class="text-white text-lg mb-6">Shows a maximum of 100 media items</h4>
<.table rows={@pending_media} table_class="text-black dark:text-white">
<:col :let={media_item} label="Title">
<%= StringUtils.truncate(media_item.title, 50) %>
</:col>
<:col :let={media_item} label="" class="flex place-content-evenly">
<.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" />
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
</:tab>
<:tab title="Downloaded Media">
<%= if match?([_|_], @downloaded_media) do %>
<h4 class="text-white text-lg mb-6">Shows a maximum of 100 media items</h4>
<.table rows={@downloaded_media} table_class="text-black dark:text-white">
<:col :let={media_item} label="Title">
<%= StringUtils.truncate(media_item.title, 50) %>
</:col>
<:col :let={media_item} label="" class="flex place-content-evenly">
<.icon_link href={~p"/sources/#{@source.id}/media/#{media_item.id}"} icon="hero-eye" />
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
</:tab>
<: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>
<:col :let={task} label="State">
<%= task.job.state %>
</:col>
<:col :let={task} label="Scheduled At">
<%= Calendar.strftime(task.job.scheduled_at, "%y-%m-%d %I:%M:%S %p %Z") %>
</:col>
</.table>
<% else %>
<p class="text-black dark:text-white">Nothing Here!</p>
<% end %>
</:tab>
</.tabbed_layout>
</div>
</div>