diff --git a/lib/pinchflat_web/controllers/sources/source_controller.ex b/lib/pinchflat_web/controllers/sources/source_controller.ex
index 2df192f..d11dd08 100644
--- a/lib/pinchflat_web/controllers/sources/source_controller.ex
+++ b/lib/pinchflat_web/controllers/sources/source_controller.ex
@@ -41,13 +41,30 @@ defmodule PinchflatWeb.Sources.SourceController do
render(conn, :index, sources: Repo.all(source_query))
end
- def new(conn, _params) do
- changeset = Sources.change_source(%Source{})
+ def new(conn, params) do
+ # This lets me preload the settings from another source for more efficient creation
+ cs_struct =
+ case to_string(params["template_id"]) do
+ "" -> %Source{}
+ template_id -> Repo.get(Source, template_id) || %Source{}
+ end
render(conn, :new,
- changeset: changeset,
media_profiles: media_profiles(),
- layout: get_onboarding_layout()
+ layout: get_onboarding_layout(),
+ # Most of these don't actually _need_ to be nullified at this point,
+ # but if I don't do it now I know it'll bite me
+ changeset:
+ Sources.change_source(%Source{
+ cs_struct
+ | id: nil,
+ uuid: nil,
+ custom_name: nil,
+ collection_name: nil,
+ collection_id: nil,
+ collection_type: nil,
+ original_url: nil
+ })
)
end
diff --git a/lib/pinchflat_web/controllers/sources/source_html.ex b/lib/pinchflat_web/controllers/sources/source_html.ex
index bf61720..b47e7f7 100644
--- a/lib/pinchflat_web/controllers/sources/source_html.ex
+++ b/lib/pinchflat_web/controllers/sources/source_html.ex
@@ -9,6 +9,7 @@ defmodule PinchflatWeb.Sources.SourceHTML do
attr :changeset, Ecto.Changeset, required: true
attr :action, :string, required: true
attr :media_profiles, :list, required: true
+ attr :method, :string, required: true
def source_form(assigns)
diff --git a/lib/pinchflat_web/controllers/sources/source_html/actions_dropdown.html.heex b/lib/pinchflat_web/controllers/sources/source_html/actions_dropdown.html.heex
index ab5b7c1..43b4c22 100644
--- a/lib/pinchflat_web/controllers/sources/source_html/actions_dropdown.html.heex
+++ b/lib/pinchflat_web/controllers/sources/source_html/actions_dropdown.html.heex
@@ -26,6 +26,11 @@
<.icon name="hero-check" class="ml-2 h-4 w-4" />
+ <:option>
+ <.link href={~p"/sources/new?template_id=#{@source}"} method="get">
+ Use as Template
+
+
<:option>
diff --git a/lib/pinchflat_web/controllers/sources/source_html/edit.html.heex b/lib/pinchflat_web/controllers/sources/source_html/edit.html.heex
index 680d2e3..e85cf1e 100644
--- a/lib/pinchflat_web/controllers/sources/source_html/edit.html.heex
+++ b/lib/pinchflat_web/controllers/sources/source_html/edit.html.heex
@@ -10,7 +10,12 @@
- <.source_form changeset={@changeset} media_profiles={@media_profiles} action={~p"/sources/#{@source}"} />
+ <.source_form
+ changeset={@changeset}
+ media_profiles={@media_profiles}
+ action={~p"/sources/#{@source}"}
+ method="patch"
+ />
diff --git a/lib/pinchflat_web/controllers/sources/source_html/new.html.heex b/lib/pinchflat_web/controllers/sources/source_html/new.html.heex
index f144d9e..e4969f9 100644
--- a/lib/pinchflat_web/controllers/sources/source_html/new.html.heex
+++ b/lib/pinchflat_web/controllers/sources/source_html/new.html.heex
@@ -8,7 +8,7 @@
- <.source_form changeset={@changeset} media_profiles={@media_profiles} action={~p"/sources"} />
+ <.source_form changeset={@changeset} media_profiles={@media_profiles} action={~p"/sources"} method="post" />
diff --git a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
index 6705f99..93c29be 100644
--- a/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
+++ b/lib/pinchflat_web/controllers/sources/source_html/source_form.html.heex
@@ -2,6 +2,7 @@
:let={f}
for={@changeset}
action={@action}
+ method={@method}
x-data="{ advancedMode: !!JSON.parse(localStorage.getItem('advancedMode')) }"
x-init="$watch('advancedMode', value => localStorage.setItem('advancedMode', JSON.stringify(value)))"
>
@@ -10,7 +11,7 @@
-
+
General Options
@@ -19,6 +20,14 @@
+ <.input
+ field={f[:original_url]}
+ type="text"
+ label="Source URL"
+ help="URL of a channel or playlist (required)"
+ x-init="$el.focus()"
+ />
+
<.input
field={f[:custom_name]}
type="text"
@@ -26,8 +35,6 @@
help="Does not impact indexing or downloading. Will be inferred from the source if left blank"
/>
- <.input field={f[:original_url]} type="text" label="Source URL" help="URL of a channel or playlist (required)" />
-
<.input
field={f[:media_profile_id]}
options={Enum.map(@media_profiles, &{&1.name, &1.id})}
diff --git a/test/pinchflat_web/controllers/source_controller_test.exs b/test/pinchflat_web/controllers/source_controller_test.exs
index b9d6882..a4d18dc 100644
--- a/test/pinchflat_web/controllers/source_controller_test.exs
+++ b/test/pinchflat_web/controllers/source_controller_test.exs
@@ -50,6 +50,15 @@ defmodule PinchflatWeb.SourceControllerTest do
refute html_response(conn, 200) =~ "MENU"
end
+
+ test "preloads some attributes when using a template", %{conn: conn} do
+ source = source_fixture(custom_name: "My first source", download_cutoff_date: "2021-01-01")
+
+ conn = get(conn, ~p"/sources/new", %{"template_id" => source.id})
+ assert html_response(conn, 200) =~ "New Source"
+ assert html_response(conn, 200) =~ "2021-01-01"
+ refute html_response(conn, 200) =~ source.custom_name
+ end
end
describe "create source" do