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">
|
||||
<div class="pr-2 border-r border-slate-100">
|
||||
<.link navigate={~p"/admin"} class="font-bold">admin mode</.link>
|
||||
</div>
|
||||
<nav>
|
||||
<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>
|
||||
</nav>
|
||||
</section>
|
||||
|
@ -21,12 +24,11 @@
|
|||
<.link href={~p"/"} class="font-bold hover:underline">sloanelybutsurely.com</.link>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><.link href={~p"/writing"} class="hover:underline">writing</.link></li>
|
||||
<li><.link href={~p"/microblog"} class="hover:underline">microblog</.link></li>
|
||||
<li><.link href={~p"/posts"} class="hover:underline">writing</.link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</section>
|
||||
<main class="p-2">
|
||||
<main class="p-2 w-full">
|
||||
{@inner_content}
|
||||
</main>
|
||||
</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
|
||||
|
||||
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
|
||||
post "/admin/session/create", AdminSessionController, :create
|
||||
|
@ -45,6 +46,9 @@ defmodule CMSWeb.Router do
|
|||
pipe_through :requires_admin
|
||||
|
||||
live "/", AdminLive
|
||||
|
||||
live "/posts/new", PostLive, :new
|
||||
live "/posts/:post_id", PostLive, :edit
|
||||
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