Skip to content

Commit

Permalink
CRUD boilerplate for autohosts
Browse files Browse the repository at this point in the history
  • Loading branch information
geekingfrog committed Jul 27, 2024
1 parent 7f5de08 commit 26a60c0
Show file tree
Hide file tree
Showing 18 changed files with 421 additions and 9 deletions.
19 changes: 18 additions & 1 deletion lib/teiserver/autohost.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Teiserver.Autohost do
alias Teiserver.Autohost.Autohost
alias Teiserver.AutohostQueries
alias Teiserver.Repo

def create_autohost(attrs \\ %{}) do
Expand All @@ -8,5 +9,21 @@ defmodule Teiserver.Autohost do
|> Repo.insert()
end

defdelegate get_autohost(id), to: Teiserver.AutohostQueries
def change_autohost(%Autohost{} = autohost, attrs \\ %{}) do
Autohost.changeset(autohost, attrs)
end

def update_autohost(%Autohost{} = autohost, attrs) do
autohost |> change_autohost(attrs) |> Repo.update()
end

@spec delete(Autohost.t()) :: :ok | {:error, term()}
def delete(%Autohost{} = autohost) do
case Repo.delete(autohost) do
{:ok, _} -> :ok
{:error, err} -> {:error, err}
end
end

defdelegate get_by_id(id), to: AutohostQueries
end
7 changes: 7 additions & 0 deletions lib/teiserver/autohost/libs/autohost_lib.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule Teiserver.AutohostLib do
@spec icon :: String.t()
def icon, do: "fa-solid fa-robot"

@spec colours :: atom
def colours, do: :success2
end
16 changes: 13 additions & 3 deletions lib/teiserver/autohost/queries/autohost_query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@ defmodule Teiserver.AutohostQueries do
use TeiserverWeb, :queries
alias Teiserver.Autohost.Autohost

@spec get_autohost(Autohost.id()) :: Autohost.t() | nil
def get_autohost(nil), do: nil
@doc """
Returns all autohosts.
That list may get big, so think about streaming and/or paginating
but for now this will do.
"""
@spec list_autohosts() :: [Autohost.t()]
def list_autohosts() do
base_query() |> Repo.all()
end

@spec get_by_id(Autohost.id()) :: Autohost.t() | nil
def get_by_id(nil), do: nil

def get_autohost(id) do
def get_by_id(id) do
base_query() |> where_id(id) |> Repo.one()
end

Expand Down
2 changes: 2 additions & 0 deletions lib/teiserver/autohost/schemas/autohost.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ defmodule Teiserver.Autohost.Autohost do
def changeset(autohost, attrs) do
autohost
|> cast(attrs, [:name])
|> Ecto.Changeset.validate_required([:name])
|> Ecto.Changeset.validate_length(:name, min: 3, max: 30)
end
end
2 changes: 0 additions & 2 deletions lib/teiserver/o_auth/libs/application_lib.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
defmodule Teiserver.OAuth.ApplicationLib do

@spec icon :: String.t()
def icon, do: "fa-solid fa-passport"

@spec colours :: atom
def colours, do: :success2

end
23 changes: 23 additions & 0 deletions lib/teiserver_web/components/autohost_components.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule TeiserverWeb.Components.AutohostComponent do
use Phoenix.Component
alias TeiserverWeb.CoreComponents, as: CC

attr :changeset, Ecto.Changeset, required: true
attr :action, :string, required: true

def autohost_form(assigns) do
~H"""
<CC.simple_form :let={f} for={@changeset} action={@action}>
<CC.error :if={@changeset.action}>
Oops, something went wrong! Please check the errors below.
</CC.error>
<CC.input field={f[:name]} type="text" label="Name" />
<:actions>
<CC.button type="submit" class="btn-primary"><%= @button_label %></CC.button>
</:actions>
</CC.simple_form>
"""
end
end
1 change: 0 additions & 1 deletion lib/teiserver_web/components/layouts/root.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
</script>
<script defer phx-track-static type="text/javascript" src={~p"/js/bootstrap.min.js"}>
</script>

</head>
<body class="container-fluid px-0 d-flex flex-column">
<.flash_group flash={@flash} />
Expand Down
144 changes: 144 additions & 0 deletions lib/teiserver_web/controllers/admin/autohost_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
defmodule TeiserverWeb.Admin.AutohostController do
@moduledoc """
management of autohosts and their credentials
"""

use TeiserverWeb, :controller

alias Teiserver.{Autohost, AutohostQueries}

plug Bodyguard.Plug.Authorize,
# The policy should be Admin or something fairly high. But while we're
# developping the new lobby, it's easier if this is allowed for any
# contributors
policy: Teiserver.Staff,
action: {Phoenix.Controller, :action_name},
user: {Teiserver.Account.AuthLib, :current_user}

plug :add_breadcrumb, name: 'Admin', url: '/teiserver/admin'
plug :add_breadcrumb, name: 'Autohosts', url: '/teiserver/admin/autohost'

@spec index(Plug.Conn.t(), map()) :: Plug.Conn.t()
def index(conn, _params) do
autohosts = AutohostQueries.list_autohosts()

conn
|> render("index.html", autohosts: autohosts)
end

@spec new(Plug.Conn.t(), map()) :: Plug.Conn.t()
def new(conn, _params) do
changeset = Autohost.change_autohost(%Autohost.Autohost{})

conn
|> assign(:page_title, "")
|> render("new.html", changeset: changeset)
end

@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()
def create(conn, %{"autohost" => attrs}) do
case Autohost.create_autohost(attrs) do
{:ok, %Autohost.Autohost{} = autohost} ->
conn
|> put_flash(:info, "Autohost created")
|> redirect(to: ~p"/teiserver/admin/autohost/#{autohost.id}")

{:error, changeset} ->
conn
|> assign(:page_title, "BAR - new autohost")
|> put_status(400)
|> render("new.html", changeset: changeset)
end
end

def create(conn, _),
do:
conn
|> put_status(400)
|> assign(:page_title, "BAR - new autohost")
|> render("new.html", changeset: Autohost.Autohost.changeset(%Autohost.Autohost{}, %{}))

@spec show(Plug.Conn.t(), map()) :: Plug.Conn.t()
def show(conn, assigns) do
case Autohost.get_by_id(Map.get(assigns, "id")) do
%Autohost.Autohost{} = autohost ->
conn
|> assign(:page_title, "BAR - autohost #{autohost.name}")
|> render("show.html", autohost: autohost)

nil ->
conn
|> put_status(:not_found)
|> render("not_found.html")
end
end

@spec edit(Plug.Conn.t(), map()) :: Plug.Conn.t()
def edit(conn, assigns) do
case Autohost.get_by_id(Map.get(assigns, "id")) do
%Autohost.Autohost{} = autohost ->
changeset = Autohost.change_autohost(autohost)

conn
|> assign(:page_title, "BAR - edit autohost #{autohost.name}")
|> render("edit.html", autohost: autohost, changeset: changeset)

nil ->
conn
|> put_status(:not_found)
|> render("not_found.html")
end
end

@spec update(Plug.Conn.t(), map()) :: Plug.Conn.t()
def update(conn, %{"autohost" => params} = assigns) do
case Autohost.get_by_id(Map.get(assigns, "id")) do
%Autohost.Autohost{} = autohost ->
case Autohost.update_autohost(autohost, params) do
{:ok, autohost} ->
conn
|> put_flash(:info, "Autohost updated")
|> render(:show, autohost: autohost)

{:error, changeset} ->
conn
|> put_status(400)
|> render(:edit, autohost: autohost, changeset: changeset)
end

nil ->
conn
|> put_status(:not_found)
|> render("not_found.html")
end
end

def update(conn, _) do
conn
|> put_status(:not_found)
|> render("not_found.html")
end

@spec delete(Plug.Conn.t(), map()) :: Plug.Conn.t()
def delete(conn, assigns) do
case Autohost.get_by_id(Map.get(assigns, "id")) do
%Autohost.Autohost{} = autohost ->
case Autohost.delete(autohost) do
:ok ->
conn
|> put_flash(:info, "Deleted!")
|> redirect(to: ~p"/teiserver/admin/autohost")

{:error, err} ->
conn
|> put_flash(:danger, inspect(err))
|> redirect(to: ~p"/teiserver/admin/autohost/#{autohost.id}")
end

nil ->
conn
|> put_status(:not_found)
|> render("not_found.html")
end
end
end
1 change: 1 addition & 0 deletions lib/teiserver_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -688,5 +688,6 @@ defmodule TeiserverWeb.Router do
get("/lobbies/:id/lobby_chat/:page", LobbyController, :lobby_chat)

resources("/oauth_application", OAuthApplicationController)
resources("/autohost", AutohostController)
end
end
16 changes: 16 additions & 0 deletions lib/teiserver_web/templates/admin/autohost/edit.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="card page-card">
<div class="card-body">
<h1>Edit autohost <%= @autohost.name %></h1>

<div class="row d-flex justify-content-center">
<div class="col-md-6">
<.autohost_form
button_label="Update"
changeset={@changeset}
action={~p"/teiserver/admin/autohost/#{@autohost.id}"}
method="PUT"
/>
</div>
</div>
</div>
</div>
39 changes: 39 additions & 0 deletions lib/teiserver_web/templates/admin/autohost/index.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<div class="container">
<h1>List of autohosts</h1>

<p>
<div class="btn btn-sm btn-outline-success">
<a href={~p"/teiserver/admin/autohost/new"}>Create autohost</a>
</div>
</p>

<%= if length(@autohosts) > 0 do %>
<table class="table">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>actions</th>
</tr>
</thead>
<tbody>
<%= for autohost <- @autohosts do %>
<tr>
<td><%= autohost.id %></td>
<td><%= autohost.name %></td>
<td>
<a href={~p"/teiserver/admin/autohost/#{autohost.id}"}>
<button type="button" class="btn btn-primary btn-sm">show</button>
</a>
<a href={~p"/teiserver/admin/autohost/#{autohost.id}/edit"}>
<button type="button" class="btn btn-primary btn-sm">Edit</button>
</a>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
No autohost!
<% end %>
</div>
15 changes: 15 additions & 0 deletions lib/teiserver_web/templates/admin/autohost/new.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="card page-card">
<div class="card-body">
<h1>Create a new autohost</h1>

<div class="row d-flex justify-content-center">
<div class="col-md-6">
<.autohost_form
button_label="Create autohost"
changeset={@changeset}
action={~p"/teiserver/admin/autohost"}
/>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>No autohost found</h1>

<a href={~p"/teiserver/admin/autohost/"}>Back to the list of autohosts</a>
17 changes: 17 additions & 0 deletions lib/teiserver_web/templates/admin/autohost/show.html.heex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="container">
<h1>Autohost: <%= @autohost.name %></h1>
<%!-- TODO: add a list of oauth credentials + action to delete them --%>

<p>
<a href={~p"/teiserver/admin/autohost/#{@autohost.id}/edit"}>
<button type="button" class="btn btn-primary">Edit</button>
</a>

<%!-- TODO: add a modal confirmation for deleting an autohost --%>
<CC.simple_form for={} action={~p"/teiserver/admin/autohost/#{@autohost.id}"} method="delete">
<:actions>
<CC.button type="submit" class="btn-danger">Delete</CC.button>
</:actions>
</CC.simple_form>
</p>
</div>
9 changes: 8 additions & 1 deletion lib/teiserver_web/templates/admin/general/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,16 @@
url={~p"/teiserver/admin/oauth_application"}
size={:small}
>
OAuth applications
OAuth applications
</.menu_card>

<.menu_card
icon={Teiserver.AutohostLib.icon()}
url={~p"/teiserver/admin/autohost"}
size={:small}
>
Autohosts
</.menu_card>
</div>

<div class="row">
Expand Down
9 changes: 9 additions & 0 deletions lib/teiserver_web/views/admin/autohost_view.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule TeiserverWeb.Admin.AutohostView do
use TeiserverWeb, :view

import TeiserverWeb.Components.AutohostComponent
alias TeiserverWeb.CoreComponents, as: CC

def view_colour(), do: Teiserver.AutohostLib.colours()
def icon(), do: Teiserver.AutohostLib.icon()
end
2 changes: 1 addition & 1 deletion test/teiserver/autohost/autohost_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ defmodule Teiserver.Autohost.AutohostTest do
test "can create autohost" do
{:ok, autohost} = Autohost.create_autohost(%{name: "autohost_test"})
assert autohost != nil
assert Autohost.get_autohost(autohost.id) == autohost
assert Autohost.get_by_id(autohost.id) == autohost
end
end
Loading

0 comments on commit 26a60c0

Please sign in to comment.