create simple posts
This commit is contained in:
parent
ef3d6d8b7a
commit
d02833e472
10 changed files with 171 additions and 7 deletions
25
lib/cms/posts.ex
Normal file
25
lib/cms/posts.ex
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
defmodule CMS.Posts do
|
||||||
|
@moduledoc false
|
||||||
|
alias CMS.Posts.Post
|
||||||
|
alias CMS.Repo
|
||||||
|
|
||||||
|
def create_post(attrs) do
|
||||||
|
%Post{}
|
||||||
|
|> Post.changeset(attrs)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_post(post, attrs) do
|
||||||
|
post
|
||||||
|
|> Post.changeset(attrs)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_post!(id) do
|
||||||
|
Repo.get!(Post, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_posts do
|
||||||
|
Repo.all(Post)
|
||||||
|
end
|
||||||
|
end
|
20
lib/cms/posts/post.ex
Normal file
20
lib/cms/posts/post.ex
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
defmodule CMS.Posts.Post do
|
||||||
|
@moduledoc false
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
import Ecto.Changeset, warn: false
|
||||||
|
|
||||||
|
@primary_key {:id, :binary_id, autogenerate: true}
|
||||||
|
schema "posts" do
|
||||||
|
field :title, :string
|
||||||
|
field :contents, :string
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(%__MODULE__{} = post, attrs \\ %{}) do
|
||||||
|
post
|
||||||
|
|> cast(attrs, [:title, :contents])
|
||||||
|
|> validate_required([:contents])
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,11 +1,14 @@
|
||||||
<div :if={@admin?} class="flex flex-row justify-between py-1 px-3 mb-2 border-b border-slate-100">
|
<div
|
||||||
|
:if={@admin?}
|
||||||
|
class="flex flex-row justify-between py-1 px-3 md:mb-2 border-b border-slate-100"
|
||||||
|
>
|
||||||
<section class="flex flex-row gap-x-2">
|
<section class="flex flex-row gap-x-2">
|
||||||
<div class="pr-2 border-r border-slate-100">
|
<div class="pr-2 border-r border-slate-100">
|
||||||
<.link navigate={~p"/admin"} class="font-bold">admin mode</.link>
|
<.link navigate={~p"/admin"} class="font-bold">admin mode</.link>
|
||||||
</div>
|
</div>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="flex flex-row">
|
<ul class="flex flex-row">
|
||||||
<.link href="#" class="hover:underline">new post</.link>
|
<.link href={~p"/admin/posts/new"} class="hover:underline">new post</.link>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</section>
|
</section>
|
||||||
|
@ -21,12 +24,11 @@
|
||||||
<.link href={~p"/"} class="font-bold hover:underline">sloanelybutsurely.com</.link>
|
<.link href={~p"/"} class="font-bold hover:underline">sloanelybutsurely.com</.link>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li><.link href={~p"/writing"} class="hover:underline">writing</.link></li>
|
<li><.link href={~p"/posts"} class="hover:underline">writing</.link></li>
|
||||||
<li><.link href={~p"/microblog"} class="hover:underline">microblog</.link></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</section>
|
</section>
|
||||||
<main class="p-2">
|
<main class="p-2 w-full">
|
||||||
{@inner_content}
|
{@inner_content}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
21
lib/cms_web/controllers/post_controller.ex
Normal file
21
lib/cms_web/controllers/post_controller.ex
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
defmodule CMSWeb.PostController do
|
||||||
|
use CMSWeb, :controller
|
||||||
|
|
||||||
|
alias CMS.Posts
|
||||||
|
|
||||||
|
def index(conn, _params) do
|
||||||
|
posts = Posts.list_posts()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:posts, posts)
|
||||||
|
|> render(:index)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show(conn, %{"post_id" => post_id}) do
|
||||||
|
post = Posts.get_post!(post_id)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:post, post)
|
||||||
|
|> render(:show)
|
||||||
|
end
|
||||||
|
end
|
6
lib/cms_web/controllers/post_html.ex
Normal file
6
lib/cms_web/controllers/post_html.ex
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
defmodule CMSWeb.PostHTML do
|
||||||
|
@moduledoc false
|
||||||
|
use CMSWeb, :html
|
||||||
|
|
||||||
|
embed_templates "post_html/*"
|
||||||
|
end
|
6
lib/cms_web/controllers/post_html/index.html.heex
Normal file
6
lib/cms_web/controllers/post_html/index.html.heex
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<%= for post <- @posts do %>
|
||||||
|
<article id={"post-#{post.id}"}>
|
||||||
|
<h2><.link href={~p"/posts/#{post}"}>{post.title}</.link></h2>
|
||||||
|
<p>{post.contents}</p>
|
||||||
|
</article>
|
||||||
|
<% end %>
|
5
lib/cms_web/controllers/post_html/show.html.heex
Normal file
5
lib/cms_web/controllers/post_html/show.html.heex
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<header class="flex flex-row justify-between">
|
||||||
|
<h1>{@post.title}</h1>
|
||||||
|
<.link :if={@admin?} href={~p"/admin/posts/#{@post}"}>edit</.link>
|
||||||
|
</header>
|
||||||
|
<p>{@post.contents}</p>
|
62
lib/cms_web/live/post_live.ex
Normal file
62
lib/cms_web/live/post_live.ex
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
defmodule CMSWeb.PostLive do
|
||||||
|
@moduledoc false
|
||||||
|
use CMSWeb, :live_view
|
||||||
|
|
||||||
|
alias CMS.Posts
|
||||||
|
alias CMS.Posts.Post
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_params(_params, _uri, %{assigns: %{live_action: :new}} = socket) do
|
||||||
|
post = %Post{}
|
||||||
|
changeset = Post.changeset(post)
|
||||||
|
|
||||||
|
socket = assign(socket, post: post, form: to_form(changeset))
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_params(%{"post_id" => post_id}, _uri, %{assigns: %{live_action: :edit}} = socket) do
|
||||||
|
post = Posts.get_post!(post_id)
|
||||||
|
|
||||||
|
changeset = Post.changeset(post)
|
||||||
|
|
||||||
|
socket = assign(socket, post: post, form: to_form(changeset))
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("save_post", %{"post" => attrs}, %{assigns: %{live_action: :new}} = socket) do
|
||||||
|
socket =
|
||||||
|
case Posts.create_post(attrs) do
|
||||||
|
{:ok, post} -> push_navigate(socket, to: ~p"/admin/posts/#{post}")
|
||||||
|
{:error, changeset} -> assign(socket, form: to_form(changeset))
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("save_post", %{"post" => attrs}, %{assigns: %{post: post, live_action: :edit}} = socket) do
|
||||||
|
socket =
|
||||||
|
case Posts.update_post(post, attrs) do
|
||||||
|
{:ok, post} ->
|
||||||
|
assign(socket, post: post, form: post |> Post.changeset() |> to_form())
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
assign(socket, form: to_form(changeset))
|
||||||
|
end
|
||||||
|
|
||||||
|
{:noreply, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<.form for={@form} class="flex flex-col" phx-submit="save_post">
|
||||||
|
<input type="text" id={@form[:title].id} name={@form[:title].name} value={@form[:title].value} />
|
||||||
|
<textarea id={@form[:contents].id} name={@form[:contents].name}>{@form[:contents].value} </textarea>
|
||||||
|
<button type="submit" class="self-end">save</button>
|
||||||
|
</.form>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
|
@ -32,8 +32,9 @@ defmodule CMSWeb.Router do
|
||||||
pipe_through :supports_admin_action
|
pipe_through :supports_admin_action
|
||||||
|
|
||||||
get "/", PageController, :home
|
get "/", PageController, :home
|
||||||
get "/writing", PageController, :writing
|
|
||||||
get "/microblog", PageController, :microblog
|
get "/posts", PostController, :index
|
||||||
|
get "/posts/:post_id", PostController, :show
|
||||||
|
|
||||||
live "/sign-in", AdminLoginLive
|
live "/sign-in", AdminLoginLive
|
||||||
post "/admin/session/create", AdminSessionController, :create
|
post "/admin/session/create", AdminSessionController, :create
|
||||||
|
@ -45,6 +46,9 @@ defmodule CMSWeb.Router do
|
||||||
pipe_through :requires_admin
|
pipe_through :requires_admin
|
||||||
|
|
||||||
live "/", AdminLive
|
live "/", AdminLive
|
||||||
|
|
||||||
|
live "/posts/new", PostLive, :new
|
||||||
|
live "/posts/:post_id", PostLive, :edit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
13
priv/repo/migrations/20250222164951_add_posts_table.exs
Normal file
13
priv/repo/migrations/20250222164951_add_posts_table.exs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
defmodule CMS.Repo.Migrations.AddPostsTable do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:posts, primary_key: false) do
|
||||||
|
add :id, :uuid, primary_key: true
|
||||||
|
add :title, :text
|
||||||
|
add :contents, :text, null: false, default: ""
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue