primitive history viewing

This commit is contained in:
byte[] 2019-12-05 21:46:51 -05:00
parent 2a338d86c7
commit 9fc04b9b71
9 changed files with 139 additions and 71 deletions

View file

@ -7,35 +7,47 @@ defmodule Philomena.Versions do
alias Philomena.Repo alias Philomena.Repo
alias Philomena.Versions.Version alias Philomena.Versions.Version
alias Philomena.Users.User
@doc """ def load_data_and_associations(versions, parent) do
Returns the list of versions. user_ids =
versions
|> Enum.map(& &1.whodunnit)
|> Enum.reject(&is_nil/1)
## Examples users =
User
|> where([u], u.id in ^user_ids)
|> preload(awards: :badge)
|> Repo.all()
|> Map.new(&{to_string(&1.id), &1})
iex> list_versions() {versions, _last_body} =
[%Version{}, ...] versions
|> Enum.reverse()
|> Enum.map_reduce(nil, fn version, previous_body ->
yaml = YamlElixir.read_from_string!(version.object || "")
body = yaml["body"] || ""
edit_reason = yaml["edit_reason"]
""" v =
def list_versions do %{
Repo.all(Version) version |
parent: parent,
user: users[version.whodunnit],
body: body,
edit_reason: edit_reason,
difference: difference(previous_body, body)
}
{v, body}
end)
Enum.reverse(versions)
end end
@doc """ defp difference(nil, next), do: [eq: next]
Gets a single version. defp difference(previous, next), do: String.myers_difference(previous, next)
Raises `Ecto.NoResultsError` if the Version does not exist.
## Examples
iex> get_version!(123)
%Version{}
iex> get_version!(456)
** (Ecto.NoResultsError)
"""
def get_version!(id), do: Repo.get!(Version, id)
@doc """ @doc """
Creates a version. Creates a version.
@ -54,51 +66,4 @@ defmodule Philomena.Versions do
|> Version.changeset(attrs) |> Version.changeset(attrs)
|> Repo.insert() |> Repo.insert()
end end
@doc """
Updates a version.
## Examples
iex> update_version(version, %{field: new_value})
{:ok, %Version{}}
iex> update_version(version, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_version(%Version{} = version, attrs) do
version
|> Version.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Version.
## Examples
iex> delete_version(version)
{:ok, %Version{}}
iex> delete_version(version)
{:error, %Ecto.Changeset{}}
"""
def delete_version(%Version{} = version) do
Repo.delete(version)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking version changes.
## Examples
iex> change_version(version)
%Ecto.Changeset{source: %Version{}}
"""
def change_version(%Version{} = version) do
Version.changeset(version, %{})
end
end end

View file

@ -0,0 +1,16 @@
defimpl Philomena.Attribution, for: Philomena.Versions.Version do
def object_identifier(version) do
to_string(version.parent.id)
end
def best_user_identifier(version) do
to_string(version.user.id)
end
def anonymous?(version) do
same_user?(version.user, version.parent) and !!version.parent.anonymous
end
defp same_user?(%{id: id}, %{user_id: id}), do: true
defp same_user?(_user, _parent), do: false
end

View file

@ -11,6 +11,12 @@ defmodule Philomena.Versions.Version do
field :item_id, :integer field :item_id, :integer
field :item_type, :string field :item_type, :string
field :user, :any, virtual: true
field :parent, :any, virtual: true
field :body, :string, virtual: true
field :edit_reason, :string, virtual: true
field :difference, :any, virtual: true
timestamps(inserted_at: :created_at, updated_at: false) timestamps(inserted_at: :created_at, updated_at: false)
end end

View file

@ -0,0 +1,28 @@
defmodule PhilomenaWeb.Image.Comment.HistoryController do
use PhilomenaWeb, :controller
alias Philomena.Versions.Version
alias Philomena.Versions
alias Philomena.Comments.Comment
alias Philomena.Images.Image
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.CanaryMapPlug, index: :show
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
plug :load_and_authorize_resource, model: Comment, id_name: "comment_id", persisted: true, preload: [:user, :image]
def index(conn, _params) do
comment = conn.assigns.comment
versions =
Version
|> where(item_type: "Comment", item_id: ^comment.id)
|> order_by(desc: :created_at)
|> limit(25)
|> Repo.all()
|> Versions.load_data_and_associations(comment)
render(conn, "index.html", versions: versions)
end
end

View file

@ -152,6 +152,7 @@ defmodule PhilomenaWeb.Router do
resources "/images", ImageController, only: [:index, :show, :new, :create] do resources "/images", ImageController, only: [:index, :show, :new, :create] do
resources "/comments", Image.CommentController, only: [:index, :show, :create] do resources "/comments", Image.CommentController, only: [:index, :show, :create] do
resources "/reports", Image.Comment.ReportController, only: [:new, :create] resources "/reports", Image.Comment.ReportController, only: [:new, :create]
resources "/history", Image.Comment.HistoryController, only: [:index]
end end
resources "/tags", Image.TagController, only: [:update], singleton: true resources "/tags", Image.TagController, only: [:update], singleton: true
resources "/sources", Image.SourceController, only: [:update], singleton: true resources "/sources", Image.SourceController, only: [:update], singleton: true

View file

@ -0,0 +1,46 @@
h1
' Viewing last 25 versions of comment by
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @comment, conn: @conn
' on image
a href=Routes.image_path(@conn, :show, @comment.image)
| #
= @comment.image_id
= 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: @comment, conn: @conn
.flex__grow.communication__body
span.communication__body__sender-name = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @comment, awards: true, conn: @conn
br
= render PhilomenaWeb.UserAttributionView, "_anon_user_title.html", object: @comment, conn: @conn
.communication__body__text
= for edit <- version.difference do
= case edit do
- {:eq, value} ->
= text_to_html(value)
- {:ins, value} ->
ins.differ = text_to_html(value)
- {:del, value} ->
del.differ = text_to_html(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
.flex__right
' Edited
= pretty_time(version.created_at)
' by
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @version, conn: @conn

View file

@ -0,0 +1,3 @@
defmodule PhilomenaWeb.Image.Comment.HistoryView do
use PhilomenaWeb, :view
end

View file

@ -60,7 +60,8 @@ defmodule Philomena.MixProject do
{:bamboo_smtp, "~> 1.7"}, {:bamboo_smtp, "~> 1.7"},
{:remote_ip, "~> 0.2.0"}, {:remote_ip, "~> 0.2.0"},
{:briefly, "~> 0.3.0"}, {:briefly, "~> 0.3.0"},
{:phoenix_mtm, "~> 1.0.0"} {:phoenix_mtm, "~> 1.0.0"},
{:yaml_elixir, "~> 2.4.0"}
] ]
end end

View file

@ -61,4 +61,6 @@
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
"telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
"yamerl": {:hex, :yamerl, "0.7.0", "e51dba652dce74c20a88294130b48051ebbbb0be7d76f22de064f0f3ccf0aaf5", [:rebar3], [], "hexpm"},
"yaml_elixir": {:hex, :yaml_elixir, "2.4.0", "2f444abc3c994c902851fde56b6a9cb82895c291c05a0490a289035c2e62ae71", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm"},
} }