mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-12-18 06:57: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.Posts.Post
|
||||||
alias Philomena.Forums.Forum
|
alias Philomena.Forums.Forum
|
||||||
alias Philomena.Notifications
|
alias Philomena.Notifications
|
||||||
|
alias Philomena.Versions
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single post.
|
Gets a single post.
|
||||||
|
@ -122,10 +123,23 @@ defmodule Philomena.Posts do
|
||||||
{:error, %Ecto.Changeset{}}
|
{:error, %Ecto.Changeset{}}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def update_post(%Post{} = post, attrs) do
|
def update_post(%Post{} = post, editor, attrs) do
|
||||||
post
|
now = DateTime.utc_now() |> DateTime.truncate(:second)
|
||||||
|> Post.changeset(attrs)
|
current_body = post.body
|
||||||
|> Repo.update()
|
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
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
@ -24,7 +24,7 @@ defmodule Philomena.Posts.Post do
|
||||||
field :topic_position, :integer
|
field :topic_position, :integer
|
||||||
field :hidden_from_users, :boolean, default: false
|
field :hidden_from_users, :boolean, default: false
|
||||||
field :anonymous, :boolean, default: false
|
field :anonymous, :boolean, default: false
|
||||||
field :edited_at, :naive_datetime
|
field :edited_at, :utc_datetime
|
||||||
field :deletion_reason, :string, default: ""
|
field :deletion_reason, :string, default: ""
|
||||||
field :destroyed_content, :boolean, default: false
|
field :destroyed_content, :boolean, default: false
|
||||||
field :name_at_post_time, :string
|
field :name_at_post_time, :string
|
||||||
|
@ -33,10 +33,13 @@ defmodule Philomena.Posts.Post do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
def changeset(post, attrs) do
|
def changeset(post, attrs, edited_at \\ nil) do
|
||||||
post
|
post
|
||||||
|> cast(attrs, [])
|
|> cast(attrs, [:body, :edit_reason])
|
||||||
|> validate_required([])
|
|> 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
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
|
|
@ -100,10 +100,8 @@ defmodule PhilomenaWeb.Image.CommentController do
|
||||||
|> put_flash(:info, "Comment updated successfully.")
|
|> put_flash(:info, "Comment updated successfully.")
|
||||||
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image) <> "#comment_#{comment.id}")
|
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image) <> "#comment_#{comment.id}")
|
||||||
|
|
||||||
_error ->
|
{:error, :comment, changeset, _changes} ->
|
||||||
conn
|
render(conn, "edit.html", comment: conn.assigns.comment, changeset: changeset)
|
||||||
|> put_flash(:error, "There was an error editing your comment")
|
|
||||||
|> redirect(to: Routes.image_path(conn, :show, conn.assigns.image))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
defmodule PhilomenaWeb.Topic.PostController do
|
defmodule PhilomenaWeb.Topic.PostController do
|
||||||
use PhilomenaWeb, :controller
|
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.UserStatistics
|
||||||
alias Philomena.Repo
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
plug PhilomenaWeb.FilterBannedUsersPlug
|
plug PhilomenaWeb.FilterBannedUsersPlug
|
||||||
plug PhilomenaWeb.UserAttributionPlug
|
plug PhilomenaWeb.UserAttributionPlug
|
||||||
plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show
|
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_and_authorize_resource, model: Forum, id_field: "short_name", id_name: "forum_id", persisted: true
|
||||||
|
|
||||||
plug :load_topic
|
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
|
def create(conn, %{"post" => post_params}) do
|
||||||
attributes = conn.assigns.attributes
|
attributes = conn.assigns.attributes
|
||||||
|
@ -33,20 +41,46 @@ defmodule PhilomenaWeb.Topic.PostController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp load_topic(%{params: %{"topic_id" => slug}} = conn, _args) do
|
def edit(conn, _params) do
|
||||||
forum = conn.assigns.forum
|
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
|
user = conn.assigns.current_user
|
||||||
|
|
||||||
with topic when not is_nil(topic) <- Repo.get_by(Topic, slug: slug, forum_id: forum.id),
|
case Posts.update_post(post, user, post_params) do
|
||||||
true <- Canada.Can.can?(user, :show, topic)
|
{:ok, _post} ->
|
||||||
do
|
Posts.reindex_post(post)
|
||||||
conn
|
|
||||||
|> assign(:topic, topic)
|
|
||||||
else
|
|
||||||
_ ->
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:error, "Couldn't access that topic")
|
|> put_flash(:info, "Post successfully edited.")
|
||||||
|> redirect(external: conn.assigns.referrer)
|
|> 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
|
end
|
||||||
end
|
end
|
|
@ -107,6 +107,7 @@ defmodule PhilomenaWeb.Router do
|
||||||
resources "/topics", TopicController, only: [:new, :create] do
|
resources "/topics", TopicController, only: [:new, :create] do
|
||||||
resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true
|
resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true
|
||||||
resources "/read", Topic.ReadController, only: [:create], singleton: true
|
resources "/read", Topic.ReadController, only: [:create], singleton: true
|
||||||
|
resources "/posts", Topic.PostController, only: [:edit, :update]
|
||||||
end
|
end
|
||||||
|
|
||||||
resources "/subscription", Forum.SubscriptionController, only: [:create, :delete], singleton: true
|
resources "/subscription", Forum.SubscriptionController, only: [:create, :delete], singleton: true
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
.field
|
.field
|
||||||
= text_input f, :edit_reason, class: "input input--wide", placeholder: "Reason for edit"
|
= 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"
|
.block__tab.communication-edit__tab.hidden data-tab="preview"
|
||||||
' [Loading preview...]
|
' [Loading preview...]
|
||||||
|
|
|
@ -6,14 +6,16 @@ div
|
||||||
i.fa.fa-flag>
|
i.fa.fa-flag>
|
||||||
' Report
|
' Report
|
||||||
|
|
||||||
/- if post.edited_at && can?(:read, post)
|
= if not is_nil(@post.edited_at) and can?(@conn, :read, @post) do
|
||||||
/ br
|
br
|
||||||
/ a href=forum_topic_post_history_path(post.topic.forum, post.topic, post)
|
a href=Routes.forum_topic_post_history_path(@conn, :index, @post.topic.forum, @post.topic, @post)
|
||||||
/ | Edited
|
' Edited
|
||||||
/ =<> friendly_time(post.edited_at)
|
=> pretty_time(@post.edited_at)
|
||||||
/ - if post.edit_reason.present?
|
|
||||||
/ | because:
|
= if @post.edit_reason not in [nil, ""] do
|
||||||
/ =<> post.edit_reason
|
' because:
|
||||||
|
=> @post.edit_reason
|
||||||
|
|
||||||
div
|
div
|
||||||
- link_path = Routes.forum_topic_path(@conn, :show, @post.topic.forum, @post.topic, post_id: @post.id) <> "#post_#{@post.id}"
|
- 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)
|
- 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
|
a.communication__interaction.post-reply href=link_path data-reply-url=link_path data-author=safe_author
|
||||||
i.fa.fa-reply>
|
i.fa.fa-reply>
|
||||||
' Reply
|
' Reply
|
||||||
/span.owner-options.hidden
|
|
||||||
/ strong =<> link_to edit_forum_topic_post_path(post.topic.forum, post.topic, post), class: 'communication__interaction' do
|
= if can?(@conn, :edit, @post) do
|
||||||
/ i.fas.fa-edit
|
span.owner-options
|
||||||
/ ' Edit
|
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
|
= for version <- @versions do
|
||||||
article.block.communication
|
article.block.communication
|
||||||
.block__content.flex.flex--no-wrap
|
.block__content.flex.flex--no-wrap
|
||||||
.flex__fixed.spacing-right
|
.flex__fixed.spacing-right
|
||||||
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn
|
= render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn
|
||||||
|
|
||||||
.flex__grow.communication__body
|
.flex__grow.communication__body
|
||||||
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @post, awards: true, conn: @conn
|
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @post, awards: true, conn: @conn
|
||||||
br
|
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
|
.communication__body__text
|
||||||
= for edit <- version.difference do
|
= for edit <- version.difference do
|
||||||
= case edit do
|
= case edit do
|
||||||
- {:eq, value} ->
|
- {:eq, value} ->
|
||||||
= escape_nl2br(value)
|
= escape_nl2br(value)
|
||||||
|
|
||||||
- {:ins, value} ->
|
- {:ins, value} ->
|
||||||
ins.differ = escape_nl2br(value)
|
ins.differ = escape_nl2br(value)
|
||||||
|
|
||||||
- {:del, value} ->
|
- {:del, value} ->
|
||||||
del.differ = escape_nl2br(value)
|
del.differ = escape_nl2br(value)
|
||||||
|
|
||||||
.block__content.communication__options
|
.block__content.communication__options
|
||||||
.flex.flex--wrap.flex--spaced-out
|
.flex.flex--wrap.flex--spaced-out
|
||||||
div
|
div
|
||||||
= if version.edit_reason not in [nil, ""] do
|
= if version.edit_reason not in [nil, ""] do
|
||||||
' Reason:
|
' Reason:
|
||||||
= version.edit_reason
|
= version.edit_reason
|
||||||
- else
|
- else
|
||||||
' No reason given
|
' No reason given
|
||||||
|
|
||||||
.flex__right
|
.flex__right
|
||||||
' Edited
|
' Edited
|
||||||
=> pretty_time(version.created_at)
|
=> pretty_time(version.created_at)
|
||||||
' by
|
' by
|
||||||
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: version, conn: @conn
|
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: version, conn: @conn
|
Loading…
Reference in a new issue