mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-12-17 22:47:59 +01:00
post editing
This commit is contained in:
parent
d22ab9aa58
commit
ae6e282424
9 changed files with 153 additions and 65 deletions
|
@ -12,6 +12,7 @@ defmodule Philomena.Posts do
|
|||
alias Philomena.Posts.Post
|
||||
alias Philomena.Forums.Forum
|
||||
alias Philomena.Notifications
|
||||
alias Philomena.Versions
|
||||
|
||||
@doc """
|
||||
Gets a single post.
|
||||
|
@ -122,10 +123,23 @@ defmodule Philomena.Posts do
|
|||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_post(%Post{} = post, attrs) do
|
||||
post
|
||||
|> Post.changeset(attrs)
|
||||
|> Repo.update()
|
||||
def update_post(%Post{} = post, editor, attrs) do
|
||||
now = DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
current_body = post.body
|
||||
current_reason = post.edit_reason
|
||||
|
||||
post_changes =
|
||||
Post.changeset(post, attrs, now)
|
||||
|
||||
Multi.new
|
||||
|> Multi.update(:post, post_changes)
|
||||
|> Multi.run(:version, fn _repo, _changes ->
|
||||
Versions.create_version("Post", post.id, editor.id, %{
|
||||
"body" => current_body,
|
||||
"edit_reason" => current_reason
|
||||
})
|
||||
end)
|
||||
|> Repo.isolated_transaction(:serializable)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
|
|
@ -24,7 +24,7 @@ defmodule Philomena.Posts.Post do
|
|||
field :topic_position, :integer
|
||||
field :hidden_from_users, :boolean, default: false
|
||||
field :anonymous, :boolean, default: false
|
||||
field :edited_at, :naive_datetime
|
||||
field :edited_at, :utc_datetime
|
||||
field :deletion_reason, :string, default: ""
|
||||
field :destroyed_content, :boolean, default: false
|
||||
field :name_at_post_time, :string
|
||||
|
@ -33,10 +33,13 @@ defmodule Philomena.Posts.Post do
|
|||
end
|
||||
|
||||
@doc false
|
||||
def changeset(post, attrs) do
|
||||
def changeset(post, attrs, edited_at \\ nil) do
|
||||
post
|
||||
|> cast(attrs, [])
|
||||
|> validate_required([])
|
||||
|> cast(attrs, [:body, :edit_reason])
|
||||
|> put_change(:edited_at, edited_at)
|
||||
|> validate_required([:body])
|
||||
|> validate_length(:body, min: 1, max: 300_000, count: :bytes)
|
||||
|> validate_length(:edit_reason, max: 70, count: :bytes)
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
|
|
@ -100,10 +100,8 @@ defmodule PhilomenaWeb.Image.CommentController do
|
|||
|> put_flash(:info, "Comment updated successfully.")
|
||||
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image) <> "#comment_#{comment.id}")
|
||||
|
||||
_error ->
|
||||
conn
|
||||
|> put_flash(:error, "There was an error editing your comment")
|
||||
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image))
|
||||
{:error, :comment, changeset, _changes} ->
|
||||
render(conn, "edit.html", comment: conn.assigns.comment, changeset: changeset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
defmodule PhilomenaWeb.Topic.PostController do
|
||||
use PhilomenaWeb, :controller
|
||||
|
||||
alias Philomena.{Forums.Forum, Topics.Topic, Posts}
|
||||
alias Philomena.{Forums.Forum, Topics.Topic, Posts.Post}
|
||||
alias Philomena.Posts
|
||||
alias Philomena.UserStatistics
|
||||
alias Philomena.Repo
|
||||
import Ecto.Query
|
||||
|
||||
plug PhilomenaWeb.FilterBannedUsersPlug
|
||||
plug PhilomenaWeb.UserAttributionPlug
|
||||
plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show
|
||||
plug :load_and_authorize_resource, model: Forum, id_field: "short_name", id_name: "forum_id", persisted: true
|
||||
|
||||
plug :load_topic
|
||||
plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show
|
||||
plug :authorize_resource, model: Topic, id_field: "slug", id_name: "topic_id", persisted: true
|
||||
|
||||
plug PhilomenaWeb.CanaryMapPlug, edit: :edit, update: :edit
|
||||
plug :load_and_authorize_resource, model: Post, only: [:edit, :update], preload: [topic: :forum]
|
||||
|
||||
def create(conn, %{"post" => post_params}) do
|
||||
attributes = conn.assigns.attributes
|
||||
|
@ -33,20 +41,46 @@ defmodule PhilomenaWeb.Topic.PostController do
|
|||
end
|
||||
end
|
||||
|
||||
defp load_topic(%{params: %{"topic_id" => slug}} = conn, _args) do
|
||||
forum = conn.assigns.forum
|
||||
def edit(conn, _params) do
|
||||
changeset = Posts.change_post(conn.assigns.post)
|
||||
render(conn, "edit.html", changeset: changeset)
|
||||
end
|
||||
|
||||
def update(conn, %{"post" => post_params}) do
|
||||
post = conn.assigns.post
|
||||
user = conn.assigns.current_user
|
||||
|
||||
with topic when not is_nil(topic) <- Repo.get_by(Topic, slug: slug, forum_id: forum.id),
|
||||
true <- Canada.Can.can?(user, :show, topic)
|
||||
do
|
||||
conn
|
||||
|> assign(:topic, topic)
|
||||
else
|
||||
_ ->
|
||||
case Posts.update_post(post, user, post_params) do
|
||||
{:ok, _post} ->
|
||||
Posts.reindex_post(post)
|
||||
|
||||
conn
|
||||
|> put_flash(:error, "Couldn't access that topic")
|
||||
|> redirect(external: conn.assigns.referrer)
|
||||
|> put_flash(:info, "Post successfully edited.")
|
||||
|> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic, post_id: post.id) <> "#post_#{post.id}")
|
||||
|
||||
{:error, :post, changeset, _changes} ->
|
||||
render(conn, "edit.html", post: conn.assigns.post, changeset: changeset)
|
||||
end
|
||||
end
|
||||
|
||||
defp load_topic(conn, _opts) do
|
||||
user = conn.assigns.current_user
|
||||
forum = conn.assigns.forum
|
||||
topic =
|
||||
Topic
|
||||
|> where(forum_id: ^forum.id, slug: ^conn.params["topic_id"])
|
||||
|> preload(:forum)
|
||||
|> Repo.one()
|
||||
|
||||
cond do
|
||||
is_nil(topic) ->
|
||||
PhilomenaWeb.NotFoundPlug.call(conn)
|
||||
|
||||
not Canada.Can.can?(user, :show, topic) ->
|
||||
PhilomenaWeb.NotAuthorizedPlug.call(conn)
|
||||
|
||||
true ->
|
||||
Plug.Conn.assign(conn, :topic, topic)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -107,6 +107,7 @@ defmodule PhilomenaWeb.Router do
|
|||
resources "/topics", TopicController, only: [:new, :create] do
|
||||
resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true
|
||||
resources "/read", Topic.ReadController, only: [:create], singleton: true
|
||||
resources "/posts", Topic.PostController, only: [:edit, :update]
|
||||
end
|
||||
|
||||
resources "/subscription", Forum.SubscriptionController, only: [:create, :delete], singleton: true
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.field
|
||||
= text_input f, :edit_reason, class: "input input--wide", placeholder: "Reason for edit"
|
||||
= error_tag f, :edit_reason
|
||||
|
||||
.block__tab.communication-edit__tab.hidden data-tab="preview"
|
||||
' [Loading preview...]
|
||||
|
|
|
@ -6,14 +6,16 @@ div
|
|||
i.fa.fa-flag>
|
||||
' Report
|
||||
|
||||
/- if post.edited_at && can?(:read, post)
|
||||
/ br
|
||||
/ a href=forum_topic_post_history_path(post.topic.forum, post.topic, post)
|
||||
/ | Edited
|
||||
/ =<> friendly_time(post.edited_at)
|
||||
/ - if post.edit_reason.present?
|
||||
/ | because:
|
||||
/ =<> post.edit_reason
|
||||
= if not is_nil(@post.edited_at) and can?(@conn, :read, @post) do
|
||||
br
|
||||
a href=Routes.forum_topic_post_history_path(@conn, :index, @post.topic.forum, @post.topic, @post)
|
||||
' Edited
|
||||
=> pretty_time(@post.edited_at)
|
||||
|
||||
= if @post.edit_reason not in [nil, ""] do
|
||||
' because:
|
||||
=> @post.edit_reason
|
||||
|
||||
div
|
||||
- link_path = Routes.forum_topic_path(@conn, :show, @post.topic.forum, @post.topic, post_id: @post.id) <> "#post_#{@post.id}"
|
||||
- safe_author = textile_safe_author(@post)
|
||||
|
@ -30,7 +32,10 @@ div
|
|||
a.communication__interaction.post-reply href=link_path data-reply-url=link_path data-author=safe_author
|
||||
i.fa.fa-reply>
|
||||
' Reply
|
||||
/span.owner-options.hidden
|
||||
/ strong =<> link_to edit_forum_topic_post_path(post.topic.forum, post.topic, post), class: 'communication__interaction' do
|
||||
/ i.fas.fa-edit
|
||||
/ ' Edit
|
||||
|
||||
= if can?(@conn, :edit, @post) do
|
||||
span.owner-options
|
||||
strong
|
||||
a.communication__interaction href=Routes.forum_topic_post_path(@conn, :edit, @post.topic.forum, @post.topic, @post)
|
||||
i.fa.fa-pencil>
|
||||
' Edit
|
||||
|
|
32
lib/philomena_web/templates/topic/post/edit.html.slime
Normal file
32
lib/philomena_web/templates/topic/post/edit.html.slime
Normal file
|
@ -0,0 +1,32 @@
|
|||
= form_for @changeset, Routes.forum_topic_post_path(@conn, :update, @post.topic.forum, @post.topic, @post), fn f ->
|
||||
= if @changeset.action do
|
||||
.alert.alert-danger
|
||||
p Oops, something went wrong! Please check the errors below.
|
||||
|
||||
.block
|
||||
.block__header.block__header--js-tabbed
|
||||
a.selected href="#" data-click-tab="write"
|
||||
i.fa.fa-pencil>
|
||||
' Edit
|
||||
|
||||
a href="#" data-click-tab="preview"
|
||||
i.fa.fa-eye>
|
||||
' Preview
|
||||
|
||||
.block__tab.communication-edit__tab.selected data-tab="write"
|
||||
= render PhilomenaWeb.TextileView, "_help.html", conn: @conn
|
||||
= render PhilomenaWeb.TextileView, "_toolbar.html", conn: @conn
|
||||
|
||||
.field
|
||||
= textarea f, :body, class: "input input--wide input--text js-preview-input js-toolbar-input", placeholder: "Please read the site rules before posting and use [spoiler][/spoiler] for above-rating stuff.", required: true
|
||||
= error_tag f, :body
|
||||
|
||||
.field
|
||||
= text_input f, :edit_reason, class: "input input--wide", placeholder: "Reason for edit"
|
||||
= error_tag f, :edit_reason
|
||||
|
||||
.block__tab.communication-edit__tab.hidden data-tab="preview"
|
||||
' [Loading preview...]
|
||||
|
||||
.block__content.communication-edit__actions
|
||||
=> submit "Edit", class: "button", data: [disable_with: raw("Posting…")]
|
|
@ -7,39 +7,39 @@ h1
|
|||
|
||||
= for version <- @versions do
|
||||
article.block.communication
|
||||
.block__content.flex.flex--no-wrap
|
||||
.flex__fixed.spacing-right
|
||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn
|
||||
.block__content.flex.flex--no-wrap
|
||||
.flex__fixed.spacing-right
|
||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn
|
||||
|
||||
.flex__grow.communication__body
|
||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @post, awards: true, conn: @conn
|
||||
br
|
||||
.flex__grow.communication__body
|
||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @post, awards: true, conn: @conn
|
||||
br
|
||||
|
||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @post, conn: @conn
|
||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @post, conn: @conn
|
||||
|
||||
.communication__body__text
|
||||
= for edit <- version.difference do
|
||||
= case edit do
|
||||
- {:eq, value} ->
|
||||
= escape_nl2br(value)
|
||||
.communication__body__text
|
||||
= for edit <- version.difference do
|
||||
= case edit do
|
||||
- {:eq, value} ->
|
||||
= escape_nl2br(value)
|
||||
|
||||
- {:ins, value} ->
|
||||
ins.differ = escape_nl2br(value)
|
||||
- {:ins, value} ->
|
||||
ins.differ = escape_nl2br(value)
|
||||
|
||||
- {:del, value} ->
|
||||
del.differ = escape_nl2br(value)
|
||||
- {:del, value} ->
|
||||
del.differ = escape_nl2br(value)
|
||||
|
||||
.block__content.communication__options
|
||||
.flex.flex--wrap.flex--spaced-out
|
||||
div
|
||||
= if version.edit_reason not in [nil, ""] do
|
||||
' Reason:
|
||||
= version.edit_reason
|
||||
- else
|
||||
' No reason given
|
||||
.block__content.communication__options
|
||||
.flex.flex--wrap.flex--spaced-out
|
||||
div
|
||||
= if version.edit_reason not in [nil, ""] do
|
||||
' Reason:
|
||||
= version.edit_reason
|
||||
- else
|
||||
' No reason given
|
||||
|
||||
.flex__right
|
||||
' Edited
|
||||
=> pretty_time(version.created_at)
|
||||
' by
|
||||
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: version, conn: @conn
|
||||
.flex__right
|
||||
' Edited
|
||||
=> pretty_time(version.created_at)
|
||||
' by
|
||||
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: version, conn: @conn
|
Loading…
Reference in a new issue