Added tabbed view; improved relationships for media profile
This commit is contained in:
parent
5b29f5036a
commit
000bed18b1
5 changed files with 89 additions and 26 deletions
|
|
@ -88,6 +88,7 @@ defmodule PinchflatWeb do
|
||||||
# Core UI components and translation
|
# Core UI components and translation
|
||||||
import PinchflatWeb.Gettext
|
import PinchflatWeb.Gettext
|
||||||
import PinchflatWeb.CoreComponents
|
import PinchflatWeb.CoreComponents
|
||||||
|
import PinchflatWeb.CustomComponents.TabComponents
|
||||||
import PinchflatWeb.CustomComponents.TextComponents
|
import PinchflatWeb.CustomComponents.TextComponents
|
||||||
import PinchflatWeb.CustomComponents.TableComponents
|
import PinchflatWeb.CustomComponents.TableComponents
|
||||||
import PinchflatWeb.CustomComponents.ButtonComponents
|
import PinchflatWeb.CustomComponents.ButtonComponents
|
||||||
|
|
|
||||||
|
|
@ -587,6 +587,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
attrs =
|
attrs =
|
||||||
Enum.filter(assigns.map, fn
|
Enum.filter(assigns.map, fn
|
||||||
{_, %{__struct__: _}} -> false
|
{_, %{__struct__: _}} -> false
|
||||||
|
{_, [%{__meta__: _} | _]} -> false
|
||||||
_ -> true
|
_ -> true
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
defmodule PinchflatWeb.CustomComponents.TabComponents do
|
||||||
|
@moduledoc false
|
||||||
|
use Phoenix.Component
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Takes a list of tabs and renders them in a tabbed layout.
|
||||||
|
"""
|
||||||
|
slot :tab, required: true do
|
||||||
|
attr :title, :string, required: true
|
||||||
|
end
|
||||||
|
|
||||||
|
def tabbed_layout(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div
|
||||||
|
x-data="{ openTab: 0, activeClasses: 'text-meta-5 border-meta-5', inactiveClasses: 'border-transparent' }"
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
|
<div class="mb-6 flex flex-wrap gap-5 border-b border-strokedark sm:gap-10">
|
||||||
|
<a
|
||||||
|
:for={{tab, idx} <- Enum.with_index(@tab)}
|
||||||
|
href="#"
|
||||||
|
@click.prevent={"openTab = #{idx}"}
|
||||||
|
x-bind:class={"openTab === #{idx} ? activeClasses : inactiveClasses"}
|
||||||
|
class="border-b-2 py-4 text-sm font-medium hover:text-meta-5 md:text-base"
|
||||||
|
>
|
||||||
|
<span class="text-xl"><%= tab.title %></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div :for={{tab, idx} <- Enum.with_index(@tab)} x-show={"openTab === #{idx}"} class="font-medium leading-relaxed">
|
||||||
|
<%= render_slot(tab) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule PinchflatWeb.MediaProfiles.MediaProfileController do
|
defmodule PinchflatWeb.MediaProfiles.MediaProfileController do
|
||||||
use PinchflatWeb, :controller
|
use PinchflatWeb, :controller
|
||||||
|
|
||||||
|
alias Pinchflat.Repo
|
||||||
alias Pinchflat.Profiles
|
alias Pinchflat.Profiles
|
||||||
alias Pinchflat.Profiles.MediaProfile
|
alias Pinchflat.Profiles.MediaProfile
|
||||||
|
|
||||||
|
|
@ -39,7 +40,11 @@ defmodule PinchflatWeb.MediaProfiles.MediaProfileController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(conn, %{"id" => id}) do
|
def show(conn, %{"id" => id}) do
|
||||||
media_profile = Profiles.get_media_profile!(id)
|
media_profile =
|
||||||
|
id
|
||||||
|
|> Profiles.get_media_profile!()
|
||||||
|
|> Repo.preload(:sources)
|
||||||
|
|
||||||
render(conn, :show, media_profile: media_profile)
|
render(conn, :show, media_profile: media_profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,31 +18,50 @@
|
||||||
</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 px-5 pb-2.5 pt-6 shadow-default dark:border-strokedark dark:bg-boxdark sm:px-7.5 xl:pb-1">
|
||||||
<div class="max-w-full overflow-x-auto">
|
<div class="max-w-full overflow-x-auto">
|
||||||
<div class="flex flex-col gap-10 dark:text-white">
|
<.tabbed_layout>
|
||||||
<h3 class="font-bold text-xl">Attributes for "<%= @media_profile.name %>"</h3>
|
<:tab title="Attributes">
|
||||||
<.list_items_from_map map={Map.from_struct(@media_profile)} />
|
<div class="flex flex-col gap-10 text-white">
|
||||||
</div>
|
<h3 class="font-bold text-xl">Attributes for "<%= @media_profile.name %>"</h3>
|
||||||
|
<.list_items_from_map map={Map.from_struct(@media_profile)} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<section class="flex flex-col md:flex-row items-center md:justify-around my-10">
|
<section class="flex flex-col md:flex-row items-center md:justify-around my-10">
|
||||||
<.link
|
<.link
|
||||||
href={~p"/media_profiles/#{@media_profile}"}
|
href={~p"/media_profiles/#{@media_profile}"}
|
||||||
method="delete"
|
method="delete"
|
||||||
data-confirm="Are you sure you want to delete this profile and all its sources (leaving files in place)? This cannot be undone."
|
data-confirm="Are you sure you want to delete this profile and all its sources (leaving files in place)? This cannot be undone."
|
||||||
>
|
>
|
||||||
<.button color="bg-meta-1" rounding="rounded-full">
|
<.button color="bg-meta-1" rounding="rounded-full">
|
||||||
Delete Profile and its Sources
|
Delete Profile and its Sources
|
||||||
</.button>
|
</.button>
|
||||||
</.link>
|
</.link>
|
||||||
<.link
|
<.link
|
||||||
href={~p"/media_profiles/#{@media_profile}?delete_files=true"}
|
href={~p"/media_profiles/#{@media_profile}?delete_files=true"}
|
||||||
method="delete"
|
method="delete"
|
||||||
data-confirm="Are you sure you want to delete this profile, all its sources, and its files on disk? This cannot be undone."
|
data-confirm="Are you sure you want to delete this profile, all its sources, and its files on disk? This cannot be undone."
|
||||||
class="mt-5 md:mt-0"
|
class="mt-5 md:mt-0"
|
||||||
>
|
>
|
||||||
<.button color="bg-meta-1" rounding="rounded-full">
|
<.button color="bg-meta-1" rounding="rounded-full">
|
||||||
Delete Profile, Sources, and Files
|
Delete Profile, Sources, and Files
|
||||||
</.button>
|
</.button>
|
||||||
</.link>
|
</.link>
|
||||||
</section>
|
</section>
|
||||||
|
</:tab>
|
||||||
|
<:tab title="Sources">
|
||||||
|
<.table rows={@media_profile.sources} table_class="text-black dark:text-white">
|
||||||
|
<:col :let={source} label="Name">
|
||||||
|
<%= source.friendly_name || source.collection_name %>
|
||||||
|
</:col>
|
||||||
|
<:col :let={source} label="Type"><%= source.collection_type %></:col>
|
||||||
|
<:col :let={source} label="Should Download?">
|
||||||
|
<.icon name={if source.download_media, do: "hero-check", else: "hero-x-mark"} />
|
||||||
|
</:col>
|
||||||
|
<:col :let={source} label="" class="flex place-content-evenly">
|
||||||
|
<.icon_link href={~p"/sources/#{source.id}"} icon="hero-eye" class="mx-1" />
|
||||||
|
<.icon_link href={~p"/sources/#{source.id}/edit"} icon="hero-pencil-square" class="mx-1" />
|
||||||
|
</:col>
|
||||||
|
</.table>
|
||||||
|
</:tab>
|
||||||
|
</.tabbed_layout>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue