Compare commits

..

2 commits

Author SHA1 Message Date
Ivan R. 750429fc62
feat: fancy admin panel 2024-08-31 17:06:02 +05:00
Ivan R. a8dbdadb90
fix: reset esbuild config 2024-08-31 17:02:54 +05:00
12 changed files with 113 additions and 24 deletions

View file

@ -1,10 +1,58 @@
.admin-panel { .admin-panel {
display: flex; display: flex;
gap: 16px; gap: 32px;
margin-top: 16px; margin-top: 16px;
} }
.admin-panel ul { .admin-panel .menu {
padding: 0; padding: 0;
margin: 0; margin: 0;
list-style-type: none;
}
.admin-panel .menu li {
padding: 10px;
background-color: #20232f;
}
.admin-panel .menu li:first-child {
border-radius: 8px 8px 0 0;
}
.admin-panel .menu li:not(:first-child) {
border-top: 1px solid #353544;
}
.admin-panel .menu li:last-child {
border-radius: 0 0 8px 8px;
}
.admin-panel h3 {
margin-top: 0;
}
.admin-panel .stats {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.admin-panel .stat {
background-color: #20232f;
padding: 16px;
border-radius: 8px;
display: flex;
flex-direction: column;
gap: 8px;
align-items: center;
width: min-content;
}
.admin-panel .stat .value {
font-size: 48px;
font-weight: bold;
}
.admin-panel .stat .name {
text-align: center;
} }

View file

@ -22,6 +22,8 @@ import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view" import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar" import topbar from "../vendor/topbar"
import "../css/core/app.css" import "../css/core/app.css"
import "../css/admin.css"
import "../css/home.css"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, { let liveSocket = new LiveSocket("/live", Socket, {

View file

@ -38,7 +38,7 @@ config :esbuild,
version: "0.17.11", version: "0.17.11",
comfycamp: [ comfycamp: [
args: args:
~w(js/app.js css/home.css css/admin.css --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
cd: Path.expand("../assets", __DIR__), cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)} env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
] ]

View file

@ -33,6 +33,14 @@ defmodule Comfycamp.Accounts do
Repo.all(User) Repo.all(User)
end end
def count_users() do
Repo.one(from u in "users", select: count(u.id))
end
def count_unapproved_users() do
Repo.one(from u in "users", select: count(u.id), where: not u.is_approved)
end
@doc """ @doc """
Gets a user by email and password. Gets a user by email and password.

View file

@ -2,12 +2,15 @@
<main> <main>
<div class="limiter"> <div class="limiter">
<.link href={~p"/"}>
Главная страница
</.link>
<h1>Панель администратора</h1> <h1>Панель администратора</h1>
<.back navigate={~p"/"}>Главная страница</.back>
<div class="admin-panel"> <div class="admin-panel">
<ul> <ul class="menu">
<li>
<.link href={~p"/admin"}>
Управление
</.link>
</li>
<li> <li>
<.link href={~p"/admin/notes"}> <.link href={~p"/admin/notes"}>
Заметки Заметки

View file

@ -15,11 +15,6 @@
} }
/> />
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} /> <link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<%= if assigns[:stylesheets] do %>
<%= for stylesheet <- @stylesheets do %>
<link phx-track-static rel="stylesheet" href={stylesheet} />
<% end %>
<% end %>
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}> <script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script> </script>
<link <link

View file

@ -1,15 +1,23 @@
defmodule ComfycampWeb.AdminPageController do defmodule ComfycampWeb.AdminPageController do
use ComfycampWeb, :controller use ComfycampWeb, :controller
alias Comfycamp.Accounts
def home(conn, _params) do def home(conn, _params) do
user_count = Accounts.count_users()
unapproved_user_count = Accounts.count_unapproved_users()
conn conn
|> put_layout(html: :admin) |> put_layout(html: :admin)
|> render(:home, page_title: "Админка", stylesheets: ["/assets/admin.css"]) |> render(:home,
page_title: "Админка",
user_count: user_count,
unapproved_user_count: unapproved_user_count
)
end end
def services(conn, _params) do def services(conn, _params) do
conn conn
|> put_layout(html: :admin) |> put_layout(html: :admin)
|> render(:home, page_title: "Админка", stylesheets: ["/assets/admin.css"]) |> render(:home, page_title: "Админка")
end end
end end

View file

