mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
controller/view for tag changes, source changes
This commit is contained in:
parent
0e5de7aaa2
commit
dd8ecd531c
31 changed files with 431 additions and 34 deletions
|
@ -14,4 +14,10 @@ defprotocol Philomena.Attribution do
|
||||||
"""
|
"""
|
||||||
@spec best_user_identifier(struct()) :: String.t()
|
@spec best_user_identifier(struct()) :: String.t()
|
||||||
def best_user_identifier(object)
|
def best_user_identifier(object)
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Return whether this object is considered to be anonymous.
|
||||||
|
"""
|
||||||
|
@spec anonymous?(struct()) :: true | false
|
||||||
|
def anonymous?(object)
|
||||||
end
|
end
|
|
@ -6,4 +6,8 @@ defimpl Philomena.Attribution, for: Philomena.Comments.Comment do
|
||||||
def best_user_identifier(comment) do
|
def best_user_identifier(comment) do
|
||||||
to_string(comment.user_id || comment.fingerprint || comment.ip)
|
to_string(comment.user_id || comment.fingerprint || comment.ip)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def anonymous?(comment) do
|
||||||
|
!!comment.anonymous
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -12,6 +12,7 @@ defmodule Philomena.Images do
|
||||||
alias Philomena.SourceChanges.SourceChange
|
alias Philomena.SourceChanges.SourceChange
|
||||||
alias Philomena.TagChanges.TagChange
|
alias Philomena.TagChanges.TagChange
|
||||||
alias Philomena.Tags
|
alias Philomena.Tags
|
||||||
|
alias Philomena.Tags.Tag
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets a single image.
|
Gets a single image.
|
||||||
|
@ -118,11 +119,27 @@ defmodule Philomena.Images do
|
||||||
|
|
||||||
{:ok, count}
|
{:ok, count}
|
||||||
end)
|
end)
|
||||||
|
|> Multi.run(:added_tag_count, fn repo, %{image: {_image, added_tags, _removed}} ->
|
||||||
|
tag_ids = added_tags |> Enum.map(& &1.id)
|
||||||
|
tags = Tag |> where([t], t.id in ^tag_ids)
|
||||||
|
|
||||||
|
{count, nil} = repo.update_all(tags, inc: [images_count: 1])
|
||||||
|
|
||||||
|
{:ok, count}
|
||||||
|
end)
|
||||||
|
|> Multi.run(:removed_tag_count, fn repo, %{image: {_image, _added, removed_tags}} ->
|
||||||
|
tag_ids = removed_tags |> Enum.map(& &1.id)
|
||||||
|
tags = Tag |> where([t], t.id in ^tag_ids)
|
||||||
|
|
||||||
|
{count, nil} = repo.update_all(tags, inc: [images_count: -1])
|
||||||
|
|
||||||
|
{:ok, count}
|
||||||
|
end)
|
||||||
|> Repo.isolated_transaction(:serializable)
|
|> Repo.isolated_transaction(:serializable)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp tag_change_attributes(attribution, image, tag, added, user) do
|
defp tag_change_attributes(attribution, image, tag, added, user) do
|
||||||
now = DateTime.utc_now() |> DateTime.truncate(:second)
|
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||||
user_id =
|
user_id =
|
||||||
case user do
|
case user do
|
||||||
nil -> nil
|
nil -> nil
|
||||||
|
@ -134,6 +151,7 @@ defmodule Philomena.Images do
|
||||||
tag_id: tag.id,
|
tag_id: tag.id,
|
||||||
user_id: user_id,
|
user_id: user_id,
|
||||||
created_at: now,
|
created_at: now,
|
||||||
|
updated_at: now,
|
||||||
tag_name_cache: tag.name,
|
tag_name_cache: tag.name,
|
||||||
ip: attribution[:ip],
|
ip: attribution[:ip],
|
||||||
fingerprint: attribution[:fingerprint],
|
fingerprint: attribution[:fingerprint],
|
||||||
|
|
|
@ -6,4 +6,8 @@ defimpl Philomena.Attribution, for: Philomena.Images.Image do
|
||||||
def best_user_identifier(image) do
|
def best_user_identifier(image) do
|
||||||
to_string(image.user_id || image.fingerprint || image.ip)
|
to_string(image.user_id || image.fingerprint || image.ip)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def anonymous?(image) do
|
||||||
|
!!image.anonymous
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -16,9 +16,14 @@ defmodule Philomena.Images.TagDiffer do
|
||||||
{tags, actually_added, actually_removed} =
|
{tags, actually_added, actually_removed} =
|
||||||
apply_changes(tags, added_tags, removed_tags)
|
apply_changes(tags, added_tags, removed_tags)
|
||||||
|
|
||||||
|
{tag_list_cache, tag_list_plus_alias_cache} =
|
||||||
|
create_caches(tags)
|
||||||
|
|
||||||
changeset
|
changeset
|
||||||
|> put_change(:added_tags, actually_added)
|
|> put_change(:added_tags, actually_added)
|
||||||
|> put_change(:removed_tags, actually_removed)
|
|> put_change(:removed_tags, actually_removed)
|
||||||
|
|> put_change(:tag_list_cache, tag_list_cache)
|
||||||
|
|> put_change(:tag_list_plus_alias_cache, tag_list_plus_alias_cache)
|
||||||
|> put_assoc(:tags, tags)
|
|> put_assoc(:tags, tags)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -88,4 +93,26 @@ defmodule Philomena.Images.TagDiffer do
|
||||||
|
|
||||||
{tags, actually_added, actually_removed}
|
{tags, actually_added, actually_removed}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp create_caches(tags) do
|
||||||
|
tag_list_cache =
|
||||||
|
tags
|
||||||
|
|> Tag.display_order()
|
||||||
|
|> Enum.map_join(", ", & &1.name)
|
||||||
|
|
||||||
|
tag_ids =
|
||||||
|
tags |> Enum.map(& &1.id)
|
||||||
|
|
||||||
|
aliases =
|
||||||
|
Tag
|
||||||
|
|> where([t], t.aliased_tag_id in ^tag_ids)
|
||||||
|
|> Repo.all()
|
||||||
|
|
||||||
|
tag_list_plus_alias_cache =
|
||||||
|
(tags ++ aliases)
|
||||||
|
|> Tag.display_order()
|
||||||
|
|> Enum.map_join(", ", & &1.name)
|
||||||
|
|
||||||
|
{tag_list_cache, tag_list_plus_alias_cache}
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -6,4 +6,8 @@ defimpl Philomena.Attribution, for: Philomena.Posts.Post do
|
||||||
def best_user_identifier(post) do
|
def best_user_identifier(post) do
|
||||||
to_string(post.user_id || post.fingerprint || post.ip)
|
to_string(post.user_id || post.fingerprint || post.ip)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def anonymous?(post) do
|
||||||
|
!!post.anonymous
|
||||||
|
end
|
||||||
end
|
end
|
13
lib/philomena/source_changes/attribution.ex
Normal file
13
lib/philomena/source_changes/attribution.ex
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
defimpl Philomena.Attribution, for: Philomena.SourceChanges.SourceChange do
|
||||||
|
def object_identifier(source_change) do
|
||||||
|
to_string(source_change.image_id || source_change.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def best_user_identifier(source_change) do
|
||||||
|
to_string(source_change.user_id || source_change.fingerprint || source_change.ip)
|
||||||
|
end
|
||||||
|
|
||||||
|
def anonymous?(source_change) do
|
||||||
|
source_change.user_id == source_change.image.user_id and !!source_change.image.anonymous
|
||||||
|
end
|
||||||
|
end
|
13
lib/philomena/tag_changes/attribution.ex
Normal file
13
lib/philomena/tag_changes/attribution.ex
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
defimpl Philomena.Attribution, for: Philomena.TagChanges.TagChange do
|
||||||
|
def object_identifier(tag_change) do
|
||||||
|
to_string(tag_change.image_id || tag_change.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def best_user_identifier(tag_change) do
|
||||||
|
to_string(tag_change.user_id || tag_change.fingerprint || tag_change.ip)
|
||||||
|
end
|
||||||
|
|
||||||
|
def anonymous?(tag_change) do
|
||||||
|
tag_change.user_id == tag_change.image.user_id and !!tag_change.image.anonymous
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,8 +15,10 @@ defmodule Philomena.Tags do
|
||||||
existent_tags =
|
existent_tags =
|
||||||
Tag
|
Tag
|
||||||
|> where([t], t.name in ^tag_names)
|
|> where([t], t.name in ^tag_names)
|
||||||
|> preload(:implied_tags)
|
|> preload([:implied_tags, aliased_tag: :implied_tags])
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|
|> Enum.map(& &1.aliased_tag || &1)
|
||||||
|
|> Enum.uniq()
|
||||||
|
|
||||||
existent_tag_names =
|
existent_tag_names =
|
||||||
existent_tags
|
existent_tags
|
||||||
|
|
|
@ -75,6 +75,21 @@ defmodule Philomena.Tags.Tag do
|
||||||
|> Enum.reject(&"" == &1)
|
|> Enum.reject(&"" == &1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def display_order(tags) do
|
||||||
|
tags
|
||||||
|
|> Enum.sort_by(&{
|
||||||
|
&1.category != "rating",
|
||||||
|
&1.category != "origin",
|
||||||
|
&1.category != "character",
|
||||||
|
&1.category != "oc",
|
||||||
|
&1.category != "species",
|
||||||
|
&1.category != "content-fanmade",
|
||||||
|
&1.category != "content-official",
|
||||||
|
&1.category != "spoiler",
|
||||||
|
&1.name
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
def clean_tag_name(name) do
|
def clean_tag_name(name) do
|
||||||
# Downcase, replace extra runs of spaces, replace unicode quotes
|
# Downcase, replace extra runs of spaces, replace unicode quotes
|
||||||
# with ascii quotes, trim space from end
|
# with ascii quotes, trim space from end
|
||||||
|
|
|
@ -6,4 +6,8 @@ defimpl Philomena.Attribution, for: Philomena.Topics.Topic do
|
||||||
def best_user_identifier(topic) do
|
def best_user_identifier(topic) do
|
||||||
to_string(topic.user_id)
|
to_string(topic.user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def anonymous?(topic) do
|
||||||
|
!!topic.anonymous
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -64,6 +64,13 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
|
||||||
when action in [:show, :index],
|
when action in [:show, :index],
|
||||||
do: true
|
do: true
|
||||||
|
|
||||||
|
# Comment on images where that is allowed
|
||||||
|
def can?(_user, :create_comment, %Image{hidden_from_users: false, commenting_allowed: true}), do: true
|
||||||
|
|
||||||
|
# Edit metadata on images where that is allowed
|
||||||
|
def can?(_user, :edit_metadata, %Image{hidden_from_users: false, tag_editing_allowed: true}), do: true
|
||||||
|
def can?(%User{id: id}, :edit_description, %Image{user_id: id, hidden_from_users: false, description_editing_allowed: true}), do: true
|
||||||
|
|
||||||
# Vote on images they can see
|
# Vote on images they can see
|
||||||
def can?(user, :vote, image), do: can?(user, :show, image)
|
def can?(user, :vote, image), do: can?(user, :show, image)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ defmodule PhilomenaWeb.Image.CommentController do
|
||||||
alias Philomena.Repo
|
alias Philomena.Repo
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show
|
plug PhilomenaWeb.CanaryMapPlug, create: :create_comment, edit: :create_comment, update: :create_comment
|
||||||
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
||||||
|
|
||||||
# Undo the previous private parameter screwery
|
# Undo the previous private parameter screwery
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
defmodule PhilomenaWeb.Image.SourceChangeController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias Philomena.Images.Image
|
||||||
|
alias Philomena.SourceChanges.SourceChange
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
plug PhilomenaWeb.CanaryMapPlug, index: :show
|
||||||
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
||||||
|
|
||||||
|
def index(conn, params) do
|
||||||
|
image = conn.assigns.image
|
||||||
|
|
||||||
|
source_changes =
|
||||||
|
SourceChange
|
||||||
|
|> where(image_id: ^image.id)
|
||||||
|
|> preload([:user, image: [:user, :tags]])
|
||||||
|
|> order_by(desc: :created_at)
|
||||||
|
|> Repo.paginate(conn.assigns.scrivener)
|
||||||
|
|
||||||
|
render(conn, "index.html", image: image, source_changes: source_changes)
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,7 +7,7 @@ defmodule PhilomenaWeb.Image.SourceController do
|
||||||
plug PhilomenaWeb.FilterBannedUsersPlug
|
plug PhilomenaWeb.FilterBannedUsersPlug
|
||||||
plug PhilomenaWeb.CaptchaPlug
|
plug PhilomenaWeb.CaptchaPlug
|
||||||
plug PhilomenaWeb.UserAttributionPlug
|
plug PhilomenaWeb.UserAttributionPlug
|
||||||
plug PhilomenaWeb.CanaryMapPlug, update: :show
|
plug PhilomenaWeb.CanaryMapPlug, update: :edit_metadata
|
||||||
plug :load_and_authorize_resource, model: Image, id_name: "image_id"
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id"
|
||||||
|
|
||||||
def update(conn, %{"image" => image_params}) do
|
def update(conn, %{"image" => image_params}) do
|
||||||
|
@ -21,12 +21,12 @@ defmodule PhilomenaWeb.Image.SourceController do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(PhilomenaWeb.ImageView)
|
|> put_view(PhilomenaWeb.ImageView)
|
||||||
|> render("_source.html", image: image, changeset: changeset)
|
|> render("_source.html", layout: false, image: image, changeset: changeset)
|
||||||
|
|
||||||
{:error, :image, changeset, _} ->
|
{:error, :image, changeset, _} ->
|
||||||
conn
|
conn
|
||||||
|> put_view(PhilomenaWeb.ImageView)
|
|> put_view(PhilomenaWeb.ImageView)
|
||||||
|> render("_source.html", image: image, changeset: changeset)
|
|> render("_source.html", layout: false, image: image, changeset: changeset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
32
lib/philomena_web/controllers/image/tag_change_controller.ex
Normal file
32
lib/philomena_web/controllers/image/tag_change_controller.ex
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
defmodule PhilomenaWeb.Image.TagChangeController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias Philomena.Images.Image
|
||||||
|
alias Philomena.TagChanges.TagChange
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
plug PhilomenaWeb.CanaryMapPlug, index: :show
|
||||||
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
||||||
|
|
||||||
|
def index(conn, params) do
|
||||||
|
image = conn.assigns.image
|
||||||
|
|
||||||
|
tag_changes =
|
||||||
|
TagChange
|
||||||
|
|> where(image_id: ^image.id)
|
||||||
|
|> added_filter(params)
|
||||||
|
|> preload([:tag, :user, image: [:user, :tags]])
|
||||||
|
|> order_by(desc: :created_at)
|
||||||
|
|> Repo.paginate(conn.assigns.scrivener)
|
||||||
|
|
||||||
|
render(conn, "index.html", image: image, tag_changes: tag_changes)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp added_filter(query, %{"added" => "1"}),
|
||||||
|
do: where(query, added: true)
|
||||||
|
defp added_filter(query, %{"added" => "0"}),
|
||||||
|
do: where(query, added: false)
|
||||||
|
defp added_filter(query, _params),
|
||||||
|
do: query
|
||||||
|
end
|
|
@ -3,11 +3,13 @@ defmodule PhilomenaWeb.Image.TagController do
|
||||||
|
|
||||||
alias Philomena.Images
|
alias Philomena.Images
|
||||||
alias Philomena.Images.Image
|
alias Philomena.Images.Image
|
||||||
|
alias Philomena.Tags
|
||||||
|
alias Philomena.Repo
|
||||||
|
|
||||||
plug PhilomenaWeb.FilterBannedUsersPlug
|
plug PhilomenaWeb.FilterBannedUsersPlug
|
||||||
plug PhilomenaWeb.CaptchaPlug
|
plug PhilomenaWeb.CaptchaPlug
|
||||||
plug PhilomenaWeb.UserAttributionPlug
|
plug PhilomenaWeb.UserAttributionPlug
|
||||||
plug PhilomenaWeb.CanaryMapPlug, update: :show
|
plug PhilomenaWeb.CanaryMapPlug, update: :edit_metadata
|
||||||
plug :load_and_authorize_resource, model: Image, id_name: "image_id"
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id"
|
||||||
|
|
||||||
def update(conn, %{"image" => image_params}) do
|
def update(conn, %{"image" => image_params}) do
|
||||||
|
@ -15,18 +17,25 @@ defmodule PhilomenaWeb.Image.TagController do
|
||||||
image = conn.assigns.image
|
image = conn.assigns.image
|
||||||
|
|
||||||
case Images.update_tags(image, attributes, image_params) do
|
case Images.update_tags(image, attributes, image_params) do
|
||||||
{:ok, %{image: image}} ->
|
{:ok, %{image: {image, added_tags, removed_tags}}} ->
|
||||||
|
Images.reindex_image(image)
|
||||||
|
Tags.reindex_tags(added_tags ++ removed_tags)
|
||||||
|
|
||||||
|
image =
|
||||||
|
image
|
||||||
|
|> Repo.preload(:tags, force: true)
|
||||||
|
|
||||||
changeset =
|
changeset =
|
||||||
Images.change_image(image)
|
Images.change_image(image)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(PhilomenaWeb.ImageView)
|
|> put_view(PhilomenaWeb.ImageView)
|
||||||
|> render("_tags.html", image: image, changeset: changeset)
|
|> render("_tags.html", layout: false, image: image, changeset: changeset)
|
||||||
|
|
||||||
{:error, :image, changeset, _} ->
|
{:error, :image, changeset, _} ->
|
||||||
conn
|
conn
|
||||||
|> put_view(PhilomenaWeb.ImageView)
|
|> put_view(PhilomenaWeb.ImageView)
|
||||||
|> render("_tags.html", image: image, changeset: changeset)
|
|> render("_tags.html", layout: false, image: image, changeset: changeset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -57,6 +57,10 @@ defmodule PhilomenaWeb.ImageController do
|
||||||
%Comment{}
|
%Comment{}
|
||||||
|> Comments.change_comment()
|
|> Comments.change_comment()
|
||||||
|
|
||||||
|
image_changeset =
|
||||||
|
image
|
||||||
|
|> Images.change_image()
|
||||||
|
|
||||||
watching =
|
watching =
|
||||||
Images.subscribed?(image, conn.assigns.current_user)
|
Images.subscribed?(image, conn.assigns.current_user)
|
||||||
|
|
||||||
|
@ -65,6 +69,7 @@ defmodule PhilomenaWeb.ImageController do
|
||||||
"show.html",
|
"show.html",
|
||||||
image: image,
|
image: image,
|
||||||
comments: comments,
|
comments: comments,
|
||||||
|
image_changeset: image_changeset,
|
||||||
comment_changeset: comment_changeset,
|
comment_changeset: comment_changeset,
|
||||||
description: description,
|
description: description,
|
||||||
interactions: interactions,
|
interactions: interactions,
|
||||||
|
|
|
@ -85,6 +85,10 @@ defmodule PhilomenaWeb.Router do
|
||||||
resources "/activity", ActivityController, only: [:index]
|
resources "/activity", ActivityController, only: [:index]
|
||||||
resources "/images", ImageController, only: [:index, :show] do
|
resources "/images", ImageController, only: [:index, :show] do
|
||||||
resources "/comments", Image.CommentController, only: [:index, :show, :create]
|
resources "/comments", Image.CommentController, only: [:index, :show, :create]
|
||||||
|
resources "/tags", Image.TagController, only: [:update], singleton: true
|
||||||
|
resources "/sources", Image.SourceController, only: [:update], singleton: true
|
||||||
|
resources "/tag_changes", Image.TagChangeController, only: [:index]
|
||||||
|
resources "/source_changes", Image.SourceChangeController, only: [:index]
|
||||||
end
|
end
|
||||||
resources "/tags", TagController, only: [:index, :show]
|
resources "/tags", TagController, only: [:index, :show]
|
||||||
resources "/search", SearchController, only: [:index]
|
resources "/search", SearchController, only: [:index]
|
||||||
|
|
40
lib/philomena_web/templates/image/_source.html.slime
Normal file
40
lib/philomena_web/templates/image/_source.html.slime
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
.block
|
||||||
|
= form_for @changeset, Routes.image_source_path(@conn, :update, @image), [method: "put", class: "hidden", id: "source-form", data: [remote: true]], fn f ->
|
||||||
|
= if can?(@conn, :update_metadata, @image) and !@conn.assigns.current_ban do
|
||||||
|
|
||||||
|
= if @changeset.action do
|
||||||
|
.alert.alert-danger
|
||||||
|
p Oops, something went wrong! Please check the errors below.
|
||||||
|
|
||||||
|
.flex
|
||||||
|
= url_input f, :source_url, id: "source-field", class: "input input--wide", autocomplete: "off", placeholder: "Source URL"
|
||||||
|
= submit "Save source", class: "button button--separate-left"
|
||||||
|
button.button.button--separate-left type="reset" data-click-hide="#source-form" data-click-show="#image-source"
|
||||||
|
' Cancel
|
||||||
|
|
||||||
|
= if !@conn.assigns.current_user do
|
||||||
|
= checkbox f, :captcha, class: "js-captcha", value: 0
|
||||||
|
= label f, :captcha, "I am not a robot!"
|
||||||
|
|
||||||
|
- else
|
||||||
|
p
|
||||||
|
' You can't edit the source on this image.
|
||||||
|
|
||||||
|
.flex.flex--wrap#image-source
|
||||||
|
p
|
||||||
|
a.button.button--separate-right#edit-source data-click-focus="#source-field" data-click-hide="#image-source" data-click-show="#source-form" title="Edit source" accessKey="s"
|
||||||
|
i.fa.fa-pencil>
|
||||||
|
' Source:
|
||||||
|
|
||||||
|
p
|
||||||
|
= if @image.source_url not in [nil, ""] do
|
||||||
|
a.js-source-link href=@image.source_url
|
||||||
|
strong
|
||||||
|
= @image.source_url
|
||||||
|
|
||||||
|
- else
|
||||||
|
em> not provided yet
|
||||||
|
|
||||||
|
a.button.button--link.button--separate-left href=Routes.image_source_change_path(@conn, :index, @image) title="Source history"
|
||||||
|
i.fa.fa-history>
|
||||||
|
' History
|
60
lib/philomena_web/templates/image/_tags.html.slime
Normal file
60
lib/philomena_web/templates/image/_tags.html.slime
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
- form_class = if @changeset.action, do: "", else: "hidden"
|
||||||
|
|
||||||
|
.js-tagsauce#image_tags_and_source
|
||||||
|
= if can?(@conn, :update_metadata, @image) and !@conn.assigns.current_ban do
|
||||||
|
|
||||||
|
.js-imageform class=form_class
|
||||||
|
|
||||||
|
= form_for @changeset, Routes.image_tag_path(@conn, :update, @image), [id: "tags-form", method: "put", data: [remote: true]], fn f ->
|
||||||
|
= if @changeset.action do
|
||||||
|
.alert.alert-danger
|
||||||
|
p Oops, something went wrong! Please check the errors below.
|
||||||
|
|
||||||
|
= hidden_input f, :old_tag_input, value: @image.tag_list_cache
|
||||||
|
|
||||||
|
.field
|
||||||
|
= label f, :tag_input do
|
||||||
|
' Separate tags with commas. Use 'artist:name' tags to identify artists. Got questions? Check the
|
||||||
|
a> href="/pages/tags" tag guidelines
|
||||||
|
' or the
|
||||||
|
a href="/pages/spoilers" spoiler guidelines
|
||||||
|
' .
|
||||||
|
|
||||||
|
= render PhilomenaWeb.TagView, "_tag_editor.html", f: f, name: :tag_input, type: :edit, extra: [value: @image.tag_list_cache]
|
||||||
|
|
||||||
|
= if !@conn.assigns.current_user do
|
||||||
|
.block.block--fixed.block--warning
|
||||||
|
strong
|
||||||
|
em Hang on a sec…
|
||||||
|
br
|
||||||
|
' Make sure you have read and understood our
|
||||||
|
a> href="/pages/tags" tagging guidelines
|
||||||
|
' before editing tags.
|
||||||
|
|
||||||
|
.field
|
||||||
|
= checkbox f, :captcha, class: "js-captcha", value: 0
|
||||||
|
= label f, :captcha, "I am not a robot!"
|
||||||
|
|
||||||
|
ul.horizontal-list
|
||||||
|
li
|
||||||
|
.actions
|
||||||
|
= submit "Save tags", class: "button", id: "edit_save_button", data: [disable_with: raw("Saving…")]
|
||||||
|
li
|
||||||
|
button.button.js-tag-sauce-toggle data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input"
|
||||||
|
' Cancel
|
||||||
|
|
||||||
|
- else
|
||||||
|
p
|
||||||
|
' You can't edit the tags on this image.
|
||||||
|
|
||||||
|
.tagsauce
|
||||||
|
.block
|
||||||
|
a.button.js-tag-sauce-toggle#edit-tags data-click-toggle=".tagsauce, .js-imageform" data-click-focus=".js-taginput-plain:not(.hidden), .js-taginput-input" title="Edit tags" accessKey="t"
|
||||||
|
i.fa.fa-pencil>
|
||||||
|
' Tags:
|
||||||
|
|
||||||
|
a.button.button--link.button--separate-left href=Routes.image_tag_change_path(@conn, :index, @image) title="Tag history"
|
||||||
|
i.fa.fa-history>
|
||||||
|
' History
|
||||||
|
|
||||||
|
= render PhilomenaWeb.TagView, "_tag_list.html", tags: display_order(@image.tags), conn: @conn
|
|
@ -8,15 +8,9 @@
|
||||||
| Description:
|
| Description:
|
||||||
.image-description__text
|
.image-description__text
|
||||||
== @description
|
== @description
|
||||||
.js-tagsauce id="image_tags_and_source_#{@image.id}"
|
|
||||||
.tagsauce
|
= render PhilomenaWeb.ImageView, "_tags.html", image: @image, changeset: @image_changeset, conn: @conn
|
||||||
= render PhilomenaWeb.TagView, "_tag_list.html", tags: display_order(@image.tags), conn: @conn
|
= render PhilomenaWeb.ImageView, "_source.html", image: @image, changeset: @image_changeset, conn: @conn
|
||||||
.block
|
|
||||||
.flex.flex--wrap#image-source
|
|
||||||
= if !!@image.source_url and @image.source_url != "" do
|
|
||||||
a href=@image.source_url = @image.source_url
|
|
||||||
- else
|
|
||||||
em> no source provided yet
|
|
||||||
|
|
||||||
h4 Comments
|
h4 Comments
|
||||||
= cond do
|
= cond do
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
h1
|
||||||
|
' Source changes for
|
||||||
|
a href=Routes.image_path(@conn, :show, @image)
|
||||||
|
| image #
|
||||||
|
= @image.id
|
||||||
|
|
||||||
|
- route = fn p -> Routes.image_source_change_path(@conn, :index, @image, p) end
|
||||||
|
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @source_changes, route: route, conn: @conn
|
||||||
|
|
||||||
|
.block
|
||||||
|
.block__header
|
||||||
|
= pagination
|
||||||
|
|
||||||
|
.block__content
|
||||||
|
table.table
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th colspan=2 Image
|
||||||
|
th New Source
|
||||||
|
th Timestamp
|
||||||
|
th User
|
||||||
|
th Initial?
|
||||||
|
|
||||||
|
tbody
|
||||||
|
= for source_change <- @source_changes do
|
||||||
|
tr
|
||||||
|
td.center
|
||||||
|
= link source_change.image_id, to: Routes.image_path(@conn, :show, source_change.image)
|
||||||
|
td.center
|
||||||
|
= render PhilomenaWeb.ImageView, "_image_container.html", image: source_change.image, size: :thumb_tiny, conn: @conn
|
||||||
|
|
||||||
|
td
|
||||||
|
= source_change.new_value
|
||||||
|
|
||||||
|
td
|
||||||
|
= pretty_time(source_change.created_at)
|
||||||
|
|
||||||
|
td
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: source_change, conn: @conn
|
||||||
|
|
||||||
|
td
|
||||||
|
= if source_change.initial do
|
||||||
|
' ✓
|
||||||
|
|
||||||
|
.block__header
|
||||||
|
= pagination
|
|
@ -0,0 +1,58 @@
|
||||||
|
h1
|
||||||
|
' Tag changes for
|
||||||
|
a href=Routes.image_path(@conn, :show, @image)
|
||||||
|
| image #
|
||||||
|
= @image.id
|
||||||
|
|
||||||
|
- route = fn p -> Routes.image_tag_change_path(@conn, :index, @image, p) end
|
||||||
|
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @tag_changes, route: route, conn: @conn
|
||||||
|
|
||||||
|
.block
|
||||||
|
.block__header
|
||||||
|
span.block__header_title
|
||||||
|
| Display only:
|
||||||
|
|
||||||
|
= link "Removed", to: Routes.image_tag_change_path(@conn, :index, @image, added: 0)
|
||||||
|
= link "Added", to: Routes.image_tag_change_path(@conn, :index, @image, added: 1)
|
||||||
|
= link "All", to: Routes.image_tag_change_path(@conn, :index, @image)
|
||||||
|
|
||||||
|
.block__header
|
||||||
|
= pagination
|
||||||
|
|
||||||
|
.block__content
|
||||||
|
table.table
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th colspan=2 Image
|
||||||
|
th Tag
|
||||||
|
th Action
|
||||||
|
th Timestamp
|
||||||
|
th User
|
||||||
|
|
||||||
|
tbody
|
||||||
|
= for tag_change <- @tag_changes do
|
||||||
|
tr
|
||||||
|
td.center
|
||||||
|
= link tag_change.image_id, to: Routes.image_path(@conn, :show, tag_change.image)
|
||||||
|
td.center
|
||||||
|
= render PhilomenaWeb.ImageView, "_image_container.html", image: tag_change.image, size: :thumb_tiny, conn: @conn
|
||||||
|
|
||||||
|
td
|
||||||
|
= if tag_change.tag do
|
||||||
|
= render PhilomenaWeb.TagView, "_tag.html", tag: tag_change.tag, conn: @conn
|
||||||
|
- else
|
||||||
|
= tag_change.tag_name_cache || "Unknown tag"
|
||||||
|
|
||||||
|
= if tag_change.added do
|
||||||
|
td.success Added
|
||||||
|
- else
|
||||||
|
td.danger Removed
|
||||||
|
|
||||||
|
td
|
||||||
|
= pretty_time(tag_change.created_at)
|
||||||
|
|
||||||
|
td
|
||||||
|
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: tag_change, conn: @conn
|
||||||
|
|
||||||
|
.block__header
|
||||||
|
= pagination
|
|
@ -1,5 +1,12 @@
|
||||||
|
elixir:
|
||||||
|
textarea_options = [
|
||||||
|
class: "input input--wide tagsinput js-image-input js-taginput js-taginput-plain js-taginput-#{@name}",
|
||||||
|
placeholder: "Add tags separated with commas"
|
||||||
|
]
|
||||||
|
html_options = Keyword.merge(textarea_options, assigns[:extra] || [])
|
||||||
|
|
||||||
.js-tag-block class="fancy-tag-#{@type}"
|
.js-tag-block class="fancy-tag-#{@type}"
|
||||||
= textarea @f, @name, class: "input input--wide tagsinput js-image-input js-taginput js-taginput-plain js-taginput-#{@name}", placeholder: "Add tags separated with commas"
|
= textarea @f, @name, html_options
|
||||||
.js-taginput.input.input--wide.tagsinput.hidden class="js-taginput-fancy" data-click-focus=".js-taginput-input.js-taginput-#{@name}"
|
.js-taginput.input.input--wide.tagsinput.hidden class="js-taginput-fancy" data-click-focus=".js-taginput-input.js-taginput-#{@name}"
|
||||||
input.input class="js-taginput-input js-taginput-#{@name}" id="taginput-fancy-#{@name}" type="text" placeholder="add a tag" autocapitalize="none" data-ac="true" data-ac-min-length="3" data-ac-source='/tags/autocomplete.json?term='
|
input.input class="js-taginput-input js-taginput-#{@name}" id="taginput-fancy-#{@name}" type="text" placeholder="add a tag" autocapitalize="none" data-ac="true" data-ac-min-length="3" data-ac-source='/tags/autocomplete.json?term='
|
||||||
button.button.button--state-primary.button--bold class="js-taginput-show" data-click-show=".js-taginput-fancy,.js-taginput-hide" data-click-hide=".js-taginput-plain,.js-taginput-show" data-click-focus=".js-taginput-input.js-taginput-#{@name}"
|
button.button.button--state-primary.button--bold class="js-taginput-show" data-click-show=".js-taginput-fancy,.js-taginput-hide" data-click-hide=".js-taginput-plain,.js-taginput-show" data-click-focus=".js-taginput-input.js-taginput-#{@name}"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= if !!@object.user and !@object.anonymous do
|
= if !!@object.user and !anonymous?(@object) do
|
||||||
strong<>
|
strong<>
|
||||||
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
= link(@object.user.name, to: Routes.profile_path(@conn, :show, @object.user))
|
||||||
= if assigns[:awards] do
|
= if assigns[:awards] do
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= if !!@object.user and !@object.anonymous do
|
= if !!@object.user and !anonymous?(@object) do
|
||||||
= user_avatar(@object, assigns[:class] || "avatar--100px")
|
= user_avatar(@object, assigns[:class] || "avatar--100px")
|
||||||
- else
|
- else
|
||||||
= anonymous_avatar(@object, assigns[:class] || "avatar--100px")
|
= anonymous_avatar(@object, assigns[:class] || "avatar--100px")
|
3
lib/philomena_web/views/image/source_change_view.ex
Normal file
3
lib/philomena_web/views/image/source_change_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
defmodule PhilomenaWeb.Image.SourceChangeView do
|
||||||
|
use PhilomenaWeb, :view
|
||||||
|
end
|
3
lib/philomena_web/views/image/tag_change_view.ex
Normal file
3
lib/philomena_web/views/image/tag_change_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
defmodule PhilomenaWeb.Image.TagChangeView do
|
||||||
|
use PhilomenaWeb, :view
|
||||||
|
end
|
|
@ -1,6 +1,8 @@
|
||||||
defmodule PhilomenaWeb.ImageView do
|
defmodule PhilomenaWeb.ImageView do
|
||||||
use PhilomenaWeb, :view
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
|
alias Philomena.Tags.Tag
|
||||||
|
|
||||||
def thumb_urls(image, show_hidden) do
|
def thumb_urls(image, show_hidden) do
|
||||||
%{
|
%{
|
||||||
thumb_tiny: thumb_url(image, show_hidden, :thumb_tiny),
|
thumb_tiny: thumb_url(image, show_hidden, :thumb_tiny),
|
||||||
|
@ -76,18 +78,7 @@ defmodule PhilomenaWeb.ImageView do
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_order(tags) do
|
def display_order(tags) do
|
||||||
tags
|
Tag.display_order(tags)
|
||||||
|> Enum.sort_by(&{
|
|
||||||
&1.category != "rating",
|
|
||||||
&1.category != "origin",
|
|
||||||
&1.category != "character",
|
|
||||||
&1.category != "oc",
|
|
||||||
&1.category != "species",
|
|
||||||
&1.category != "content-fanmade",
|
|
||||||
&1.category != "content-official",
|
|
||||||
&1.category != "spoiler",
|
|
||||||
&1.name
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp thumb_format("svg"), do: "png"
|
defp thumb_format("svg"), do: "png"
|
||||||
|
|
|
@ -3,6 +3,10 @@ defmodule PhilomenaWeb.UserAttributionView do
|
||||||
use Bitwise
|
use Bitwise
|
||||||
use PhilomenaWeb, :view
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
|
def anonymous?(object) do
|
||||||
|
Attribution.anonymous?(object)
|
||||||
|
end
|
||||||
|
|
||||||
def anonymous_name(object) do
|
def anonymous_name(object) do
|
||||||
salt = anonymous_name_salt()
|
salt = anonymous_name_salt()
|
||||||
id = Attribution.object_identifier(object)
|
id = Attribution.object_identifier(object)
|
||||||
|
|
Loading…
Reference in a new issue