feat: admin panel for notes
This commit is contained in:
parent
45c91eb3bf
commit
5a00fdf843
14 changed files with 224 additions and 24 deletions
|
@ -255,10 +255,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-nav-link {
|
.back-nav-link {
|
||||||
font-size: 0.875rem;
|
display: flex;
|
||||||
line-height: 1.25rem;
|
gap: 8px;
|
||||||
font-weight: 600;
|
}
|
||||||
line-height: 1.5rem;
|
|
||||||
|
.back-nav-link svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container {
|
.table-container {
|
||||||
|
|
|
@ -1,18 +1,39 @@
|
||||||
defmodule Comfycamp.Note do
|
defmodule Comfycamp.Notes do
|
||||||
use Ecto.Schema
|
@moduledoc """
|
||||||
import Ecto.Changeset
|
The Notes context.
|
||||||
|
"""
|
||||||
|
|
||||||
schema "notes" do
|
import Ecto.Query, warn: false
|
||||||
field :title, :string
|
alias Comfycamp.Repo
|
||||||
field :markdown, :string
|
alias Comfycamp.Notes.Note
|
||||||
|
|
||||||
timestamps(type: :utc_datetime)
|
def change_note(%Note{} = note, attrs \\ %{}) do
|
||||||
|
note
|
||||||
|
|> Note.changeset(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
def create_note(attrs \\ %{}) do
|
||||||
def changeset(note, attrs) do
|
%Note{}
|
||||||
|
|> Note.changeset(attrs)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_note(%Note{} = note, attrs \\ %{}) do
|
||||||
note
|
note
|
||||||
|> cast(attrs, [:title, :markdown])
|
|> Note.changeset(attrs)
|
||||||
|> validate_required([:title, :markdown])
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_note(%Note{} = note) do
|
||||||
|
Repo.delete(note)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_note!(id) do
|
||||||
|
Note
|
||||||
|
|> Repo.get!(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_notes() do
|
||||||
|
Repo.all(Note)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
18
lib/comfycamp/notes/note.ex
Normal file
18
lib/comfycamp/notes/note.ex
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Comfycamp.Notes.Note do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "notes" do
|
||||||
|
field :title, :string
|
||||||
|
field :markdown, :string
|
||||||
|
|
||||||
|
timestamps(type: :utc_datetime)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(note, attrs) do
|
||||||
|
note
|
||||||
|
|> cast(attrs, [:title, :markdown])
|
||||||
|
|> validate_required([:title, :markdown])
|
||||||
|
end
|
||||||
|
end
|
|
@ -313,8 +313,7 @@ defmodule ComfycampWeb.CoreComponents do
|
||||||
def error(assigns) do
|
def error(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<p class="error">
|
<p class="error">
|
||||||
<.icon name="hero-exclamation-circle-mini" class="mt-0.5 h-5 w-5 flex-none" />
|
<.exclamation_circle_icon /> <%= render_slot(@inner_block) %>
|
||||||
<%= render_slot(@inner_block) %>
|
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
@ -461,10 +460,9 @@ defmodule ComfycampWeb.CoreComponents do
|
||||||
|
|
||||||
def back(assigns) do
|
def back(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="mt-16">
|
<div>
|
||||||
<.link navigate={@navigate} class="back-nav-link">
|
<.link navigate={@navigate} class="back-nav-link">
|
||||||
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
|
<.arrow_left_icon /> <%= render_slot(@inner_block) %>
|
||||||
<%= render_slot(@inner_block) %>
|
|
||||||
</.link>
|
</.link>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
10
lib/comfycamp_web/components/icons/arrow_left_icon.svg.heex
Normal file
10
lib/comfycamp_web/components/icons/arrow_left_icon.svg.heex
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 247 B |
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="limiter">
|
<div class="limiter">
|
||||||
<h1>Comfycamp - админка</h1>
|
|
||||||
<.link href={~p"/"}>
|
<.link href={~p"/"}>
|
||||||
Главная страница
|
Главная страница
|
||||||
</.link>
|
</.link>
|
||||||
|
<h1>Панель администратора</h1>
|
||||||
<div class="admin-panel">
|
<div class="admin-panel">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<.link href={~p"/admin/posts"}>
|
<.link href={~p"/admin/notes"}>
|
||||||
Посты
|
Заметки
|
||||||
</.link>
|
</.link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
89
lib/comfycamp_web/controllers/notes_controller.ex
Normal file
89
lib/comfycamp_web/controllers/notes_controller.ex
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
defmodule ComfycampWeb.NotesController do
|
||||||
|
use ComfycampWeb, :controller
|
||||||
|
|
||||||
|
alias Comfycamp.Notes
|
||||||
|
alias Comfycamp.Notes.Note
|
||||||
|
|
||||||
|
def index(conn, _params) do
|
||||||
|
notes = Notes.list_notes()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:index, page_title: "Заметки", notes: notes)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new(conn, _params) do
|
||||||
|
changeset = Notes.change_note(%Note{})
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:new, page_title: "Новая заметка", changeset: changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit(conn, %{"id" => id}) do
|
||||||
|
note = Notes.get_note!(id)
|
||||||
|
|
||||||
|
changeset = Notes.change_note(note)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:edit, page_title: "Редактировать заметку", changeset: changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(conn, %{"note" => note_params}) do
|
||||||
|
case Notes.create_note(note_params) do
|
||||||
|
{:ok, note} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Заметка сохранена.")
|
||||||
|
|> redirect(to: ~p"/admin/notes/#{note}")
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:error, "Ошибка при обновлении заметки.")
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:new, page_title: "Создать заметку", changeset: changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(conn, %{"id" => id, "note" => note_params}) do
|
||||||
|
note = Notes.get_note!(id)
|
||||||
|
|
||||||
|
case Notes.update_note(note, note_params) do
|
||||||
|
{:ok, note} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Заметка обновлена.")
|
||||||
|
|> redirect(to: ~p"/admin/notes/#{note}")
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:error, "Ошибка при обновлении заметки.")
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:edit, page_title: "Редактировать заметку", changeset: changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show(conn, %{"id" => id}) do
|
||||||
|
note = Notes.get_note!(id)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:show, page_title: "Заметка", note: note)
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(conn, %{"id" => id}) do
|
||||||
|
note = Notes.get_note!(id)
|
||||||
|
|
||||||
|
case Notes.delete_note(note) do
|
||||||
|
{:ok, _note} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Заметка удалена.")
|
||||||
|
|> redirect(to: ~p"/admin/notes")
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:error, "Ошибка при удалении заметки.")
|
||||||
|
|> put_layout(html: :admin)
|
||||||
|
|> render(:edit, page_title: "Редактировать заметку", changeset: changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
5
lib/comfycamp_web/controllers/notes_html.ex
Normal file
5
lib/comfycamp_web/controllers/notes_html.ex
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule ComfycampWeb.NotesHTML do
|
||||||
|
use ComfycampWeb, :html
|
||||||
|
|
||||||
|
embed_templates "notes_html/*"
|
||||||
|
end
|
4
lib/comfycamp_web/controllers/notes_html/edit.html.heex
Normal file
4
lib/comfycamp_web/controllers/notes_html/edit.html.heex
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<div>
|
||||||
|
<h2>Редактировать заметку</h2>
|
||||||
|
<.note_form changeset={@changeset} action={~p"/admin/notes/#{@changeset.data.id}"} />
|
||||||
|
</div>
|
17
lib/comfycamp_web/controllers/notes_html/index.html.heex
Normal file
17
lib/comfycamp_web/controllers/notes_html/index.html.heex
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<div>
|
||||||
|
<.link href={~p"/admin/notes/new"}>
|
||||||
|
Создать заметку
|
||||||
|
</.link>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<%= for note <- @notes do %>
|
||||||
|
<li>
|
||||||
|
<.link href={~p"/admin/notes/#{note}"}>
|
||||||
|
<%= note.title %>
|
||||||
|
</.link>
|
||||||
|
|
||||||
|
<%= note.updated_at %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
4
lib/comfycamp_web/controllers/notes_html/new.html.heex
Normal file
4
lib/comfycamp_web/controllers/notes_html/new.html.heex
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<div>
|
||||||
|
<h2>Новая заметка</h2>
|
||||||
|
<.note_form changeset={@changeset} action={~p"/admin/notes"} />
|
||||||
|
</div>
|
18
lib/comfycamp_web/controllers/notes_html/note_form.html.heex
Normal file
18
lib/comfycamp_web/controllers/notes_html/note_form.html.heex
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<.simple_form :let={f} for={@changeset} action={@action}>
|
||||||
|
<.input field={f[:title]} type="text" label="Заголовок" />
|
||||||
|
<.input field={f[:markdown]} type="textarea" label="Содержание (markdown)" />
|
||||||
|
|
||||||
|
<:actions>
|
||||||
|
<.button>Сохранить</.button>
|
||||||
|
</:actions>
|
||||||
|
</.simple_form>
|
||||||
|
|
||||||
|
<%= if @changeset.data.id do %>
|
||||||
|
<.link
|
||||||
|
href={~p"/admin/notes/#{@changeset.data}"}
|
||||||
|
method="DELETE"
|
||||||
|
data-confirm="Вы уверены?"
|
||||||
|
>
|
||||||
|
Удалить
|
||||||
|
</.link>
|
||||||
|
<% end %>
|
13
lib/comfycamp_web/controllers/notes_html/show.html.heex
Normal file
13
lib/comfycamp_web/controllers/notes_html/show.html.heex
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<div>
|
||||||
|
<.back navigate={~p"/admin/notes"}>Назад</.back>
|
||||||
|
<h3><%= @note.title %></h3>
|
||||||
|
|
||||||
|
<.link href={~p"/admin/notes/#{@note}/edit"}>
|
||||||
|
Редактировать
|
||||||
|
</.link>
|
||||||
|
|
||||||
|
<p>Создана: <%= @note.inserted_at %></p>
|
||||||
|
<p>Обновлена: <%= @note.updated_at %></p>
|
||||||
|
|
||||||
|
<pre><%= @note.markdown %></pre>
|
||||||
|
</div>
|
|
@ -89,8 +89,8 @@ defmodule ComfycampWeb.Router do
|
||||||
pipe_through [:browser, :require_authenticated_user, :ensure_admin]
|
pipe_through [:browser, :require_authenticated_user, :ensure_admin]
|
||||||
|
|
||||||
get "/", AdminPageController, :home
|
get "/", AdminPageController, :home
|
||||||
get "/posts", AdminPageController, :posts
|
|
||||||
get "/users", AdminPageController, :users
|
get "/users", AdminPageController, :users
|
||||||
get "/services", AdminPageController, :services
|
get "/services", AdminPageController, :services
|
||||||
|
resources "/notes", NotesController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue