diff --git a/.gitignore b/.gitignore
index 7ab4c729..f0a1e888 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,4 @@ npm-debug.log
.env
.DS_Store
scratchpad.md
+/scratchpad/
diff --git a/assets/css/app.css b/assets/css/app.css
index 5dccbd42..e499401e 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -2,4 +2,30 @@
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
+@import './satoshi';
+
/* This file is for your main application CSS */
+[x-cloak] {
+ display: none !important;
+}
+
+@layer base {
+ body {
+ @apply relative z-1 bg-whiten font-satoshi text-base font-normal text-body;
+ }
+}
+
+@layer components {
+}
+
+@layer utilities {
+ /* Chrome, Safari and Opera */
+ .no-scrollbar::-webkit-scrollbar {
+ display: none;
+ }
+
+ .no-scrollbar {
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ }
+}
diff --git a/assets/css/satoshi.css b/assets/css/satoshi.css
new file mode 100644
index 00000000..272640a4
--- /dev/null
+++ b/assets/css/satoshi.css
@@ -0,0 +1,102 @@
+/**
+ * @license
+ *
+ * Font Family: Satoshi
+ * Designed by: Deni Anggara
+ * URL: https://www.fontshare.com/fonts/satoshi
+ * © 2023 Indian Type Foundry
+ *
+ * Font Styles:
+ * Satoshi Light
+ * Satoshi Light Italic
+ * Satoshi Regular
+ * Satoshi Italic
+ * Satoshi Medium
+ * Satoshi Medium Italic
+ * Satoshi Bold
+ * Satoshi Bold Italic
+ * Satoshi Black
+ * Satoshi Black Italic
+ *
+*/
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-Light.woff2'), url('/fonts/satoshi/Satoshi-Light.woff'),
+ url('/fonts/satoshi/Satoshi-Light.ttf');
+ font-weight: 300;
+ font-display: swap;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-LightItalic.woff2'),
+ url('/fonts/satoshi/Satoshi-LightItalic.woff'), url('/fonts/satoshi/Satoshi-LightItalic.ttf');
+ font-weight: 300;
+ font-display: swap;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-Regular.woff2'), url('/fonts/satoshi/Satoshi-Regular.woff'),
+ url('/fonts/satoshi/Satoshi-Regular.ttf');
+ font-weight: 400;
+ font-display: swap;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-Italic.woff2'), url('/fonts/satoshi/Satoshi-Italic.woff'),
+ url('/fonts/satoshi/Satoshi-Italic.ttf');
+ font-weight: 400;
+ font-display: swap;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-Medium.woff2'), url('/fonts/satoshi/Satoshi-Medium.woff'),
+ url('/fonts/satoshi/Satoshi-Medium.ttf');
+ font-weight: 500;
+ font-display: swap;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-MediumItalic.woff2'),
+ url('/fonts/satoshi/Satoshi-MediumItalic.woff'), url('/fonts/satoshi/Satoshi-MediumItalic.ttf');
+ font-weight: 500;
+ font-display: swap;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-Bold.woff2'), url('/fonts/satoshi/Satoshi-Bold.woff'),
+ url('/fonts/satoshi/Satoshi-Bold.ttf');
+ font-weight: 700;
+ font-display: swap;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-BoldItalic.woff2'), url('/fonts/satoshi/Satoshi-BoldItalic.woff'),
+ url('/fonts/satoshi/Satoshi-BoldItalic.ttf');
+ font-weight: 700;
+ font-display: swap;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Satoshi';
+ src: url('/fonts/satoshi/Satoshi-BlackItalic.woff2'),
+ url('/fonts/satoshi/Satoshi-BlackItalic.woff'), url('/fonts/satoshi/Satoshi-BlackItalic.ttf');
+ font-weight: 900;
+ font-display: swap;
+ font-style: italic;
+}
diff --git a/assets/js/app.js b/assets/js/app.js
index 4208c6d7..cc1f5fc6 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -21,10 +21,21 @@ import 'phoenix_html'
import { Socket } from 'phoenix'
import { LiveSocket } from 'phoenix_live_view'
import topbar from '../vendor/topbar'
+import Alpine from 'alpinejs'
+
+window.Alpine = Alpine
+Alpine.start()
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute('content')
let liveSocket = new LiveSocket('/live', Socket, {
- params: { _csrf_token: csrfToken }
+ params: { _csrf_token: csrfToken },
+ dom: {
+ onBeforeElUpdated(from, to) {
+ if (from._x_dataStack) {
+ window.Alpine.clone(from, to)
+ }
+ }
+ }
})
// Show progress bar on live navigation and form submits
diff --git a/assets/package.json b/assets/package.json
index 9cd9d2b0..46118dd7 100644
--- a/assets/package.json
+++ b/assets/package.json
@@ -1,3 +1,6 @@
{
- "description": "Use this one for actual JS deps used in-app"
+ "description": "Use this one for actual JS deps used in-app",
+ "dependencies": {
+ "alpinejs": "^3.13.5"
+ }
}
diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js
index a360ecc8..08f407f7 100644
--- a/assets/tailwind.config.js
+++ b/assets/tailwind.config.js
@@ -2,15 +2,288 @@
// https://tailwindcss.com/docs/configuration
const plugin = require('tailwindcss/plugin')
+const defaultTheme = require('tailwindcss/defaultTheme')
const fs = require('fs')
const path = require('path')
module.exports = {
content: ['./js/**/*.js', '../lib/pinchflat_web.ex', '../lib/pinchflat_web/**/*.*ex'],
+ darkMode: 'class',
theme: {
+ fontFamily: {
+ satoshi: ['Satoshi', 'sans-serif']
+ },
+ screens: {
+ '2xsm': '375px',
+ xsm: '425px',
+ '3xl': '2000px',
+ ...defaultTheme.screens
+ },
extend: {
colors: {
- brand: '#FD4F00'
+ current: 'currentColor',
+ transparent: 'transparent',
+ white: '#FFFFFF',
+ black: '#1C2434',
+ 'black-2': '#010101',
+ body: '#64748B',
+ bodydark: '#AEB7C0',
+ bodydark1: '#DEE4EE',
+ bodydark2: '#8A99AF',
+ primary: '#3C50E0',
+ secondary: '#80CAEE',
+ stroke: '#E2E8F0',
+ gray: '#EFF4FB',
+ graydark: '#333A48',
+ 'gray-2': '#F7F9FC',
+ 'gray-3': '#FAFAFA',
+ whiten: '#F1F5F9',
+ whiter: '#F5F7FD',
+ boxdark: '#24303F',
+ 'boxdark-2': '#1A222C',
+ strokedark: '#2E3A47',
+ 'form-strokedark': '#3d4d60',
+ 'form-input': '#1d2a39',
+ 'meta-1': '#DC3545',
+ 'meta-2': '#EFF2F7',
+ 'meta-3': '#10B981',
+ 'meta-4': '#313D4A',
+ 'meta-5': '#259AE6',
+ 'meta-6': '#FFBA00',
+ 'meta-7': '#FF6766',
+ 'meta-8': '#F0950C',
+ 'meta-9': '#E5E7EB',
+ success: '#219653',
+ danger: '#D34053',
+ warning: '#FFA70B'
+ },
+ fontSize: {
+ 'title-xxl': ['44px', '55px'],
+ 'title-xl': ['36px', '45px'],
+ 'title-xl2': ['33px', '45px'],
+ 'title-lg': ['28px', '35px'],
+ 'title-md': ['24px', '30px'],
+ 'title-md2': ['26px', '30px'],
+ 'title-sm': ['20px', '26px'],
+ 'title-xsm': ['18px', '24px']
+ },
+ spacing: {
+ 4.5: '1.125rem',
+ 5.5: '1.375rem',
+ 6.5: '1.625rem',
+ 7.5: '1.875rem',
+ 8.5: '2.125rem',
+ 9.5: '2.375rem',
+ 10.5: '2.625rem',
+ 11: '2.75rem',
+ 11.5: '2.875rem',
+ 12.5: '3.125rem',
+ 13: '3.25rem',
+ 13.5: '3.375rem',
+ 14: '3.5rem',
+ 14.5: '3.625rem',
+ 15: '3.75rem',
+ 15.5: '3.875rem',
+ 16: '4rem',
+ 16.5: '4.125rem',
+ 17: '4.25rem',
+ 17.5: '4.375rem',
+ 18: '4.5rem',
+ 18.5: '4.625rem',
+ 19: '4.75rem',
+ 19.5: '4.875rem',
+ 21: '5.25rem',
+ 21.5: '5.375rem',
+ 22: '5.5rem',
+ 22.5: '5.625rem',
+ 24.5: '6.125rem',
+ 25: '6.25rem',
+ 25.5: '6.375rem',
+ 26: '6.5rem',
+ 27: '6.75rem',
+ 27.5: '6.875rem',
+ 29: '7.25rem',
+ 29.5: '7.375rem',
+ 30: '7.5rem',
+ 31: '7.75rem',
+ 32.5: '8.125rem',
+ 34: '8.5rem',
+ 34.5: '8.625rem',
+ 35: '8.75rem',
+ 36.5: '9.125rem',
+ 37.5: '9.375rem',
+ 39: '9.75rem',
+ 39.5: '9.875rem',
+ 40: '10rem',
+ 42.5: '10.625rem',
+ 44: '11rem',
+ 45: '11.25rem',
+ 46: '11.5rem',
+ 47.5: '11.875rem',
+ 49: '12.25rem',
+ 50: '12.5rem',
+ 52: '13rem',
+ 52.5: '13.125rem',
+ 54: '13.5rem',
+ 54.5: '13.625rem',
+ 55: '13.75rem',
+ 55.5: '13.875rem',
+ 59: '14.75rem',
+ 60: '15rem',
+ 62.5: '15.625rem',
+ 65: '16.25rem',
+ 67: '16.75rem',
+ 67.5: '16.875rem',
+ 70: '17.5rem',
+ 72.5: '18.125rem',
+ 73: '18.25rem',
+ 75: '18.75rem',
+ 90: '22.5rem',
+ 94: '23.5rem',
+ 95: '23.75rem',
+ 100: '25rem',
+ 115: '28.75rem',
+ 125: '31.25rem',
+ 132.5: '33.125rem',
+ 150: '37.5rem',
+ 171.5: '42.875rem',
+ 180: '45rem',
+ 187.5: '46.875rem',
+ 203: '50.75rem',
+ 230: '57.5rem',
+ 242.5: '60.625rem'
+ },
+ maxWidth: {
+ 2.5: '0.625rem',
+ 3: '0.75rem',
+ 4: '1rem',
+ 11: '2.75rem',
+ 13: '3.25rem',
+ 14: '3.5rem',
+ 15: '3.75rem',
+ 22.5: '5.625rem',
+ 25: '6.25rem',
+ 30: '7.5rem',
+ 34: '8.5rem',
+ 35: '8.75rem',
+ 40: '10rem',
+ 42.5: '10.625rem',
+ 44: '11rem',
+ 45: '11.25rem',
+ 60: '15rem',
+ 70: '17.5rem',
+ 90: '22.5rem',
+ 94: '23.5rem',
+ 125: '31.25rem',
+ 132.5: '33.125rem',
+ 142.5: '35.625rem',
+ 150: '37.5rem',
+ 180: '45rem',
+ 203: '50.75rem',
+ 230: '57.5rem',
+ 242.5: '60.625rem',
+ 270: '67.5rem',
+ 280: '70rem',
+ 292.5: '73.125rem'
+ },
+ maxHeight: {
+ 35: '8.75rem',
+ 70: '17.5rem',
+ 90: '22.5rem',
+ 550: '34.375rem',
+ 300: '18.75rem'
+ },
+ minWidth: {
+ 22.5: '5.625rem',
+ 42.5: '10.625rem',
+ 47.5: '11.875rem',
+ 75: '18.75rem'
+ },
+ zIndex: {
+ 999999: '999999',
+ 99999: '99999',
+ 9999: '9999',
+ 999: '999',
+ 99: '99',
+ 9: '9',
+ 1: '1'
+ },
+ opacity: {
+ 65: '.65'
+ },
+ transitionProperty: { width: 'width', stroke: 'stroke' },
+ borderWidth: {
+ 6: '6px'
+ },
+ boxShadow: {
+ default: '0px 8px 13px -3px rgba(0, 0, 0, 0.07)',
+ card: '0px 1px 3px rgba(0, 0, 0, 0.12)',
+ 'card-2': '0px 1px 2px rgba(0, 0, 0, 0.05)',
+ switcher:
+ '0px 2px 4px rgba(0, 0, 0, 0.2), inset 0px 2px 2px #FFFFFF, inset 0px -1px 1px rgba(0, 0, 0, 0.1)',
+ 'switch-1': '0px 0px 5px rgba(0, 0, 0, 0.15)',
+ 1: '0px 1px 3px rgba(0, 0, 0, 0.08)',
+ 2: '0px 1px 4px rgba(0, 0, 0, 0.12)',
+ 3: '0px 1px 5px rgba(0, 0, 0, 0.14)',
+ 4: '0px 4px 10px rgba(0, 0, 0, 0.12)',
+ 5: '0px 1px 1px rgba(0, 0, 0, 0.15)',
+ 6: '0px 3px 15px rgba(0, 0, 0, 0.1)',
+ 7: '-5px 0 0 #313D4A, 5px 0 0 #313D4A',
+ 8: '1px 0 0 #313D4A, -1px 0 0 #313D4A, 0 1px 0 #313D4A, 0 -1px 0 #313D4A, 0 3px 13px rgb(0 0 0 / 8%)'
+ },
+ dropShadow: {
+ 1: '0px 1px 0px #E2E8F0',
+ 2: '0px 1px 4px rgba(0, 0, 0, 0.12)'
+ },
+ keyframes: {
+ linspin: {
+ '100%': { transform: 'rotate(360deg)' }
+ },
+ easespin: {
+ '12.5%': { transform: 'rotate(135deg)' },
+ '25%': { transform: 'rotate(270deg)' },
+ '37.5%': { transform: 'rotate(405deg)' },
+ '50%': { transform: 'rotate(540deg)' },
+ '62.5%': { transform: 'rotate(675deg)' },
+ '75%': { transform: 'rotate(810deg)' },
+ '87.5%': { transform: 'rotate(945deg)' },
+ '100%': { transform: 'rotate(1080deg)' }
+ },
+ 'left-spin': {
+ '0%': { transform: 'rotate(130deg)' },
+ '50%': { transform: 'rotate(-5deg)' },
+ '100%': { transform: 'rotate(130deg)' }
+ },
+ 'right-spin': {
+ '0%': { transform: 'rotate(-130deg)' },
+ '50%': { transform: 'rotate(5deg)' },
+ '100%': { transform: 'rotate(-130deg)' }
+ },
+ rotating: {
+ '0%, 100%': { transform: 'rotate(360deg)' },
+ '50%': { transform: 'rotate(0deg)' }
+ },
+ topbottom: {
+ '0%, 100%': { transform: 'translate3d(0, -100%, 0)' },
+ '50%': { transform: 'translate3d(0, 0, 0)' }
+ },
+ bottomtop: {
+ '0%, 100%': { transform: 'translate3d(0, 0, 0)' },
+ '50%': { transform: 'translate3d(0, -100%, 0)' }
+ }
+ },
+ animation: {
+ linspin: 'linspin 1568.2353ms linear infinite',
+ easespin: 'easespin 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both',
+ 'left-spin': 'left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both',
+ 'right-spin': 'right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both',
+ 'ping-once': 'ping 5s cubic-bezier(0, 0, 0.2, 1)',
+ rotating: 'rotating 30s linear infinite',
+ topbottom: 'topbottom 60s infinite alternate linear',
+ bottomtop: 'bottomtop 60s infinite alternate linear',
+ 'spin-1.5': 'spin 1.5s linear infinite',
+ 'spin-2': 'spin 2s linear infinite',
+ 'spin-3': 'spin 3s linear infinite'
}
}
},
diff --git a/assets/yarn.lock b/assets/yarn.lock
index fb57ccd1..5d8ae6d9 100644
--- a/assets/yarn.lock
+++ b/assets/yarn.lock
@@ -2,3 +2,21 @@
# yarn lockfile v1
+"@vue/reactivity@~3.1.1":
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.1.5.tgz#dbec4d9557f7c8f25c2635db1e23a78a729eb991"
+ integrity sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==
+ dependencies:
+ "@vue/shared" "3.1.5"
+
+"@vue/shared@3.1.5":
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.1.5.tgz#74ee3aad995d0a3996a6bb9533d4d280514ede03"
+ integrity sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==
+
+alpinejs@^3.13.5:
+ version "3.13.5"
+ resolved "https://registry.yarnpkg.com/alpinejs/-/alpinejs-3.13.5.tgz#c06f067e847a295085b4c6f76c42a6a35499d953"
+ integrity sha512-1d2XeNGN+Zn7j4mUAKXtAgdc4/rLeadyTMWeJGXF5DzwawPBxwTiBhFFm6w/Ei8eJxUZeyNWWSD9zknfdz1kEw==
+ dependencies:
+ "@vue/reactivity" "~3.1.1"
diff --git a/lib/pinchflat/profiles/media_profile.ex b/lib/pinchflat/profiles/media_profile.ex
index 5e4a3747..0d7fad9d 100644
--- a/lib/pinchflat/profiles/media_profile.ex
+++ b/lib/pinchflat/profiles/media_profile.ex
@@ -27,7 +27,8 @@ defmodule Pinchflat.Profiles.MediaProfile do
schema "media_profiles" do
field :name, :string
- field :output_path_template, :string
+
+ field :output_path_template, :string, default: "/{{ uploader }}/{{ title }}.{{ ext }}"
field :download_subs, :boolean, default: true
field :download_auto_subs, :boolean, default: true
diff --git a/lib/pinchflat_web.ex b/lib/pinchflat_web.ex
index 036a9b15..05187a18 100644
--- a/lib/pinchflat_web.ex
+++ b/lib/pinchflat_web.ex
@@ -84,8 +84,10 @@ defmodule PinchflatWeb do
# HTML escaping functionality
import Phoenix.HTML
# Core UI components and translation
- import PinchflatWeb.CoreComponents
import PinchflatWeb.Gettext
+ import PinchflatWeb.CoreComponents
+ import PinchflatWeb.CustomComponents.TableComponents
+ import PinchflatWeb.CustomComponents.ButtonComponents
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
diff --git a/lib/pinchflat_web/components/core_components.ex b/lib/pinchflat_web/components/core_components.ex
index c20f3ca1..cc655403 100644
--- a/lib/pinchflat_web/components/core_components.ex
+++ b/lib/pinchflat_web/components/core_components.ex
@@ -201,46 +201,14 @@ defmodule PinchflatWeb.CoreComponents do
def simple_form(assigns) do
~H"""
<.form :let={f} for={@for} as={@as} {@rest}>
-
- <%= render_slot(@inner_block, f) %>
-
- <%= render_slot(action, f) %>
-
+ <%= render_slot(@inner_block, f) %>
+
+ <%= render_slot(action, f) %>
"""
end
- @doc """
- Renders a button.
-
- ## Examples
-
- <.button>Send!
- <.button phx-click="go" class="ml-2">Send!
- """
- 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"""
-
- <%= render_slot(@inner_block) %>
-
- """
- end
-
@doc """
Renders an input with label and error messages.
@@ -270,11 +238,12 @@ defmodule PinchflatWeb.CoreComponents do
attr :name, :any
attr :label, :string, default: nil
attr :value, :any
+ attr :help, :string, default: nil
attr :type, :string,
default: "text",
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,
doc: "a form field struct retrieved from the form, for example: @form[:email]"
@@ -308,7 +277,7 @@ defmodule PinchflatWeb.CoreComponents do
~H"""
-
+
<%= @label %>
+ <.help :if={@help}><%= @help %>
<.error :for={msg <- @errors}><%= msg %>
"""
end
+ def input(%{type: "toggle"} = assigns) do
+ assigns =
+ assign_new(assigns, :checked, fn ->
+ Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value])
+ end)
+
+ ~H"""
+
+ <.label for={@id}><%= @label %>
+
+
+
+
+ <.help :if={@help}><%= @help %>
+ <.error :for={msg <- @errors}><%= msg %>
+
+
+ """
+ end
+
def input(%{type: "select"} = assigns) do
~H"""
@@ -333,13 +340,17 @@ defmodule PinchflatWeb.CoreComponents do
<%= @prompt %>
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
+ <.help :if={@help}><%= @help %>
<.error :for={msg <- @errors}><%= msg %>
"""
@@ -360,6 +371,7 @@ defmodule PinchflatWeb.CoreComponents do
]}
{@rest}
><%= Phoenix.HTML.Form.normalize_value("textarea", @value) %>
+ <.help :if={@help}><%= @help %>
<.error :for={msg <- @errors}><%= msg %>
"""
@@ -376,18 +388,32 @@ defmodule PinchflatWeb.CoreComponents do
id={@id}
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
class={[
- "mt-2 block w-full rounded-lg text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6",
- "phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400",
- @errors == [] && "border-zinc-300 focus:border-zinc-400",
+ "w-full rounded-lg border-[1.5px] border-stroke bg-transparent px-5 py-3 font-normal text-black",
+ "outline-none transition focus:border-primary active:border-primary disabled:cursor-default disabled:bg-whiter",
+ "dark:border-form-strokedark dark:bg-form-input dark:text-white dark:focus:border-primary",
@errors != [] && "border-rose-400 focus:border-rose-400"
]}
{@rest}
/>
+ <.help :if={@help}><%= @help %>
<.error :for={msg <- @errors}><%= msg %>
"""
end
+ @doc """
+ Renders help text.
+ """
+ slot :inner_block, required: true
+
+ def help(assigns) do
+ ~H"""
+
+ <%= render_slot(@inner_block) %>
+
+ """
+ end
+
@doc """
Renders a label.
"""
@@ -396,7 +422,7 @@ defmodule PinchflatWeb.CoreComponents do
def label(assigns) do
~H"""
-
+
<%= render_slot(@inner_block) %>
"""
@@ -409,7 +435,7 @@ defmodule PinchflatWeb.CoreComponents do
def error(assigns) do
~H"""
-
+
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
<%= render_slot(@inner_block) %>
@@ -425,7 +451,7 @@ defmodule PinchflatWeb.CoreComponents do
slot :subtitle
slot :actions
- def header(assigns) do
+ def old_header(assigns) do
~H"""
@@ -446,10 +472,10 @@ defmodule PinchflatWeb.CoreComponents do
## Examples
- <.table id="users" rows={@users}>
+ <.old_table id="users" rows={@users}>
<:col :let={user} label="id"><%= user.id %>
<:col :let={user} label="username"><%= user.username %>
-
+
"""
attr :id, :string, required: true
attr :rows, :list, required: true
@@ -466,56 +492,54 @@ defmodule PinchflatWeb.CoreComponents do
slot :action, doc: "the slot for showing user actions in the last table column"
- def table(assigns) do
+ def old_table(assigns) do
assigns =
with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do
assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end)
end
~H"""
-
-
-
-
- <%= col[:label] %>
-
- <%= gettext("Actions") %>
-
-
-
-
-
-
-
-
-
- <%= render_slot(col, @row_item.(row)) %>
-
-
-
-
-
-
-
- <%= render_slot(action, @row_item.(row)) %>
-
-
-
-
-
-
-
+
+
+
+ <%= col[:label] %>
+
+ <%= gettext("Actions") %>
+
+
+
+
+
+
+
+
+
+ <%= render_slot(col, @row_item.(row)) %>
+
+
+
+
+
+
+
+ <%= render_slot(action, @row_item.(row)) %>
+
+
+
+
+
+
"""
end
@@ -536,10 +560,10 @@ defmodule PinchflatWeb.CoreComponents do
def list(assigns) do
~H"""
-
+
-
<%= item.title %>
- <%= render_slot(item) %>
+ <%= item.title %>
+ <%= render_slot(item) %>
diff --git a/lib/pinchflat_web/components/custom_components/button_components.ex b/lib/pinchflat_web/components/custom_components/button_components.ex
new file mode 100644
index 00000000..5949ae08
--- /dev/null
+++ b/lib/pinchflat_web/components/custom_components/button_components.ex
@@ -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">
+
Click me
+
+ """
+ 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"""
+
+ <%= render_slot(@inner_block) %>
+
+ """
+ end
+end
diff --git a/lib/pinchflat_web/components/custom_components/table_components.ex b/lib/pinchflat_web/components/custom_components/table_components.ex
new file mode 100644
index 00000000..fbe897c4
--- /dev/null
+++ b/lib/pinchflat_web/components/custom_components/table_components.ex
@@ -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 %>
+
+ """
+ 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"""
+
+
+
+
+ <%= col[:label] %>
+
+
+
+
+
+ length(@rows) && "border-b border-[#eee] dark:border-π",
+ col[:class]
+ ]}
+ >
+ <%= render_slot(col, @row_item.(row)) %>
+
+
+
+
+ """
+ end
+end
diff --git a/lib/pinchflat_web/components/layouts.ex b/lib/pinchflat_web/components/layouts.ex
index f954088f..42172ec0 100644
--- a/lib/pinchflat_web/components/layouts.ex
+++ b/lib/pinchflat_web/components/layouts.ex
@@ -2,4 +2,28 @@ defmodule PinchflatWeb.Layouts do
use PinchflatWeb, :html
embed_templates "layouts/*"
+ embed_templates "layouts/partials/*"
+
+ attr :icon, :string, required: true
+ attr :text, :string, required: true
+ attr :navigate, :any, required: true
+
+ def sidebar_item(assigns) do
+ # I'm testing out grouping classes here. Tentative order: font, layout, color, animation, state-modifiers
+ ~H"""
+
+ <.link
+ navigate={@navigate}
+ class={[
+ "font-medium text-bodydark1",
+ "group relative flex items-center gap-2.5 rounded-sm px-4 py-2 duration-300 ease-in-out",
+ "duration-300 ease-in-out",
+ "hover:bg-graydark dark:hover:bg-meta-4"
+ ]}
+ >
+ <.icon name={@icon} /> <%= @text %>
+
+
+ """
+ end
end
diff --git a/lib/pinchflat_web/components/layouts/app.html.heex b/lib/pinchflat_web/components/layouts/app.html.heex
index e23bfc81..a582e8ca 100644
--- a/lib/pinchflat_web/components/layouts/app.html.heex
+++ b/lib/pinchflat_web/components/layouts/app.html.heex
@@ -1,32 +1,13 @@
-
-
-
-
-
-
-
- v<%= Application.spec(:phoenix, :vsn) %>
-
-
-
+
+ <.sidebar />
+
+
+ <.header />
+
+
+ <.flash_group flash={@flash} />
+ <%= @inner_content %>
+
+
-
-
-
- <.flash_group flash={@flash} />
- <%= @inner_content %>
-
-
+
diff --git a/lib/pinchflat_web/components/layouts/partials/header.html.heex b/lib/pinchflat_web/components/layouts/partials/header.html.heex
new file mode 100644
index 00000000..a89a1626
--- /dev/null
+++ b/lib/pinchflat_web/components/layouts/partials/header.html.heex
@@ -0,0 +1,29 @@
+
diff --git a/lib/pinchflat_web/components/layouts/partials/sidebar.html.heex b/lib/pinchflat_web/components/layouts/partials/sidebar.html.heex
new file mode 100644
index 00000000..8f27e76e
--- /dev/null
+++ b/lib/pinchflat_web/components/layouts/partials/sidebar.html.heex
@@ -0,0 +1,29 @@
+
diff --git a/lib/pinchflat_web/components/layouts/root.html.heex b/lib/pinchflat_web/components/layouts/root.html.heex
index c33013a6..781ede59 100644
--- a/lib/pinchflat_web/components/layouts/root.html.heex
+++ b/lib/pinchflat_web/components/layouts/root.html.heex
@@ -1,5 +1,5 @@
-
+
@@ -11,7 +11,7 @@
-
+
<%= @inner_content %>
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/edit.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/edit.html.heex
index ca35b198..6570b9b4 100644
--- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/edit.html.heex
+++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/edit.html.heex
@@ -1,8 +1,14 @@
-<.header>
- Edit Media profile <%= @media_profile.id %>
- <:subtitle>Use this form to manage media_profile records in your database.
-
+
+ <.link navigate={~p"/media_profiles"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
+
+
Edit Media Profile
+
-<.media_profile_form changeset={@changeset} action={~p"/media_profiles/#{@media_profile}"} />
-
-<.back navigate={~p"/media_profiles"}>Back to media_profiles
+
+
+
+ <.media_profile_form changeset={@changeset} action={~p"/media_profiles/#{@media_profile}"} />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/index.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/index.html.heex
index eec319c3..a0097029 100644
--- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/index.html.heex
+++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/index.html.heex
@@ -1,30 +1,39 @@
-<.header>
- Listing Media profiles
- <:actions>
- <.link href={~p"/media_profiles/new"}>
- <.button>New Media profile
+
+
All Media Profiles
+
+ <.link navigate={~p"/media_profiles/new"}>
+ <.button color="bg-primary" rounding="rounded-full">
+ + New Media Profile
+
-
-
+
+
-<.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 :let={media_profile} label="Output path template">
- <%= media_profile.output_path_template %>
-
- <:action :let={media_profile}>
-
- <.link navigate={~p"/media_profiles/#{media_profile}"}>Show
+
+
+
+ <.table rows={@media_profiles} table_class="text-black dark:text-white">
+ <:col :let={media_profile} label="Name">
+ <%= media_profile.name %>
+
+ <:col :let={media_profile} label="Output Template">
+ <%= media_profile.output_path_template %>
+
+ <:col :let={media_profile} label="" class="flex place-content-evenly">
+ <.link
+ navigate={~p"/media_profiles/#{media_profile.id}"}
+ class="hover:text-secondary duration-200 ease-in-out mx-0.5"
+ >
+ <.icon name="hero-eye" />
+
+ <.link
+ navigate={~p"/media_profiles/#{media_profile.id}/edit"}
+ class="hover:text-secondary duration-200 ease-in-out mx-0.5"
+ >
+ <.icon name="hero-pencil-square" />
+
+
+
- <.link navigate={~p"/media_profiles/#{media_profile}/edit"}>Edit
-
- <:action :let={media_profile}>
- <.link href={~p"/media_profiles/#{media_profile}"} method="delete" data-confirm="Are you sure?">
- Delete
-
-
-
+
+
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/media_profile_form.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/media_profile_form.html.heex
index ca1ee9ce..1c653fc2 100644
--- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/media_profile_form.html.heex
+++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/media_profile_form.html.heex
@@ -2,29 +2,62 @@
<.error :if={@changeset.action}>
Oops, something went wrong! Please check the errors below.
- <.input field={f[:name]} type="text" label="Name" />
- <.input field={f[:output_path_template]} type="text" label="Output path template" />
+
+ General Options
+
+ <.input field={f[:name]} type="text" label="Name" placeholder="New Profile" help="(required)" />
+ <.input
+ field={f[:output_path_template]}
+ type="text"
+ label="Output path template"
+ help="TODO: provide docs (required)"
+ />
+
+
+ Subtitle Options
+
+ <.input field={f[:download_subs]} type="toggle" label="Download Subtitles" />
+ <.input
+ field={f[:download_auto_subs]}
+ type="toggle"
+ label="Download Autogenerated Subtitles"
+ help="Prefers normal subs but will download autogenerated if needed"
+ />
+ <.input
+ field={f[:embed_subs]}
+ type="toggle"
+ label="Embed Subtitles"
+ help="Embeds subtitles in the video file itself, if supported"
+ />
+ <.input
+ field={f[:sub_langs]}
+ type="text"
+ label="Subtitle Languages"
+ help="Use commas for multiple languages (eg: en,de)"
+ />
-
Subtitle Options
- <.input field={f[:download_subs]} type="checkbox" label="Download Subs" />
- <.input field={f[:download_auto_subs]} type="checkbox" label="Download Autogenerated Subs" />
- <.input field={f[:embed_subs]} type="checkbox" label="Embed Subs" />
- <.input field={f[:sub_langs]} type="text" label="Sub Langs" />
+
+ Thumbnail Options
+
+ <.input field={f[:download_thumbnail]} type="toggle" label="Download Thumbnail" />
+ <.input field={f[:embed_thumbnail]} type="toggle" label="Embed Thumbnail" />
-
Thumbnail Options
- <.input field={f[:download_thumbnail]} type="checkbox" label="Download Thumbnail" />
- <.input field={f[:embed_thumbnail]} type="checkbox" label="Embed Thumbnail" />
+
+ Metadata Options
+
+ <.input field={f[:download_metadata]} type="toggle" label="Download Metadata" />
+ <.input field={f[:embed_metadata]} type="toggle" label="Embed Metadata" />
-
Metadata Options
- <.input field={f[:download_metadata]} type="checkbox" label="Download Metadata" />
- <.input field={f[:embed_metadata]} type="checkbox" label="Embed Metadata" />
+
+ Release Format Options
+
-
Release Format Options
<.input
field={f[:shorts_behaviour]}
options={friendly_format_type_options()}
type="select"
label="Include Shorts?"
+ help="Experimental"
/>
<.input
field={f[:livestream_behaviour]}
@@ -34,6 +67,6 @@
/>
<:actions>
- <.button>Save Media profile
+ <.button class="mt-15 mb-5 sm:mb-7.5">Save Media profile
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/new.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/new.html.heex
index 0887e17e..95996192 100644
--- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/new.html.heex
+++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/new.html.heex
@@ -1,8 +1,14 @@
-<.header>
- New Media profile
- <:subtitle>Use this form to manage media_profile records in your database.
-
+
+ <.link navigate={~p"/media_profiles"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
+
+
New Media Profile
+
-<.media_profile_form changeset={@changeset} action={~p"/media_profiles"} />
-
-<.back navigate={~p"/media_profiles"}>Back to media_profiles
+
+
+
+ <.media_profile_form changeset={@changeset} action={~p"/media_profiles"} />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/show.html.heex b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/show.html.heex
index 965f7e8d..bb39eb9e 100644
--- a/lib/pinchflat_web/controllers/media_profiles/media_profile_html/show.html.heex
+++ b/lib/pinchflat_web/controllers/media_profiles/media_profile_html/show.html.heex
@@ -1,13 +1,26 @@
-<.header>
- Media profile <%= @media_profile.id %>
- <:subtitle>This is a media_profile record from your database.
- <:actions>
- <.link href={~p"/media_profiles/#{@media_profile}/edit"}>
- <.button>Edit media_profile
+
+
+ <.link navigate={~p"/media_profiles"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
-
-
+
+ Media Profile #<%= @media_profile.id %>
+
+
-<.list_items_from_map map={Map.from_struct(@media_profile)} />
-
-<.back navigate={~p"/media_profiles"}>Back to media_profiles
+
+ <.link navigate={~p"/media_profiles/#{@media_profile}/edit"}>
+ <.button color="bg-primary" rounding="rounded-full">
+ <.icon name="hero-pencil-square" class="mr-2" /> Edit Media Profile
+
+
+
+
+
+
+
+
Attributes
+ <.list_items_from_map map={Map.from_struct(@media_profile)} />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_sources/source_controller.ex b/lib/pinchflat_web/controllers/media_sources/source_controller.ex
index 5061e34f..63f4cbe5 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_controller.ex
+++ b/lib/pinchflat_web/controllers/media_sources/source_controller.ex
@@ -7,7 +7,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
alias Pinchflat.MediaSource.Source
def index(conn, _params) do
- sources = MediaSource.list_sources()
+ sources = Repo.preload(MediaSource.list_sources(), :media_profile)
render(conn, :index, sources: sources)
end
@@ -23,7 +23,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
{:ok, source} ->
conn
|> put_flash(:info, "Source created successfully.")
- |> redirect(to: ~p"/media_sources/sources/#{source}")
+ |> redirect(to: ~p"/sources/#{source}")
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, :new, changeset: changeset, media_profiles: media_profiles())
@@ -53,7 +53,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
{:ok, source} ->
conn
|> put_flash(:info, "Source updated successfully.")
- |> redirect(to: ~p"/media_sources/sources/#{source}")
+ |> redirect(to: ~p"/sources/#{source}")
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, :edit,
@@ -70,7 +70,7 @@ defmodule PinchflatWeb.MediaSources.SourceController do
conn
|> put_flash(:info, "Source deleted successfully.")
- |> redirect(to: ~p"/media_sources/sources")
+ |> redirect(to: ~p"/sources")
end
defp media_profiles do
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/edit.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/edit.html.heex
index d1afc041..9286ec39 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_html/edit.html.heex
+++ b/lib/pinchflat_web/controllers/media_sources/source_html/edit.html.heex
@@ -1,12 +1,18 @@
-<.header>
- Edit Source <%= @source.id %>
- <:subtitle>Use this form to manage source records in your database.
-
+
+ <.link navigate={~p"/sources"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
+
+
Edit Source
+
-<.source_form
- changeset={@changeset}
- media_profiles={@media_profiles}
- action={~p"/media_sources/sources/#{@source}"}
-/>
-
-<.back navigate={~p"/media_sources/sources"}>Back to sources
+
+
+
+ <.source_form
+ changeset={@changeset}
+ media_profiles={@media_profiles}
+ action={~p"/sources/#{@source}"}
+ />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/index.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/index.html.heex
index e5cede9c..8b741173 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_html/index.html.heex
+++ b/lib/pinchflat_web/controllers/media_sources/source_html/index.html.heex
@@ -1,24 +1,48 @@
-<.header>
- Listing Sources
- <:actions>
- <.link href={~p"/media_sources/sources/new"}>
- <.button>New Source
+
+
All Sources
+
+ <.link navigate={~p"/sources/new"}>
+ <.button color="bg-primary" rounding="rounded-full">
+ + New Source
+
-
-
+
+
-<.table id="sources" rows={@sources} row_click={&JS.navigate(~p"/media_sources/sources/#{&1}")}>
- <:col :let={source} label="Collection Name"><%= source.collection_name %>
- <:col :let={source} label="Collection ID"><%= source.collection_id %>
- <:action :let={source}>
-
- <.link navigate={~p"/media_sources/sources/#{source}"}>Show
+
+
+
+ <.table rows={@sources} table_class="text-black dark:text-white">
+ <:col :let={source} label="Name">
+ <%= source.friendly_name || source.collection_name %>
+
+ <:col :let={source} label="Type"><%= source.collection_type %>
+ <:col :let={source} label="Should Download?">
+ <.icon name={if source.download_media, do: "hero-check", else: "hero-x-mark"} />
+
+ <: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 %>
+
+
+ <: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
+ navigate={~p"/sources/#{source.id}/edit"}
+ class="hover:text-secondary duration-200 ease-in-out mx-0.5"
+ >
+ <.icon name="hero-pencil-square" />
+
+
+
- <.link navigate={~p"/media_sources/sources/#{source}/edit"}>Edit
-
- <:action :let={source}>
- <.link href={~p"/media_sources/sources/#{source}"} method="delete" data-confirm="Are you sure?">
- Delete
-
-
-
+
+
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/new.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/new.html.heex
index 4ef57417..6bd86c19 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_html/new.html.heex
+++ b/lib/pinchflat_web/controllers/media_sources/source_html/new.html.heex
@@ -1,12 +1,14 @@
-<.header>
- New Source
- <:subtitle>Use this form to manage source records in your database.
-
+
+ <.link navigate={~p"/sources"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
+
+
New Source
+
-<.source_form
- changeset={@changeset}
- media_profiles={@media_profiles}
- action={~p"/media_sources/sources"}
-/>
-
-<.back navigate={~p"/media_sources/sources"}>Back to sources
+
+
+
+ <.source_form changeset={@changeset} media_profiles={@media_profiles} action={~p"/sources"} />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex
index 898dddd0..1d947d55 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex
+++ b/lib/pinchflat_web/controllers/media_sources/source_html/show.html.heex
@@ -1,23 +1,38 @@
-<.header>
- Source <%= @source.id %>
- <:subtitle>This is a source record from your database.
- <:actions>
- <.link href={~p"/media_sources/sources/#{@source}/edit"}>
- <.button>Edit source
+
+
+ <.link navigate={~p"/sources"}>
+ <.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
-
-
+
+ Source #<%= @source.id %>
+
+
-
Relationships
-<.list>
- <:item title="media_profile">
- <.link href={~p"/media_profiles/#{@source.media_profile}"}>
- <%= @source.media_profile.name %>
+
+ <.link navigate={~p"/sources/#{@source}/edit"}>
+ <.button color="bg-primary" rounding="rounded-full">
+ <.icon name="hero-pencil-square" class="mr-2" /> Edit Source
+
-
-
+
+
+
+
+
+
Relationships
+ <.list>
+ <:item title="media_profile">
+ <.link
+ navigate={~p"/media_profiles/#{@source.media_profile_id}"}
+ class="hover:text-secondary duration-200 ease-in-out"
+ >
+ <%= @source.media_profile.name %>
+
+
+
-Attributes
-<.list_items_from_map map={Map.from_struct(@source)} />
-
-<.back navigate={~p"/media_sources/sources"}>Back to sources
+ Attributes
+ <.list_items_from_map map={Map.from_struct(@source)} />
+
+
+
diff --git a/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex b/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex
index a070a843..4cc14992 100644
--- a/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex
+++ b/lib/pinchflat_web/controllers/media_sources/source_html/source_form.html.heex
@@ -3,6 +3,13 @@
Oops, something went wrong! Please check the errors below.
+ <.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
@@ -16,21 +23,25 @@
field={f[:collection_type]}
options={friendly_collection_types()}
type="select"
- label="Collection Type"
+ label="Source Type"
/>
- <.input field={f[:original_url]} type="text" label="Source URL" />
-
<.input
field={f[:index_frequency_minutes]}
options={friendly_index_frequencies()}
type="select"
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>
- <.button>Save Source
+ <.button class="mt-15 mb-5 sm:mb-7.5">Save Source
diff --git a/lib/pinchflat_web/controllers/page_controller.ex b/lib/pinchflat_web/controllers/page_controller.ex
index f15227a0..816b6cf3 100644
--- a/lib/pinchflat_web/controllers/page_controller.ex
+++ b/lib/pinchflat_web/controllers/page_controller.ex
@@ -4,6 +4,6 @@ defmodule PinchflatWeb.PageController do
def home(conn, _params) do
# The home page is often custom made,
# so skip the default app layout.
- render(conn, :home, layout: false)
+ render(conn, :home)
end
end
diff --git a/lib/pinchflat_web/router.ex b/lib/pinchflat_web/router.ex
index fd06da34..3610003d 100644
--- a/lib/pinchflat_web/router.ex
+++ b/lib/pinchflat_web/router.ex
@@ -20,10 +20,7 @@ defmodule PinchflatWeb.Router do
get "/", PageController, :home
resources "/media_profiles", MediaProfiles.MediaProfileController
-
- scope "/media_sources", MediaSources do
- resources "/sources", SourceController
- end
+ resources "/sources", MediaSources.SourceController
end
# Other scopes may use custom stacks.
diff --git a/priv/static/fonts/satoshi/Satoshi-BlackItalic.eot b/priv/static/fonts/satoshi/Satoshi-BlackItalic.eot
new file mode 100644
index 00000000..de2edbbc
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BlackItalic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BlackItalic.ttf b/priv/static/fonts/satoshi/Satoshi-BlackItalic.ttf
new file mode 100644
index 00000000..74410b97
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BlackItalic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff b/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff
new file mode 100644
index 00000000..0e07e1c5
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff2 b/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff2
new file mode 100644
index 00000000..9d5c911d
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BlackItalic.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Bold.eot b/priv/static/fonts/satoshi/Satoshi-Bold.eot
new file mode 100644
index 00000000..390ae252
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Bold.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Bold.ttf b/priv/static/fonts/satoshi/Satoshi-Bold.ttf
new file mode 100644
index 00000000..00bc985b
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Bold.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Bold.woff b/priv/static/fonts/satoshi/Satoshi-Bold.woff
new file mode 100644
index 00000000..bba8257f
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Bold.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Bold.woff2 b/priv/static/fonts/satoshi/Satoshi-Bold.woff2
new file mode 100644
index 00000000..0a8db7a4
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Bold.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BoldItalic.eot b/priv/static/fonts/satoshi/Satoshi-BoldItalic.eot
new file mode 100644
index 00000000..426be2ac
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BoldItalic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BoldItalic.ttf b/priv/static/fonts/satoshi/Satoshi-BoldItalic.ttf
new file mode 100644
index 00000000..24f012cb
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BoldItalic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff b/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff
new file mode 100644
index 00000000..8bcb7a6e
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff2 b/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff2
new file mode 100644
index 00000000..225527f7
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-BoldItalic.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Italic.eot b/priv/static/fonts/satoshi/Satoshi-Italic.eot
new file mode 100644
index 00000000..64039a84
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Italic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Italic.ttf b/priv/static/fonts/satoshi/Satoshi-Italic.ttf
new file mode 100644
index 00000000..c214f4fe
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Italic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Italic.woff b/priv/static/fonts/satoshi/Satoshi-Italic.woff
new file mode 100644
index 00000000..edd4d932
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Italic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Italic.woff2 b/priv/static/fonts/satoshi/Satoshi-Italic.woff2
new file mode 100644
index 00000000..8b98599d
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Italic.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Light.eot b/priv/static/fonts/satoshi/Satoshi-Light.eot
new file mode 100644
index 00000000..d8fcaccd
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Light.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Light.ttf b/priv/static/fonts/satoshi/Satoshi-Light.ttf
new file mode 100644
index 00000000..b41a2d4a
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Light.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Light.woff b/priv/static/fonts/satoshi/Satoshi-Light.woff
new file mode 100644
index 00000000..8f05e4e9
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Light.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Light.woff2 b/priv/static/fonts/satoshi/Satoshi-Light.woff2
new file mode 100644
index 00000000..cf18cd4c
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Light.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-LightItalic.eot b/priv/static/fonts/satoshi/Satoshi-LightItalic.eot
new file mode 100644
index 00000000..e34a0df4
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-LightItalic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-LightItalic.ttf b/priv/static/fonts/satoshi/Satoshi-LightItalic.ttf
new file mode 100644
index 00000000..08f5db57
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-LightItalic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-LightItalic.woff b/priv/static/fonts/satoshi/Satoshi-LightItalic.woff
new file mode 100644
index 00000000..a03a50d7
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-LightItalic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-LightItalic.woff2 b/priv/static/fonts/satoshi/Satoshi-LightItalic.woff2
new file mode 100644
index 00000000..6bd15ad5
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-LightItalic.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Medium.eot b/priv/static/fonts/satoshi/Satoshi-Medium.eot
new file mode 100644
index 00000000..83caceca
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Medium.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Medium.ttf b/priv/static/fonts/satoshi/Satoshi-Medium.ttf
new file mode 100644
index 00000000..ab149b71
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Medium.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Medium.woff b/priv/static/fonts/satoshi/Satoshi-Medium.woff
new file mode 100644
index 00000000..cef3226e
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Medium.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Medium.woff2 b/priv/static/fonts/satoshi/Satoshi-Medium.woff2
new file mode 100644
index 00000000..ffd0ac96
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Medium.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-MediumItalic.eot b/priv/static/fonts/satoshi/Satoshi-MediumItalic.eot
new file mode 100644
index 00000000..25d229a5
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-MediumItalic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-MediumItalic.ttf b/priv/static/fonts/satoshi/Satoshi-MediumItalic.ttf
new file mode 100644
index 00000000..387f278e
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-MediumItalic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff b/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff
new file mode 100644
index 00000000..46d8995a
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff2 b/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff2
new file mode 100644
index 00000000..212adc92
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-MediumItalic.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Regular.eot b/priv/static/fonts/satoshi/Satoshi-Regular.eot
new file mode 100644
index 00000000..452666f4
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Regular.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Regular.ttf b/priv/static/fonts/satoshi/Satoshi-Regular.ttf
new file mode 100644
index 00000000..fe85cd6c
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Regular.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Regular.woff b/priv/static/fonts/satoshi/Satoshi-Regular.woff
new file mode 100644
index 00000000..03ac1952
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Regular.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Regular.woff2 b/priv/static/fonts/satoshi/Satoshi-Regular.woff2
new file mode 100644
index 00000000..81c40ab0
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Regular.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Variable.eot b/priv/static/fonts/satoshi/Satoshi-Variable.eot
new file mode 100644
index 00000000..f42624e1
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Variable.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Variable.ttf b/priv/static/fonts/satoshi/Satoshi-Variable.ttf
new file mode 100644
index 00000000..976e85cb
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Variable.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Variable.woff b/priv/static/fonts/satoshi/Satoshi-Variable.woff
new file mode 100644
index 00000000..f8dcd1d6
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Variable.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-Variable.woff2 b/priv/static/fonts/satoshi/Satoshi-Variable.woff2
new file mode 100644
index 00000000..b00e833e
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-Variable.woff2 differ
diff --git a/priv/static/fonts/satoshi/Satoshi-VariableItalic.eot b/priv/static/fonts/satoshi/Satoshi-VariableItalic.eot
new file mode 100644
index 00000000..5f4554af
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-VariableItalic.eot differ
diff --git a/priv/static/fonts/satoshi/Satoshi-VariableItalic.ttf b/priv/static/fonts/satoshi/Satoshi-VariableItalic.ttf
new file mode 100644
index 00000000..4c2677c6
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-VariableItalic.ttf differ
diff --git a/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff b/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff
new file mode 100644
index 00000000..3fe029e2
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff differ
diff --git a/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff2 b/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff2
new file mode 100644
index 00000000..e7ab3a09
Binary files /dev/null and b/priv/static/fonts/satoshi/Satoshi-VariableItalic.woff2 differ
diff --git a/test/pinchflat_web/controllers/media_profile_controller_test.exs b/test/pinchflat_web/controllers/media_profile_controller_test.exs
index b5bac1e5..8a2e3e19 100644
--- a/test/pinchflat_web/controllers/media_profile_controller_test.exs
+++ b/test/pinchflat_web/controllers/media_profile_controller_test.exs
@@ -13,14 +13,14 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
describe "index" do
test "lists all media_profiles", %{conn: conn} do
conn = get(conn, ~p"/media_profiles")
- assert html_response(conn, 200) =~ "Listing Media profiles"
+ assert html_response(conn, 200) =~ "All Media Profiles"
end
end
describe "new media_profile" do
test "renders form", %{conn: conn} do
conn = get(conn, ~p"/media_profiles/new")
- assert html_response(conn, 200) =~ "New Media profile"
+ assert html_response(conn, 200) =~ "New Media Profile"
end
end
@@ -32,12 +32,12 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
assert redirected_to(conn) == ~p"/media_profiles/#{id}"
conn = get(conn, ~p"/media_profiles/#{id}")
- assert html_response(conn, 200) =~ "Media profile #{id}"
+ assert html_response(conn, 200) =~ "Media Profile ##{id}"
end
test "renders errors when data is invalid", %{conn: conn} do
conn = post(conn, ~p"/media_profiles", media_profile: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Media profile"
+ assert html_response(conn, 200) =~ "New Media Profile"
end
end
@@ -49,7 +49,7 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
media_profile: media_profile
} do
conn = get(conn, ~p"/media_profiles/#{media_profile}/edit")
- assert html_response(conn, 200) =~ "Edit Media profile"
+ assert html_response(conn, 200) =~ "Edit Media Profile"
end
end
@@ -66,7 +66,7 @@ defmodule PinchflatWeb.MediaProfileControllerTest do
test "renders errors when data is invalid", %{conn: conn, media_profile: media_profile} do
conn = put(conn, ~p"/media_profiles/#{media_profile}", media_profile: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Media profile"
+ assert html_response(conn, 200) =~ "Edit Media Profile"
end
end
diff --git a/test/pinchflat_web/controllers/source_controller_test.exs b/test/pinchflat_web/controllers/source_controller_test.exs
index 39cb9d8e..9f3e2bd6 100644
--- a/test/pinchflat_web/controllers/source_controller_test.exs
+++ b/test/pinchflat_web/controllers/source_controller_test.exs
@@ -28,14 +28,14 @@ defmodule PinchflatWeb.SourceControllerTest do
describe "index" do
test "lists all sources", %{conn: conn} do
- conn = get(conn, ~p"/media_sources/sources")
- assert html_response(conn, 200) =~ "Listing Sources"
+ conn = get(conn, ~p"/sources")
+ assert html_response(conn, 200) =~ "All Sources"
end
end
describe "new source" 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"
end
end
@@ -43,17 +43,17 @@ defmodule PinchflatWeb.SourceControllerTest do
describe "create source" do
test "redirects to show when data is valid", %{conn: conn, create_attrs: create_attrs} do
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 redirected_to(conn) == ~p"/media_sources/sources/#{id}"
+ assert redirected_to(conn) == ~p"/sources/#{id}"
- conn = get(conn, ~p"/media_sources/sources/#{id}")
- assert html_response(conn, 200) =~ "Source #{id}"
+ conn = get(conn, ~p"/sources/#{id}")
+ assert html_response(conn, 200) =~ "Source ##{id}"
end
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"
end
end
@@ -62,7 +62,7 @@ defmodule PinchflatWeb.SourceControllerTest do
setup [:create_source]
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"
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
expect(YtDlpRunnerMock, :run, 1, &runner_function_mock/3)
- conn = put(conn, ~p"/media_sources/sources/#{source}", source: update_attrs)
- assert redirected_to(conn) == ~p"/media_sources/sources/#{source}"
+ conn = put(conn, ~p"/sources/#{source}", source: update_attrs)
+ 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"
end
@@ -85,7 +85,7 @@ defmodule PinchflatWeb.SourceControllerTest do
source: source,
invalid_attrs: invalid_attrs
} 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"
end
end
@@ -94,11 +94,11 @@ defmodule PinchflatWeb.SourceControllerTest do
setup [:create_source]
test "deletes chosen source", %{conn: conn, source: source} do
- conn = delete(conn, ~p"/media_sources/sources/#{source}")
- assert redirected_to(conn) == ~p"/media_sources/sources"
+ conn = delete(conn, ~p"/sources/#{source}")
+ assert redirected_to(conn) == ~p"/sources"
assert_error_sent 404, fn ->
- get(conn, ~p"/media_sources/sources/#{source}")
+ get(conn, ~p"/sources/#{source}")
end
end
end