[WIP] saving before attempting LiveView

This commit is contained in:
Kieran Eglin 2024-01-23 11:09:22 -08:00
parent 94414989af
commit f9249ff130
No known key found for this signature in database
GPG key ID: 193984967FCF432D
4 changed files with 123 additions and 29 deletions

View file

@ -7,6 +7,7 @@ defmodule Pinchflat.MediaSource do
alias Pinchflat.Repo alias Pinchflat.Repo
alias Pinchflat.MediaSource.Channel alias Pinchflat.MediaSource.Channel
alias Pinchflat.MediaClient.ChannelDetails
@doc """ @doc """
Returns the list of channels. Returns [%Channel{}, ...] Returns the list of channels. Returns [%Channel{}, ...]
@ -31,6 +32,31 @@ defmodule Pinchflat.MediaSource do
|> Repo.insert() |> Repo.insert()
end end
@doc """
Creates a channel from a given Channel URL and additional attrs.
Returns {:ok, %Channel{}} | {:error, %Ecto.Changeset{}} | {:error, binary()}
IDEA: maybe instead of creating a channel from a URL, instead the form should
extract details from the URL and automatically update based on that. So the
actual submission would be a normal form object
"""
def create_channel_from_url(channel_url, attrs) do
case ChannelDetails.get_channel_details(channel_url) do
{:ok, %ChannelDetails{} = channel_details} ->
record_attrs =
Map.merge(attrs, %{
name: channel_details.name,
channel_id: channel_details.id
})
create_channel(record_attrs)
{:error, runner_error, _status_code} ->
{:error, runner_error}
end
end
@doc """ @doc """
Updates a channel. Returns {:ok, %Channel{}} | {:error, %Ecto.Changeset{}} Updates a channel. Returns {:ok, %Channel{}} | {:error, %Ecto.Changeset{}}
""" """

View file

@ -1,6 +1,7 @@
defmodule PinchflatWeb.MediaSources.ChannelController do defmodule PinchflatWeb.MediaSources.ChannelController do
use PinchflatWeb, :controller use PinchflatWeb, :controller
alias Pinchflat.Profiles
alias Pinchflat.MediaSource alias Pinchflat.MediaSource
alias Pinchflat.MediaSource.Channel alias Pinchflat.MediaSource.Channel
@ -10,12 +11,14 @@ defmodule PinchflatWeb.MediaSources.ChannelController do
end end
def new(conn, _params) do def new(conn, _params) do
media_profiles = Profiles.list_media_profiles()
changeset = MediaSource.change_channel(%Channel{}) changeset = MediaSource.change_channel(%Channel{})
render(conn, :new, changeset: changeset)
render(conn, :new, changeset: changeset, media_profiles: media_profiles)
end end
def create(conn, %{"channel" => channel_params}) do def create(conn, %{"channel" => channel_params}) do
case MediaSource.create_channel(channel_params) do case MediaSource.create_channel_from_url(channel_params["channel_url"], channel_params) do
{:ok, channel} -> {:ok, channel} ->
conn conn
|> put_flash(:info, "Channel created successfully.") |> put_flash(:info, "Channel created successfully.")

View file

@ -3,6 +3,20 @@
<:subtitle>Use this form to manage channel records in your database.</:subtitle> <:subtitle>Use this form to manage channel records in your database.</:subtitle>
</.header> </.header>
<.channel_form changeset={@changeset} action={~p"/media_sources/channels"} /> <.simple_form :let={f} for={@changeset} action={~p"/media_sources/channels"}>
<.error :if={@changeset.action}>
Oops, something went wrong! Please check the errors below.
</.error>
<.input
field={f[:media_profile_id]}
options={Enum.map(@media_profiles, &{&1.name, &1.id})}
type="select"
label="Media Profile"
/>
<.input field={f[:channel_url]} type="text" label="Channel URL" />
<:actions>
<.button>Save Channel</.button>
</:actions>
</.simple_form>
<.back navigate={~p"/media_sources/channels"}>Back to channels</.back> <.back navigate={~p"/media_sources/channels"}>Back to channels</.back>

View file

