draft: apps

This commit is contained in:
Nikos Papadakis 2023-11-20 18:50:24 +02:00
parent 78051bb796
commit 4a37cc402a
Signed by untrusted user who does not match committer: nikos
GPG key ID: 78871F9905ADFF02
8 changed files with 354 additions and 0 deletions
app
lib
test
prymn
support/fixtures
priv/repo/migrations

103
app/lib/prymn/apps.ex Normal file
View file

@ -0,0 +1,103 @@
defmodule Prymn.Apps do
@moduledoc """
The Apps context.
"""
import Ecto.Query, warn: false
alias Prymn.Repo
alias Prymn.Apps.App
@doc """
Returns the list of apps.
## Examples
iex> list_apps()
[%App{}, ...]
"""
def list_apps do
Repo.all(App)
end
@doc """
Gets a single app.
Raises `Ecto.NoResultsError` if the App does not exist.
## Examples
iex> get_app!(123)
%App{}
iex> get_app!(456)
** (Ecto.NoResultsError)
"""
def get_app!(id), do: Repo.get!(App, id)
@doc """
Creates a app.
## Examples
iex> create_app(%{field: value})
{:ok, %App{}}
iex> create_app(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_app(attrs \\ %{}) do
%App{}
|> App.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a app.
## Examples
iex> update_app(app, %{field: new_value})
{:ok, %App{}}
iex> update_app(app, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_app(%App{} = app, attrs) do
app
|> App.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a app.
## Examples
iex> delete_app(app)
{:ok, %App{}}
iex> delete_app(app)
{:error, %Ecto.Changeset{}}
"""
def delete_app(%App{} = app) do
Repo.delete(app)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking app changes.
## Examples
iex> change_app(app)
%Ecto.Changeset{data: %App{}}
"""
def change_app(%App{} = app, attrs \\ %{}) do
App.changeset(app, attrs)
end
end

17
app/lib/prymn/apps/app.ex Normal file
View file

@ -0,0 +1,17 @@
defmodule Prymn.Apps.App do
use Ecto.Schema
import Ecto.Changeset
schema "apps" do
field :name, :string
timestamps()
end
@doc false
def changeset(app, attrs) do
app
|> cast(attrs, [:name])
|> validate_required([:name])
end
end

View file

@ -0,0 +1,78 @@
defmodule PrymnWeb.CreateApp do
use PrymnWeb, :live_component
@impl true
def render(assigns) do
~H"""
<div class="mx-auto max-w-2xl">
<fieldset>
<legend class="mb-6 border-b border-slate-200 pb-2 text-base font-semibold">App Type</legend>
<span>
<input
id="wordpress"
type="radio"
name="app_type"
value="wordpress"
class="peer hidden"
checked={@app_type == "wordpress"}
/>
<label
for="wordpress"
class="inline-block cursor-pointer rounded p-5 shadow peer-checked:bg-black peer-checked:text-white"
phx-click={JS.patch(~p"/apps/new?app_type=wordpress")}
>
WordPress
</label>
</span>
<span>
<input
id="plain_html"
type="radio"
name="app_type"
value="plain_html"
class="peer hidden"
checked={@app_type == "plain_html"}
/>
<label
for="plain_html"
class="inline-block cursor-pointer rounded p-5 shadow peer-checked:bg-black peer-checked:text-white"
phx-click={JS.patch(~p"/apps/new?app_type=plain_html")}
>
Plain HTML
</label>
</span>
</fieldset>
<.wordpress_app_form :if={assigns.app_type == "wordpress"} servers={assigns[:servers]} />
</div>
"""
end
defp wordpress_app_form(assigns) do
~H"""
<.simple_form id="test" for={nil}>
<.input
:if={assigns.servers != nil}
id="server"
type="select"
name="server"
prompt="Select a server to host this app..."
options={[]}
value={nil}
label="Hosting Server"
/>
<.input id="name" type="text" name="app_name" value={nil} label="WordPress Site Name" required />
<.input id="domain" type="text" name="domain" value={nil} label="Domain Name" required />
<.input type="checkbox" name="create_database?" label="Create a new database?" />
<.input type="text" name="db_name" value={nil} label="Database name" />
<.input type="select" name="db_name" value={nil} options={["db1", "db2"]} label="Database" />
<.input type="text" name="admin_username" value={nil} label="Admin Username" />
<.input type="email" name="admin_email" value={nil} label="Admin Email" />
<.input type="password" name="admin_password" value={nil} label="Admin Password" />
<.button type="submit">Create</.button>
</.simple_form>
"""
end
end

View file

@ -0,0 +1,63 @@
defmodule PrymnWeb.AppIndexLive do
use PrymnWeb, :live_view
@impl true
def mount(_, _, socket) do
apps = Prymn.Apps.list_apps()
servers = Prymn.Servers.list_servers()
{:ok,
socket
|> assign(:servers, servers)
|> assign(:apps, apps)}
end
@impl true
def render(assigns) do
~H"""
<%= cond do %>
<% assigns.live_action == :new -> %>
<.back navigate={~p"/apps"}>Go back</.back>
<.live_component
id={:new}
module={PrymnWeb.CreateApp}
app_type={assigns[:app_type]}
servers={@servers}
/>
<% assigns.apps == [] -> %>
<.onboarding />
<% true -> %>
<div class="mx-auto max-w-2xl">
<.header>
Live Apps
<:subtitle>
All of your apps accross all projects.
</:subtitle>
</.header>
</div>
<% end %>
"""
end
@impl true
def handle_params(%{"app_type" => app_type}, _, socket) do
{:noreply, assign(socket, app_type: app_type)}
end
def handle_params(_, _, socket) do
{:noreply,
socket
|> assign(:page_title, (socket.assigns.live_action == :new && "New App") || "Apps")}
end
defp onboarding(assigns) do
~H"""
<div class="mx-auto max-w-2xl text-center">
<h1 class="mb-5 text-3xl font-medium">You have no Apps.</h1>
<.button type="link" patch={~p"/apps/new"}>
<.icon class="mr-2 h-6 w-6" name="hero-plus" /> Create your first App!
</.button>
</div>
"""
end
end

View file

@ -37,6 +37,9 @@ defmodule PrymnWeb.Router do
live "/servers", ServerLive.Index, :index
live "/servers/new", ServerLive.Index, :new
live "/servers/:id", ServerLive.Show
live "/apps", AppIndexLive
live "/apps/new", AppIndexLive, :new
end
end

View file

@ -0,0 +1,59 @@
defmodule Prymn.AppsTest do
use Prymn.DataCase
alias Prymn.Apps
describe "apps" do
alias Prymn.Apps.App
import Prymn.AppsFixtures
@invalid_attrs %{name: nil}
test "list_apps/0 returns all apps" do
app = app_fixture()
assert Apps.list_apps() == [app]
end
test "get_app!/1 returns the app with given id" do
app = app_fixture()
assert Apps.get_app!(app.id) == app
end
test "create_app/1 with valid data creates a app" do
valid_attrs = %{name: "some name"}
assert {:ok, %App{} = app} = Apps.create_app(valid_attrs)
assert app.name == "some name"
end
test "create_app/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Apps.create_app(@invalid_attrs)
end
test "update_app/2 with valid data updates the app" do
app = app_fixture()
update_attrs = %{name: "some updated name"}
assert {:ok, %App{} = app} = Apps.update_app(app, update_attrs)
assert app.name == "some updated name"
end
test "update_app/2 with invalid data returns error changeset" do
app = app_fixture()
assert {:error, %Ecto.Changeset{}} = Apps.update_app(app, @invalid_attrs)
assert app == Apps.get_app!(app.id)
end
test "delete_app/1 deletes the app" do
app = app_fixture()
assert {:ok, %App{}} = Apps.delete_app(app)
assert_raise Ecto.NoResultsError, fn -> Apps.get_app!(app.id) end
end
test "change_app/1 returns a app changeset" do
app = app_fixture()
assert %Ecto.Changeset{} = Apps.change_app(app)
end
end
end

View file

@ -0,0 +1,20 @@
defmodule Prymn.AppsFixtures do
@moduledoc """
This module defines test helpers for creating
entities via the `Prymn.Apps` context.
"""
@doc """
Generate a app.
"""
def app_fixture(attrs \\ %{}) do
{:ok, app} =
attrs
|> Enum.into(%{
name: "some name"
})
|> Prymn.Apps.create_app()
app
end
end

View file

@ -0,0 +1,11 @@
defmodule Prymn.Repo.Migrations.CreateApps do
use Ecto.Migration
def change do
create table(:apps) do
add :name, :string
timestamps()
end
end
end