@ -3,7 +3,31 @@ defmodule ComfycampWeb.AdminPageHTML do
def home(assigns) do def home(assigns) do
~H""" ~H"""
Добро пожаловать, админ. <div>
<h3>Управление сайтом</h3>
<div class="stats">
<.stat name="Всего пользователей" value={@user_count} />
<.stat
name="Неодобренных пользователей"
value={@unapproved_user_count}
/>
</div>
</div>
"""
end
@doc """
Card for statistical data.
"""
attr :name, :string, required: true
attr :value, :any, required: true
def stat(assigns) do
~H"""
<div class="stat">
<div class="value"><%= @value %></div>
<div class="name"><%= @name %></div>
</div>
""" """
end end
end end

View file

@ -2,14 +2,14 @@ defmodule ComfycampWeb.HomeController do
use ComfycampWeb, :controller use ComfycampWeb, :controller
def index(conn, _params) do def index(conn, _params) do
render(conn, :index, page_title: "Главная", stylesheets: ["/assets/home.css"]) render(conn, :index, page_title: "Главная")
end end
def mastodon(conn, _params) do def mastodon(conn, _params) do
render(conn, :mastodon, page_title: "Mastodon", stylesheets: ["/assets/home.css"]) render(conn, :mastodon, page_title: "Mastodon")
end end
def nextcloud(conn, _params) do def nextcloud(conn, _params) do
render(conn, :nextcloud, page_title: "Nextcloud", stylesheets: ["/assets/home.css"]) render(conn, :nextcloud, page_title: "Nextcloud")
end end
end end

View file

@ -9,7 +9,7 @@ defmodule ComfycampWeb.NotesEditorController do
conn conn
|> put_layout(html: :admin) |> put_layout(html: :admin)
|> render(:index, page_title: "Заметки", notes: notes, stylesheets: ["/assets/admin.css"]) |> render(:index, page_title: "Заметки", notes: notes)
end end
def new(conn, _params) do def new(conn, _params) do
@ -83,7 +83,7 @@ defmodule ComfycampWeb.NotesEditorController do
conn conn
|> put_layout(html: :admin) |> put_layout(html: :admin)
|> render(:show, page_title: "Заметка", note: note, stylesheets: ["/assets/admin.css"]) |> render(:show, page_title: "Заметка", note: note)
end end
def delete(conn, %{"id" => id}) do def delete(conn, %{"id" => id}) do

View file

@ -4,6 +4,7 @@ defmodule ComfycampWeb.NotesEditorHTML do
def index(assigns) do def index(assigns) do
~H""" ~H"""
<div> <div>
<h3>Заметки</h3>
<.link href={~p"/admin/notes/new"}> <.link href={~p"/admin/notes/new"}>
Создать заметку Создать заметку
</.link> </.link>
@ -26,8 +27,8 @@ defmodule ComfycampWeb.NotesEditorHTML do
def show(assigns) do def show(assigns) do
~H""" ~H"""
<div> <div>
<.back navigate={~p"/admin/notes"}>Назад</.back>
<h3><%= @note.title %></h3> <h3><%= @note.title %></h3>
<.back navigate={~p"/admin/notes"}>Назад</.back>
<.link href={~p"/admin/notes/#{@note}/edit"}> <.link href={~p"/admin/notes/#{@note}/edit"}>
Редактировать Редактировать
@ -44,7 +45,7 @@ defmodule ComfycampWeb.NotesEditorHTML do
def new(assigns) do def new(assigns) do
~H""" ~H"""
<div> <div>
<h2>Новая заметка</h2> <h3>Новая заметка</h3>
<.note_form changeset={@changeset} action={~p"/admin/notes"} /> <.note_form changeset={@changeset} action={~p"/admin/notes"} />
</div> </div>
""" """
@ -53,7 +54,7 @@ defmodule ComfycampWeb.NotesEditorHTML do
def edit(assigns) do def edit(assigns) do
~H""" ~H"""
<div> <div>
<h2>Редактировать заметку</h2> <h3>Редактировать заметку</h3>
<.note_form changeset={@changeset} action={~p"/admin/notes/#{@changeset.data.id}"} /> <.note_form changeset={@changeset} action={~p"/admin/notes/#{@changeset.data.id}"} />
</div> </div>
""" """

View file

@ -19,7 +19,7 @@ defmodule ComfycampWeb.UserEditorController do
conn conn
|> put_layout(html: :admin) |> put_layout(html: :admin)
|> render(:show, page_title: user.email, user: user, stylesheets: ["/assets/admin.css"]) |> render(:show, page_title: user.email, user: user)
end end
def approve(conn, %{"id" => id}) do def approve(conn, %{"id" => id}) do