@ -2,26 +2,29 @@ defmodule Pinchflat.MediaSourceTest do
use Pinchflat.DataCase use Pinchflat.DataCase
alias Pinchflat.MediaSource alias Pinchflat.MediaSource
alias Pinchflat.MediaSource.Channel
describe "channels" do import Pinchflat.ProfilesFixtures
alias Pinchflat.MediaSource.Channel import Pinchflat.MediaSourceFixtures
import Pinchflat.ProfilesFixtures @invalid_channel_attrs %{name: nil, channel_id: nil}
import Pinchflat.MediaSourceFixtures
@invalid_attrs %{name: nil, channel_id: nil} describe "list_channels/0" do
test "it returns all channels" do
test "list_channels/0 returns all channels" do
channel = channel_fixture() channel = channel_fixture()
assert MediaSource.list_channels() == [channel] assert MediaSource.list_channels() == [channel]
end end
end
test "get_channel!/1 returns the channel with given id" do describe "get_channel!/1" do
test "it returns the channel with given id" do
channel = channel_fixture() channel = channel_fixture()
assert MediaSource.get_channel!(channel.id) == channel assert MediaSource.get_channel!(channel.id) == channel
end end
end
test "create_channel/1 with valid data creates a channel" do describe "create_channel/1" do
test "creates a channel with valid data" do
valid_attrs = %{ valid_attrs = %{
name: "some name", name: "some name",
channel_id: "some channel_id", channel_id: "some channel_id",
@ -33,11 +36,11 @@ defmodule Pinchflat.MediaSourceTest do
assert channel.channel_id == "some channel_id" assert channel.channel_id == "some channel_id"
end end
test "create_channel/1 with invalid data returns error changeset" do test "creation with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = MediaSource.create_channel(@invalid_attrs) assert {:error, %Ecto.Changeset{}} = MediaSource.create_channel(@invalid_channel_attrs)
end end
test "create_channel/1 enforces uniqueness of channel_id scoped to the media_profile" do test "creation enforces uniqueness of channel_id scoped to the media_profile" do
valid_once_attrs = %{ valid_once_attrs = %{
name: "some name", name: "some name",
channel_id: "abc123", channel_id: "abc123",
@ -48,24 +51,67 @@ defmodule Pinchflat.MediaSourceTest do
assert {:error, %Ecto.Changeset{}} = MediaSource.create_channel(valid_once_attrs) assert {:error, %Ecto.Changeset{}} = MediaSource.create_channel(valid_once_attrs)
end end
test "create_channel/1 lets you duplicate channel_ids as long as the media profile is different" do test "creation lets you duplicate channel_ids as long as the media profile is different" do
valid_attrs = %{ valid_attrs = %{
name: "some name", name: "some name",
channel_id: "abc123" channel_id: "abc123"
} }
assert {:ok, %Channel{}} = channel_1_attrs = Map.merge(valid_attrs, %{media_profile_id: media_profile_fixture().id})
MediaSource.create_channel( channel_2_attrs = Map.merge(valid_attrs, %{media_profile_id: media_profile_fixture().id})
Map.merge(valid_attrs, %{media_profile_id: media_profile_fixture().id})
)
assert {:ok, %Channel{}} = assert {:ok, %Channel{}} = MediaSource.create_channel(channel_1_attrs)
MediaSource.create_channel( assert {:ok, %Channel{}} = MediaSource.create_channel(channel_2_attrs)
Map.merge(valid_attrs, %{media_profile_id: media_profile_fixture().id}) end
) end
describe "create_channel_from_url/2" do
import Mox
setup :verify_on_exit!
test "it creates a channel with valid data" do
channel_url = "https://www.youtube.com/c/TheUselessTrials"
valid_attrs = %{media_profile_id: media_profile_fixture().id}
expect(YtDlpRunnerMock, :run, fn ^channel_url, _opts ->
{:ok, "{\"channel\": \"TheUselessTrials\", \"channel_id\": \"UCQH2\"}"}
end)
assert {:ok, %Channel{} = channel} =
MediaSource.create_channel_from_url(channel_url, valid_attrs)
assert channel.name == "TheUselessTrials"
assert channel.channel_id == "UCQH2"
end end
test "update_channel/2 with valid data updates the channel" do test "it returns an error string if the runner returns an error" do
channel_url = "https://www.youtube.com/c/TheUselessTrials"
valid_attrs = %{media_profile_id: media_profile_fixture().id}
expect(YtDlpRunnerMock, :run, fn ^channel_url, _opts ->
{:error, "Big issue", 1}
end)
assert {:error, "Big issue"} =
MediaSource.create_channel_from_url(channel_url, valid_attrs)
end
test "creation with invalid data returns error changeset" do
channel_url = "https://www.youtube.com/c/TheUselessTrials"
invalid_attrs = %{media_profile_id: nil}
expect(YtDlpRunnerMock, :run, fn ^channel_url, _opts ->
{:ok, "{\"channel\": \"TheUselessTrials\", \"channel_id\": \"UCQH2\"}"}
end)
assert {:error, %Ecto.Changeset{}} =
MediaSource.create_channel_from_url(channel_url, invalid_attrs)
end
end
describe "update_channel/2" do
test "updates with valid data updates the channel" do
channel = channel_fixture() channel = channel_fixture()
update_attrs = %{name: "some updated name", channel_id: "some updated channel_id"} update_attrs = %{name: "some updated name", channel_id: "some updated channel_id"}
@ -74,19 +120,24 @@ defmodule Pinchflat.MediaSourceTest do
assert channel.channel_id == "some updated channel_id" assert channel.channel_id == "some updated channel_id"
end end
test "update_channel/2 with invalid data returns error changeset" do test "updates with invalid data returns error changeset" do
channel = channel_fixture() channel = channel_fixture()
assert {:error, %Ecto.Changeset{}} = MediaSource.update_channel(channel, @invalid_attrs)
assert {:error, %Ecto.Changeset{}} =
MediaSource.update_channel(channel, @invalid_channel_attrs)
assert channel == MediaSource.get_channel!(channel.id) assert channel == MediaSource.get_channel!(channel.id)
end end
end
test "delete_channel/1 deletes the channel" do describe "delete_channel/1" do
test "it deletes the channel" do
channel = channel_fixture() channel = channel_fixture()
assert {:ok, %Channel{}} = MediaSource.delete_channel(channel) assert {:ok, %Channel{}} = MediaSource.delete_channel(channel)
assert_raise Ecto.NoResultsError, fn -> MediaSource.get_channel!(channel.id) end assert_raise Ecto.NoResultsError, fn -> MediaSource.get_channel!(channel.id) end
end end
test "change_channel/1 returns a channel changeset" do test "it returns a channel changeset" do
channel = channel_fixture() channel = channel_fixture()
assert %Ecto.Changeset{} = MediaSource.change_channel(channel) assert %Ecto.Changeset{} = MediaSource.change_channel(channel)
end end