[WIP] Set up basic views for sources
This commit is contained in:
parent
8f05c6a647
commit
fcc40dfa8d
18 changed files with 370 additions and 247 deletions
|
|
@ -22,9 +22,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-Light.woff2'), url('/fonts/satoshi/Satoshi-Light.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-Light.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Light.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Light.ttf');
|
url('/fonts/satoshi/Satoshi-Light.ttf');
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -33,10 +31,8 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-LightItalic.woff2'),
|
||||||
url('/fonts/satoshi/Satoshi-LightItalic.woff2'),
|
url('/fonts/satoshi/Satoshi-LightItalic.woff'), url('/fonts/satoshi/Satoshi-LightItalic.ttf');
|
||||||
url('/fonts/satoshi/Satoshi-LightItalic.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-LightItalic.ttf');
|
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|
@ -44,9 +40,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-Regular.woff2'), url('/fonts/satoshi/Satoshi-Regular.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-Regular.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Regular.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Regular.ttf');
|
url('/fonts/satoshi/Satoshi-Regular.ttf');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -55,9 +49,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-Italic.woff2'), url('/fonts/satoshi/Satoshi-Italic.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-Italic.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Italic.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Italic.ttf');
|
url('/fonts/satoshi/Satoshi-Italic.ttf');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -66,9 +58,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-Medium.woff2'), url('/fonts/satoshi/Satoshi-Medium.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-Medium.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Medium.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Medium.ttf');
|
url('/fonts/satoshi/Satoshi-Medium.ttf');
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -77,10 +67,8 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-MediumItalic.woff2'),
|
||||||
url('/fonts/satoshi/Satoshi-MediumItalic.woff2'),
|
url('/fonts/satoshi/Satoshi-MediumItalic.woff'), url('/fonts/satoshi/Satoshi-MediumItalic.ttf');
|
||||||
url('/fonts/satoshi/Satoshi-MediumItalic.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-MediumItalic.ttf');
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|
@ -88,9 +76,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-Bold.woff2'), url('/fonts/satoshi/Satoshi-Bold.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-Bold.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Bold.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-Bold.ttf');
|
url('/fonts/satoshi/Satoshi-Bold.ttf');
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -99,9 +85,7 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-BoldItalic.woff2'), url('/fonts/satoshi/Satoshi-BoldItalic.woff'),
|
||||||
url('/fonts/satoshi/Satoshi-BoldItalic.woff2'),
|
|
||||||
url('/fonts/satoshi/Satoshi-BoldItalic.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-BoldItalic.ttf');
|
url('/fonts/satoshi/Satoshi-BoldItalic.ttf');
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
|
|
@ -110,10 +94,8 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Satoshi';
|
font-family: 'Satoshi';
|
||||||
src:
|
src: url('/fonts/satoshi/Satoshi-BlackItalic.woff2'),
|
||||||
url('/fonts/satoshi/Satoshi-BlackItalic.woff2'),
|
url('/fonts/satoshi/Satoshi-BlackItalic.woff'), url('/fonts/satoshi/Satoshi-BlackItalic.ttf');
|
||||||
url('/fonts/satoshi/Satoshi-BlackItalic.woff'),
|
|
||||||
url('/fonts/satoshi/Satoshi-BlackItalic.ttf');
|
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,10 @@ defmodule PinchflatWeb do
|
||||||
# HTML escaping functionality
|
# HTML escaping functionality
|
||||||
import Phoenix.HTML
|
import Phoenix.HTML
|
||||||
# Core UI components and translation
|
# Core UI components and translation
|
||||||
import PinchflatWeb.CoreComponents
|
|
||||||
import PinchflatWeb.Gettext
|
import PinchflatWeb.Gettext
|
||||||
|
import PinchflatWeb.CoreComponents
|
||||||
|
import PinchflatWeb.CustomComponents.TableComponents
|
||||||
|
import PinchflatWeb.CustomComponents.ButtonComponents
|
||||||
|
|
||||||
# Shortcut for generating JS commands
|
# Shortcut for generating JS commands
|
||||||
alias Phoenix.LiveView.JS
|
alias Phoenix.LiveView.JS
|
||||||
|
|
|
||||||
|
|
@ -201,46 +201,14 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
def simple_form(assigns) do
|
def simple_form(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<.form :let={f} for={@for} as={@as} {@rest}>
|
<.form :let={f} for={@for} as={@as} {@rest}>
|
||||||
<div class="mt-10 space-y-8 bg-white">
|
|
||||||
<%= render_slot(@inner_block, f) %>
|
<%= render_slot(@inner_block, f) %>
|
||||||
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
|
<div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
|
||||||
<%= render_slot(action, f) %>
|
<%= render_slot(action, f) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</.form>
|
</.form>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
|
||||||
Renders a button.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
<.button>Send!</.button>
|
|
||||||
<.button phx-click="go" class="ml-2">Send!</.button>
|
|
||||||
"""
|
|
||||||
attr :type, :string, default: nil
|
|
||||||
attr :class, :string, default: nil
|
|
||||||
attr :rest, :global, include: ~w(disabled form name value)
|
|
||||||
|
|
||||||
slot :inner_block, required: true
|
|
||||||
|
|
||||||
def button(assigns) do
|
|
||||||
~H"""
|
|
||||||
<button
|
|
||||||
type={@type}
|
|
||||||
class={[
|
|
||||||
"phx-submit-loading:opacity-75 rounded-lg bg-zinc-900 hover:bg-zinc-700 py-2 px-3",
|
|
||||||
"text-sm font-semibold leading-6 text-white active:text-white/80",
|
|
||||||
@class
|
|
||||||
]}
|
|
||||||
{@rest}
|
|
||||||
>
|
|
||||||
<%= render_slot(@inner_block) %>
|
|
||||||
</button>
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders an input with label and error messages.
|
Renders an input with label and error messages.
|
||||||
|
|
||||||
|
|
@ -270,11 +238,12 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
attr :name, :any
|
attr :name, :any
|
||||||
attr :label, :string, default: nil
|
attr :label, :string, default: nil
|
||||||
attr :value, :any
|
attr :value, :any
|
||||||
|
attr :help, :string, default: nil
|
||||||
|
|
||||||
attr :type, :string,
|
attr :type, :string,
|
||||||
default: "text",
|
default: "text",
|
||||||
values: ~w(checkbox color date datetime-local email file hidden month number password
|
values: ~w(checkbox color date datetime-local email file hidden month number password
|
||||||
range radio search select tel text textarea time url week)
|
toggle range radio search select tel text textarea time url week)
|
||||||
|
|
||||||
attr :field, Phoenix.HTML.FormField,
|
attr :field, Phoenix.HTML.FormField,
|
||||||
doc: "a form field struct retrieved from the form, for example: @form[:email]"
|
doc: "a form field struct retrieved from the form, for example: @form[:email]"
|
||||||
|
|
@ -308,7 +277,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
<label class="flex items-center gap-4 text-sm leading-6 text-zinc-600">
|
<label class="flex items-center gap-4 text-sm leading-6">
|
||||||
<input type="hidden" name={@name} value="false" />
|
<input type="hidden" name={@name} value="false" />
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
|
@ -316,16 +285,54 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
name={@name}
|
name={@name}
|
||||||
value="true"
|
value="true"
|
||||||
checked={@checked}
|
checked={@checked}
|
||||||
class="rounded border-zinc-300 text-zinc-900 focus:ring-0"
|
class="rounded focus:ring-0"
|
||||||
{@rest}
|
{@rest}
|
||||||
/>
|
/>
|
||||||
<%= @label %>
|
<%= @label %>
|
||||||
</label>
|
</label>
|
||||||
|
<.help :if={@help}><%= @help %></.help>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def input(%{type: "toggle"} = assigns) do
|
||||||
|
assigns =
|
||||||
|
assign_new(assigns, :checked, fn ->
|
||||||
|
Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
|
||||||
|
end)
|
||||||
|
|
||||||
|
~H"""
|
||||||
|
<div x-data={"{ enabled: #{@checked}}"}>
|
||||||
|
<.label for={@id}><%= @label %></.label>
|
||||||
|
<div class="relative">
|
||||||
|
<input type="hidden" name={@name} value="false" />
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={@id}
|
||||||
|
name={@name}
|
||||||
|
value="true"
|
||||||
|
x-bind:checked="enabled"
|
||||||
|
class="sr-only"
|
||||||
|
@change="enabled = !enabled"
|
||||||
|
{@rest}
|
||||||
|
/>
|
||||||
|
<div class="inline-block cursor-pointer" @click="enabled = !enabled">
|
||||||
|
<div x-bind:class="enabled && '!bg-primary'" class="block h-8 w-14 rounded-full bg-black">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
x-bind:class="enabled && '!right-1 !translate-x-full'"
|
||||||
|
class="absolute left-1 top-1 flex h-6 w-6 items-center justify-center rounded-full bg-white transition"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<.help :if={@help}><%= @help %></.help>
|
||||||
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
def input(%{type: "select"} = assigns) do
|
def input(%{type: "select"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
|
|
@ -333,13 +340,17 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
<select
|
<select
|
||||||
id={@id}
|
id={@id}
|
||||||
name={@name}
|
name={@name}
|
||||||
class="mt-2 block w-full rounded-md border border-gray-300 bg-white shadow-sm focus:border-zinc-400 focus:ring-0 sm:text-sm"
|
class={[
|
||||||
|
"relative z-20 w-full appearance-none rounded border border-stroke bg-transparent py-3 pl-5 pr-12 outline-none transition",
|
||||||
|
"focus:border-primary active:border-primary dark:border-form-strokedark dark:bg-form-input text-black dark:text-white"
|
||||||
|
]}
|
||||||
multiple={@multiple}
|
multiple={@multiple}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<option :if={@prompt} value=""><%= @prompt %></option>
|
<option :if={@prompt} value=""><%= @prompt %></option>
|
||||||
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
|
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
|
||||||
</select>
|
</select>
|
||||||
|
<.help :if={@help}><%= @help %></.help>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -360,6 +371,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
]}
|
]}
|
||||||
{@rest}
|
{@rest}
|
||||||
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
|
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %></textarea>
|
||||||
|
<.help :if={@help}><%= @help %></.help>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -376,18 +388,32 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
id={@id}
|
id={@id}
|
||||||
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
||||||
class={[
|
class={[
|
||||||
"mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6",
|
"w-full rounded-lg border-[1.5px] border-stroke bg-transparent px-5 py-3 font-normal text-black",
|
||||||
"phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400",
|
"outline-none transition focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter",
|
||||||
@errors == [] && "border-zinc-300 focus:border-zinc-400",
|
"dark:border-form-strokedark dark:bg-form-input dark:text-white dark:focus:border-primary",
|
||||||
@errors != [] && "border-rose-400 focus:border-rose-400"
|
@errors != [] && "border-rose-400 focus:border-rose-400"
|
||||||
]}
|
]}
|
||||||
{@rest}
|
{@rest}
|
||||||
/>
|
/>
|
||||||
|
<.help :if={@help}><%= @help %></.help>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders help text.
|
||||||
|
"""
|
||||||
|
slot :inner_block, required: true
|
||||||
|
|
||||||
|
def help(assigns) do
|
||||||
|
~H"""
|
||||||
|
<p class="mt-1 text-sm leading-5">
|
||||||
|
<%= render_slot(@inner_block) %>
|
||||||
|
</p>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a label.
|
Renders a label.
|
||||||
"""
|
"""
|
||||||
|
|
@ -396,7 +422,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
def label(assigns) do
|
def label(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<label for={@for} class="block text-sm font-semibold leading-6 text-zinc-800">
|
<label for={@for} class="mt-5 mb-2 block text-md font-medium text-black dark:text-white">
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</label>
|
</label>
|
||||||
"""
|
"""
|
||||||
|
|
@ -409,7 +435,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
def error(assigns) do
|
def error(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<p class="mt-3 flex gap-3 text-sm leading-6 text-rose-600 phx-no-feedback:hidden">
|
<p class="mt-1 mb-5 flex gap-3 text-md leading-6 text-rose-600 phx-no-feedback:hidden">
|
||||||
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
|
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -446,10 +472,10 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
<.table id="users" rows={@users}>
|
<.old_table id="users" rows={@users}>
|
||||||
<:col :let={user} label="id"><%= user.id %></:col>
|
<:col :let={user} label="id"><%= user.id %></:col>
|
||||||
<:col :let={user} label="username"><%= user.username %></:col>
|
<:col :let={user} label="username"><%= user.username %></:col>
|
||||||
</.table>
|
</.old_table>
|
||||||
"""
|
"""
|
||||||
attr :id, :string, required: true
|
attr :id, :string, required: true
|
||||||
attr :rows, :list, required: true
|
attr :rows, :list, required: true
|
||||||
|
|
@ -466,14 +492,13 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
slot :action, doc: "the slot for showing user actions in the last table column"
|
slot :action, doc: "the slot for showing user actions in the last table column"
|
||||||
|
|
||||||
def table(assigns) do
|
def old_table(assigns) do
|
||||||
assigns =
|
assigns =
|
||||||
with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do
|
with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do
|
||||||
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
|
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
|
||||||
end
|
end
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div class="overflow-y-auto px-4 sm:overflow-visible sm:px-0">
|
|
||||||
<table class="w-[40rem] mt-11 sm:w-full">
|
<table class="w-[40rem] mt-11 sm:w-full">
|
||||||
<thead class="text-sm text-left leading-6 text-zinc-500">
|
<thead class="text-sm text-left leading-6 text-zinc-500">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -515,7 +540,6 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -536,10 +560,10 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
def list(assigns) do
|
def list(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="mt-2 mb-14">
|
<div class="mt-2 mb-14">
|
||||||
<dl class="-my-4 divide-y divide-zinc-100">
|
<dl class="-my-4 divide-y dark:divide-strokedark">
|
||||||
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
|
<div :for={item <- @item} class="flex gap-4 py-4 text-sm leading-6 sm:gap-8">
|
||||||
<dt class="w-1/4 flex-none text-zinc-500"><%= item.title %></dt>
|
<dt class="w-1/4 flex-none dark:text-white"><%= item.title %></dt>
|
||||||
<dd class="text-zinc-700"><%= render_slot(item) %></dd>
|
<dd class="dark:text-white"><%= render_slot(item) %></dd>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule PinchflatWeb.CustomComponents.ButtonComponents do
|
||||||
|
@moduledoc false
|
||||||
|
use Phoenix.Component
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Render a button
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.button color="bg-primary" rounding="rounded-sm">
|
||||||
|
<span>Click me</span>
|
||||||
|
</.button>
|
||||||
|
"""
|
||||||
|
attr :color, :string, default: "bg-primary"
|
||||||
|
attr :rounding, :string, default: "rounded-sm"
|
||||||
|
attr :class, :string, default: ""
|
||||||
|
|
||||||
|
slot :inner_block, required: true
|
||||||
|
|
||||||
|
def button(assigns) do
|
||||||
|
~H"""
|
||||||
|
<button class={[
|
||||||
|
"text-center font-medium text-white",
|
||||||
|
"#{@rounding} inline-flex items-center justify-center px-10 py-4",
|
||||||
|
"#{@color}",
|
||||||
|
"hover:bg-opacity-90 lg:px-8 xl:px-10",
|
||||||
|
@class
|
||||||
|
]}>
|
||||||
|
<%= render_slot(@inner_block) %>
|
||||||
|
</button>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
defmodule PinchflatWeb.CustomComponents.TableComponents do
|
||||||
|
@moduledoc false
|
||||||
|
use Phoenix.Component
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a table component with the given rows and columns.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
<.table rows={@users}>
|
||||||
|
<:col :let={user} label="Name"><%= user.name %></:col>
|
||||||
|
</.table>
|
||||||
|
"""
|
||||||
|
attr :rows, :list, required: true
|
||||||
|
attr :table_class, :string, default: ""
|
||||||
|
|
||||||
|
attr :row_item, :any,
|
||||||
|
default: &Function.identity/1,
|
||||||
|
doc: "the function for mapping each row before calling the :col and :action slots"
|
||||||
|
|
||||||
|
slot :col, required: true do
|
||||||
|
attr :label, :string
|
||||||
|
attr :class, :string
|
||||||
|
end
|
||||||
|
|
||||||
|
def table(assigns) do
|
||||||
|
~H"""
|
||||||
|
<table class={["w-full table-auto", @table_class]}>
|
||||||
|
<thead>
|
||||||
|
<tr class="bg-gray-2 text-left dark:bg-meta-4">
|
||||||
|
<th :for={col <- @col} class="px-4 py-4 font-medium text-black dark:text-white xl:pl-11">
|
||||||
|
<%= col[:label] %>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr :for={{row, i} <- Enum.with_index(@rows)}>
|
||||||
|
<td
|
||||||
|
:for={col <- @col}
|
||||||
|
class={[
|
||||||
|
"px-4 py-5 pl-9 dark:border-strokedark xl:pl-11",
|
||||||
|
i + 1 > length(@rows) && "border-b border-[#eee] dark:border-π",
|
||||||
|
col[:class]
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<%= render_slot(col, @row_item.(row)) %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -9,7 +9,7 @@ defmodule PinchflatWeb.Layouts do
|
||||||
attr :navigate, :any, required: true
|
attr :navigate, :any, required: true
|
||||||
|
|
||||||
def sidebar_item(assigns) do
|
def sidebar_item(assigns) do
|
||||||
# I'm testing out grouping classes here. Tentative order: font, layout, animation, state-modifiers
|
# I'm testing out grouping classes here. Tentative order: font, layout, color, animation, state-modifiers
|
||||||
~H"""
|
~H"""
|
||||||
<li>
|
<li>
|
||||||
<.link
|
<.link
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
<.header />
|
<.header />
|
||||||
<main>
|
<main>
|
||||||
<div class="mx-auto max-w-screen-2xl p-4 md:p-6 2xl:p-10">
|
<div class="mx-auto max-w-screen-2xl p-4 md:p-6 2xl:p-10">
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6 xl:grid-cols-4 2xl:gap-7.5">
|
<.flash_group flash={@flash} />
|
||||||
</div>
|
<%= @inner_content %>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<div>
|
<div>
|
||||||
<h3 class="mb-4 ml-4 text-sm font-medium text-bodydark2">MENU</h3>
|
<h3 class="mb-4 ml-4 text-sm font-medium text-bodydark2">MENU</h3>
|
||||||
<ul class="mb-6 flex flex-col gap-1.5">
|
<ul class="mb-6 flex flex-col gap-1.5">
|
||||||
<.sidebar_item icon="hero-tv" text="Sources" navigate={~p"/media_sources/sources"} />
|
<.sidebar_item icon="hero-tv" text="Sources" navigate={~p"/sources"} />
|
||||||
|
|
||||||
<.sidebar_item
|
<.sidebar_item
|
||||||
icon="hero-adjustments-vertical"
|
icon="hero-adjustments-vertical"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="[scrollbar-gutter:stable]">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
@ -11,11 +11,7 @@
|
||||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body x-data="{ 'sidebarToggle': false }" class="dark text-bodydark bg-boxdark-2">
|
||||||
x-data="{ 'darkMode': true, 'sidebarToggle': false }"
|
|
||||||
x-init="darkMode = true;"
|
|
||||||
x-bind:class="{'dark text-bodydark bg-boxdark-2': darkMode === true}"
|
|
||||||
>
|
|
||||||
<%= @inner_content %>
|
<%= @inner_content %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,3 @@
|
||||||
</.link>
|
</.link>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.old_header>
|
</.old_header>
|
||||||
|
|
||||||
<.table
|
|
||||||
id="media_profiles"
|
|
||||||
rows={@media_profiles}
|
|
||||||
row_click={&JS.navigate(~p"/media_profiles/#{&1}")}
|
|
||||||
>
|
|
||||||
<:col :let={media_profile} label="Name"><%= media_profile.name %></:col>
|
|
||||||
<:col :let={media_profile} label="Output path template">
|
|
||||||
<%= media_profile.output_path_template %>
|
|
||||||
</:col>
|
|
||||||
<:action :let={media_profile}>
|
|
||||||
<div class="sr-only">
|
|
||||||
<.link navigate={~p"/media_profiles/#{media_profile}"}>Show</.link>
|
|
||||||
</div>
|
|
||||||
<.link navigate={~p"/media_profiles/#{media_profile}/edit"}>Edit</.link>
|
|
||||||
</:action>
|
|
||||||
<:action :let={media_profile}>
|
|
||||||
<.link href={~p"/media_profiles/#{media_profile}"} method="delete" data-confirm="Are you sure?">
|
|
||||||
Delete
|
|
||||||
</.link>
|
|
||||||
</:action>
|
|
||||||
</.table>
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
|
||||||
alias Pinchflat.MediaSource.Source
|
alias Pinchflat.MediaSource.Source
|
||||||
|
|
||||||
def index(conn, _params) do
|
def index(conn, _params) do
|
||||||
sources = MediaSource.list_sources()
|
sources = Repo.preload(MediaSource.list_sources(), :media_profile)
|
||||||
|
|
||||||
render(conn, :index, sources: sources)
|
render(conn, :index, sources: sources)
|
||||||
end
|
end
|
||||||
|
|
@ -23,7 +23,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
|
||||||
{:ok, source} ->
|
{:ok, source} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:info, "Source created successfully.")
|
|> put_flash(:info, "Source created successfully.")
|
||||||
|> redirect(to: ~p"/media_sources/sources/#{source}")
|
|> redirect(to: ~p"/sources/#{source}")
|
||||||
|
|
||||||
{:error, %Ecto.Changeset{} = changeset} ->
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
|
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
|
||||||
|
|
@ -53,7 +53,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
|
||||||
{:ok, source} ->
|
{:ok, source} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:info, "Source updated successfully.")
|
|> put_flash(:info, "Source updated successfully.")
|
||||||
|> redirect(to: ~p"/media_sources/sources/#{source}")
|
|> redirect(to: ~p"/sources/#{source}")
|
||||||
|
|
||||||
{:error, %Ecto.Changeset{} = changeset} ->
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
render(conn, :edit,
|
render(conn, :edit,
|
||||||
|
|
@ -70,7 +70,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:info, "Source deleted successfully.")
|
|> put_flash(:info, "Source deleted successfully.")
|
||||||
|> redirect(to: ~p"/media_sources/sources")
|
|> redirect(to: ~p"/sources")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp media_profiles do
|
defp media_profiles do
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
<.old_header>
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
Edit Source <%= @source.id %>
|
<.link navigate={~p"/sources"}>
|
||||||
<:subtitle>Use this form to manage source records in your database.</:subtitle>
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.old_header>
|
</.link>
|
||||||
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Source</h2>
|
||||||
|
</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="max-w-full overflow-x-auto">
|
||||||
|
<div class="flex flex-col gap-10">
|
||||||
<.source_form
|
<.source_form
|
||||||
changeset={@changeset}
|
changeset={@changeset}
|
||||||
media_profiles={@media_profiles}
|
media_profiles={@media_profiles}
|
||||||
action={~p"/media_sources/sources/#{@source}"}
|
action={~p"/sources/#{@source}"}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<.back navigate={~p"/media_sources/sources"}>Back to sources</.back>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,48 @@
|
||||||
<.old_header>
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
Listing Sources
|
<h2 class="text-title-md2 font-bold text-black dark:text-white">All Sources</h2>
|
||||||
<:actions>
|
<nav>
|
||||||
<.link href={~p"/media_sources/sources/new"}>
|
<.link navigate={~p"/sources/new"}>
|
||||||
<.button>New Source</.button>
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
|
<span class="font-bold mx-2">+</span> New Source
|
||||||
|
</.button>
|
||||||
</.link>
|
</.link>
|
||||||
</:actions>
|
</nav>
|
||||||
</.old_header>
|
|
||||||
|
|
||||||
<.table id="sources" rows={@sources} row_click={&JS.navigate(~p"/media_sources/sources/#{&1}")}>
|
|
||||||
<:col :let={source} label="Collection Name"><%= source.collection_name %></:col>
|
|
||||||
<:col :let={source} label="Collection ID"><%= source.collection_id %></:col>
|
|
||||||
<:action :let={source}>
|
|
||||||
<div class="sr-only">
|
|
||||||
<.link navigate={~p"/media_sources/sources/#{source}"}>Show</.link>
|
|
||||||
</div>
|
</div>
|
||||||
<.link navigate={~p"/media_sources/sources/#{source}/edit"}>Edit</.link>
|
|
||||||
</:action>
|
<div class="rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark">
|
||||||
<:action :let={source}>
|
<div class="max-w-full overflow-x-auto">
|
||||||
<.link href={~p"/media_sources/sources/#{source}"} method="delete" data-confirm="Are you sure?">
|
<div class="flex flex-col gap-10">
|
||||||
Delete
|
<.table rows={@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="Media Profile">
|
||||||
|
<.link
|
||||||
|
navigate={~p"/media_profiles/#{source.media_profile_id}"}
|
||||||
|
class="hover:text-secondary duration-200 ease-in-out"
|
||||||
|
>
|
||||||
|
<%= source.media_profile.name %>
|
||||||
</.link>
|
</.link>
|
||||||
</:action>
|
</:col>
|
||||||
|
<:col :let={source} label="" class="flex place-content-evenly">
|
||||||
|
<.link
|
||||||
|
navigate={~p"/sources/#{source.id}"}
|
||||||
|
class="hover:text-secondary duration-200 ease-in-out mx-0.5"
|
||||||
|
>
|
||||||
|
<.icon name="hero-eye" />
|
||||||
|
</.link>
|
||||||
|
<.link
|
||||||
|
navigate={~p"/sources/#{source.id}/edit"}
|
||||||
|
class="hover:text-secondary duration-200 ease-in-out mx-0.5"
|
||||||
|
>
|
||||||
|
<.icon name="hero-pencil-square" />
|
||||||
|
</.link>
|
||||||
|
</:col>
|
||||||
</.table>
|
</.table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<.old_header>
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
New Source
|
<.link navigate={~p"/sources"}>
|
||||||
<:subtitle>Use this form to manage source records in your database.</:subtitle>
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.old_header>
|
</.link>
|
||||||
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Source</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<.source_form
|
<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">
|
||||||
changeset={@changeset}
|
<div class="max-w-full overflow-x-auto">
|
||||||
media_profiles={@media_profiles}
|
<div class="flex flex-col gap-10">
|
||||||
action={~p"/media_sources/sources"}
|
<.source_form changeset={@changeset} media_profiles={@media_profiles} action={~p"/sources"} />
|
||||||
/>
|
</div>
|
||||||
|
</div>
|
||||||
<.back navigate={~p"/media_sources/sources"}>Back to sources</.back>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,38 @@
|
||||||
<.old_header>
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
Source <%= @source.id %>
|
<div class="flex gap-3 items-center">
|
||||||
<:subtitle>This is a source record from your database.</:subtitle>
|
<.link navigate={~p"/sources"}>
|
||||||
<:actions>
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
<.link href={~p"/media_sources/sources/#{@source}/edit"}>
|
|
||||||
<.button>Edit source</.button>
|
|
||||||
</.link>
|
</.link>
|
||||||
</:actions>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
||||||
</.old_header>
|
Source #<%= @source.id %>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="mt-14">Relationships</h3>
|
<nav>
|
||||||
|
<.link navigate={~p"/sources/#{@source}/edit"}>
|
||||||
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
|
<.icon name="hero-pencil-square" class="mr-2" /> Edit Source
|
||||||
|
</.button>
|
||||||
|
</.link>
|
||||||
|
</nav>
|
||||||
|
</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="max-w-full overflow-x-auto">
|
||||||
|
<div class="flex flex-col gap-10 dark:text-white">
|
||||||
|
<h3 class="mt-14 font-bold text-xl">Relationships</h3>
|
||||||
<.list>
|
<.list>
|
||||||
<:item title="media_profile">
|
<:item title="media_profile">
|
||||||
<.link href={~p"/media_profiles/#{@source.media_profile}"}>
|
<.link
|
||||||
|
navigate={~p"/media_profiles/#{@source.media_profile_id}"}
|
||||||
|
class="hover:text-secondary duration-200 ease-in-out"
|
||||||
|
>
|
||||||
<%= @source.media_profile.name %>
|
<%= @source.media_profile.name %>
|
||||||
</.link>
|
</.link>
|
||||||
</:item>
|
</:item>
|
||||||
</.list>
|
</.list>
|
||||||
|
|
||||||
<h3>Attributes</h3>
|
<h3 class="font-bold text-xl">Attributes</h3>
|
||||||
<.list_items_from_map map={Map.from_struct(@source)} />
|
<.list_items_from_map map={Map.from_struct(@source)} />
|
||||||
|
</div>
|
||||||
<.back navigate={~p"/media_sources/sources"}>Back to sources</.back>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,13 @@
|
||||||
Oops, something went wrong! Please check the errors below.
|
Oops, something went wrong! Please check the errors below.
|
||||||
</.error>
|
</.error>
|
||||||
|
|
||||||
|
<.input
|
||||||
|
field={f[:original_url]}
|
||||||
|
type="text"
|
||||||
|
label="Source URL"
|
||||||
|
help="URL of a channel or playlist (required)"
|
||||||
|
/>
|
||||||
|
|
||||||
<.input field={f[:friendly_name]} type="text" label="Friendly Name" />
|
<.input field={f[:friendly_name]} type="text" label="Friendly Name" />
|
||||||
|
|
||||||
<.input
|
<.input
|
||||||
|
|
@ -16,21 +23,25 @@
|
||||||
field={f[:collection_type]}
|
field={f[:collection_type]}
|
||||||
options={friendly_collection_types()}
|
options={friendly_collection_types()}
|
||||||
type="select"
|
type="select"
|
||||||
label="Collection Type"
|
label="Source Type"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.input field={f[:original_url]} type="text" label="Source URL" />
|
|
||||||
|
|
||||||
<.input
|
<.input
|
||||||
field={f[:index_frequency_minutes]}
|
field={f[:index_frequency_minutes]}
|
||||||
options={friendly_index_frequencies()}
|
options={friendly_index_frequencies()}
|
||||||
type="select"
|
type="select"
|
||||||
label="Index Frequency"
|
label="Index Frequency"
|
||||||
|
help="Roughly how often to check for media to download"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.input field={f[:download_media]} type="checkbox" label="Download Media?" />
|
<.input
|
||||||
|
field={f[:download_media]}
|
||||||
|
type="toggle"
|
||||||
|
label="Download Media?"
|
||||||
|
help="Unchecking still indexes media but it won't be downloaded"
|
||||||
|
/>
|
||||||
|
|
||||||
<:actions>
|
<:actions>
|
||||||
<.button>Save Source</.button>
|
<.button class="mt-15 mb-5 sm:mb-7.5">Save Source</.button>
|
||||||
</:actions>
|
</:actions>
|
||||||
</.simple_form>
|
</.simple_form>
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,7 @@ defmodule PinchflatWeb.Router do
|
||||||
get "/", PageController, :home
|
get "/", PageController, :home
|
||||||
|
|
||||||
resources "/media_profiles", MediaProfiles.MediaProfileController
|
resources "/media_profiles", MediaProfiles.MediaProfileController
|
||||||
|
resources "/sources", MediaSources.SourceController
|
||||||
scope "/media_sources", MediaSources do
|
|
||||||
resources "/sources", SourceController
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Other scopes may use custom stacks.
|
# Other scopes may use custom stacks.
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,14 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
|
|
||||||
describe "index" do
|
describe "index" do
|
||||||
test "lists all sources", %{conn: conn} do
|
test "lists all sources", %{conn: conn} do
|
||||||
conn = get(conn, ~p"/media_sources/sources")
|
conn = get(conn, ~p"/sources")
|
||||||
assert html_response(conn, 200) =~ "Listing Sources"
|
assert html_response(conn, 200) =~ "All Sources"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "new source" do
|
describe "new source" do
|
||||||
test "renders form", %{conn: conn} do
|
test "renders form", %{conn: conn} do
|
||||||
conn = get(conn, ~p"/media_sources/sources/new")
|
conn = get(conn, ~p"/sources/new")
|
||||||
assert html_response(conn, 200) =~ "New Source"
|
assert html_response(conn, 200) =~ "New Source"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -43,17 +43,17 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
describe "create source" do
|
describe "create source" do
|
||||||
test "redirects to show when data is valid", %{conn: conn, create_attrs: create_attrs} do
|
test "redirects to show when data is valid", %{conn: conn, create_attrs: create_attrs} do
|
||||||
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
|
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
|
||||||
conn = post(conn, ~p"/media_sources/sources", source: create_attrs)
|
conn = post(conn, ~p"/sources", source: create_attrs)
|
||||||
|
|
||||||
assert %{id: id} = redirected_params(conn)
|
assert %{id: id} = redirected_params(conn)
|
||||||
assert redirected_to(conn) == ~p"/media_sources/sources/#{id}"
|
assert redirected_to(conn) == ~p"/sources/#{id}"
|
||||||
|
|
||||||
conn = get(conn, ~p"/media_sources/sources/#{id}")
|
conn = get(conn, ~p"/sources/#{id}")
|
||||||
assert html_response(conn, 200) =~ "Source #{id}"
|
assert html_response(conn, 200) =~ "Source ##{id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renders errors when data is invalid", %{conn: conn, invalid_attrs: invalid_attrs} do
|
test "renders errors when data is invalid", %{conn: conn, invalid_attrs: invalid_attrs} do
|
||||||
conn = post(conn, ~p"/media_sources/sources", source: invalid_attrs)
|
conn = post(conn, ~p"/sources", source: invalid_attrs)
|
||||||
assert html_response(conn, 200) =~ "New Source"
|
assert html_response(conn, 200) =~ "New Source"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -62,7 +62,7 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
setup [:create_source]
|
setup [:create_source]
|
||||||
|
|
||||||
test "renders form for editing chosen source", %{conn: conn, source: source} do
|
test "renders form for editing chosen source", %{conn: conn, source: source} do
|
||||||
conn = get(conn, ~p"/media_sources/sources/#{source}/edit")
|
conn = get(conn, ~p"/sources/#{source}/edit")
|
||||||
assert html_response(conn, 200) =~ "Edit Source"
|
assert html_response(conn, 200) =~ "Edit Source"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -73,10 +73,10 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
test "redirects when data is valid", %{conn: conn, source: source, update_attrs: update_attrs} do
|
test "redirects when data is valid", %{conn: conn, source: source, update_attrs: update_attrs} do
|
||||||
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
|
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
|
||||||
|
|
||||||
conn = put(conn, ~p"/media_sources/sources/#{source}", source: update_attrs)
|
conn = put(conn, ~p"/sources/#{source}", source: update_attrs)
|
||||||
assert redirected_to(conn) == ~p"/media_sources/sources/#{source}"
|
assert redirected_to(conn) == ~p"/sources/#{source}"
|
||||||
|
|
||||||
conn = get(conn, ~p"/media_sources/sources/#{source}")
|
conn = get(conn, ~p"/sources/#{source}")
|
||||||
assert html_response(conn, 200) =~ "https://www.youtube.com/source/321xyz"
|
assert html_response(conn, 200) =~ "https://www.youtube.com/source/321xyz"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
source: source,
|
source: source,
|
||||||
invalid_attrs: invalid_attrs
|
invalid_attrs: invalid_attrs
|
||||||
} do
|
} do
|
||||||
conn = put(conn, ~p"/media_sources/sources/#{source}", source: invalid_attrs)
|
conn = put(conn, ~p"/sources/#{source}", source: invalid_attrs)
|
||||||
assert html_response(conn, 200) =~ "Edit Source"
|
assert html_response(conn, 200) =~ "Edit Source"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -94,11 +94,11 @@ defmodule PinchflatWeb.SourceControllerTest do
|
||||||
setup [:create_source]
|
setup [:create_source]
|
||||||
|
|
||||||
test "deletes chosen source", %{conn: conn, source: source} do
|
test "deletes chosen source", %{conn: conn, source: source} do
|
||||||
conn = delete(conn, ~p"/media_sources/sources/#{source}")
|
conn = delete(conn, ~p"/sources/#{source}")
|
||||||
assert redirected_to(conn) == ~p"/media_sources/sources"
|
assert redirected_to(conn) == ~p"/sources"
|
||||||
|
|
||||||
assert_error_sent 404, fn ->
|
assert_error_sent 404, fn ->
|
||||||
get(conn, ~p"/media_sources/sources/#{source}")
|
get(conn, ~p"/sources/#{source}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue