diff --git a/assets/js/interactions.js b/assets/js/interactions.js index fed1ea66..0607074c 100644 --- a/assets/js/interactions.js +++ b/assets/js/interactions.js @@ -5,9 +5,9 @@ import { fetchJson } from './utils/requests'; const endpoints = { - fave: `${window.booru.apiEndpoint}interactions/fave`, - vote: `${window.booru.apiEndpoint}interactions/vote`, - hide: `${window.booru.apiEndpoint}interactions/hide`, + vote(imageId) { return `/images/${imageId}/vote` }, + fave(imageId) { return `/images/${imageId}/fave` }, + hide(imageId) { return `/images/${imageId}/hide` }, }; const spoilerDownvoteMsg = @@ -22,10 +22,8 @@ function onImage(id, selector, cb) { function setScore(imageId, data) { onImage(imageId, '.score', el => el.textContent = data.score); - onImage(imageId, '.votes', - el => el.textContent = data.votes); onImage(imageId, '.favorites', - el => el.textContent = data.favourites); + el => el.textContent = data.faves); onImage(imageId, '.upvotes', el => el.textContent = data.upvotes); onImage(imageId, '.downvotes', @@ -73,10 +71,8 @@ function resetHidden(imageId) { el => el.classList.remove('active')); } -function interact(type, imageId, value) { - return fetchJson('PUT', endpoints[type], { - class: 'Image', id: imageId, value - }) +function interact(type, imageId, method, data = {}) { + return fetchJson(method, endpoints[type](imageId), data) .then(res => res.json()) .then(res => setScore(imageId, res)); } @@ -129,37 +125,37 @@ const targets = { /* Active-state targets first */ '.interaction--upvote.active'(imageId) { - interact('vote', imageId, 'false') + interact('vote', imageId, 'DELETE') .then(() => resetVoted(imageId)); }, '.interaction--downvote.active'(imageId) { - interact('vote', imageId, 'false') + interact('vote', imageId, 'DELETE') .then(() => resetVoted(imageId)); }, '.interaction--fave.active'(imageId) { - interact('fave', imageId, 'false') + interact('fave', imageId, 'DELETE') .then(() => resetFaved(imageId)); }, '.interaction--hide.active'(imageId) { - interact('hide', imageId, 'false') + interact('hide', imageId, 'DELETE') .then(() => resetHidden(imageId)); }, /* Inactive targets */ '.interaction--upvote:not(.active)'(imageId) { - interact('vote', imageId, 'up') + interact('vote', imageId, 'POST', { up: true }) .then(() => { resetVoted(imageId); showUpvoted(imageId); }); }, '.interaction--downvote:not(.active)'(imageId) { - interact('vote', imageId, 'down') + interact('vote', imageId, 'POST', { up: false }) .then(() => { resetVoted(imageId); showDownvoted(imageId); }); }, '.interaction--fave:not(.active)'(imageId) { - interact('fave', imageId, 'true') + interact('fave', imageId, 'POST') .then(() => { resetVoted(imageId); showFaved(imageId); showUpvoted(imageId); }); }, '.interaction--hide:not(.active)'(imageId) { - interact('hide', imageId, 'true') + interact('hide', imageId, 'POST') .then(() => { showHidden(imageId); }); }, diff --git a/lib/philomena/image_faves.ex b/lib/philomena/image_faves.ex index 7fac0a80..1869dc63 100644 --- a/lib/philomena/image_faves.ex +++ b/lib/philomena/image_faves.ex @@ -4,101 +4,51 @@ defmodule Philomena.ImageFaves do """ import Ecto.Query, warn: false - alias Philomena.Repo + alias Ecto.Multi + alias Philomena.Images.Image alias Philomena.ImageFaves.ImageFave @doc """ - Returns the list of image_faves. - - ## Examples - - iex> list_image_faves() - [%ImageFave{}, ...] + Creates a image_hide. """ - def list_image_faves do - Repo.all(ImageFave) - end + def create_fave_transaction(image, user) do + fave = + %ImageFave{image_id: image.id, user_id: user.id} + |> ImageFave.changeset(%{}) - @doc """ - Gets a single image_fave. + image_query = + Image + |> where(id: ^image.id) - Raises `Ecto.NoResultsError` if the Image fave does not exist. - - ## Examples - - iex> get_image_fave!(123) - %ImageFave{} - - iex> get_image_fave!(456) - ** (Ecto.NoResultsError) - - """ - def get_image_fave!(id), do: Repo.get!(ImageFave, id) - - @doc """ - Creates a image_fave. - - ## Examples - - iex> create_image_fave(%{field: value}) - {:ok, %ImageFave{}} - - iex> create_image_fave(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_image_fave(attrs \\ %{}) do - %ImageFave{} - |> ImageFave.changeset(attrs) - |> Repo.insert() - end - - @doc """ - Updates a image_fave. - - ## Examples - - iex> update_image_fave(image_fave, %{field: new_value}) - {:ok, %ImageFave{}} - - iex> update_image_fave(image_fave, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_image_fave(%ImageFave{} = image_fave, attrs) do - image_fave - |> ImageFave.changeset(attrs) - |> Repo.update() + Multi.new + |> Multi.insert(:fave, fave) + |> Multi.update_all(:inc_faves_count, image_query, inc: [faves_count: 1]) end @doc """ Deletes a ImageFave. - ## Examples - - iex> delete_image_fave(image_fave) - {:ok, %ImageFave{}} - - iex> delete_image_fave(image_fave) - {:error, %Ecto.Changeset{}} - """ - def delete_image_fave(%ImageFave{} = image_fave) do - Repo.delete(image_fave) - end + def delete_fave_transaction(image, user) do + fave_query = + ImageFave + |> where(image_id: ^image.id) + |> where(user_id: ^user.id) - @doc """ - Returns an `%Ecto.Changeset{}` for tracking image_fave changes. + image_query = + Image + |> where(id: ^image.id) - ## Examples + Multi.new + |> Multi.delete_all(:unfave, fave_query) + |> Multi.run(:dec_faves_count, fn repo, %{unfave: {faves, nil}} -> + {count, nil} = + image_query + |> repo.update_all(inc: [faves_count: -faves]) - iex> change_image_fave(image_fave) - %Ecto.Changeset{source: %ImageFave{}} - - """ - def change_image_fave(%ImageFave{} = image_fave) do - ImageFave.changeset(image_fave, %{}) + {:ok, count} + end) end end diff --git a/lib/philomena/image_hides.ex b/lib/philomena/image_hides.ex index 1e2fc3b6..1e0b9047 100644 --- a/lib/philomena/image_hides.ex +++ b/lib/philomena/image_hides.ex @@ -4,101 +4,51 @@ defmodule Philomena.ImageHides do """ import Ecto.Query, warn: false - alias Philomena.Repo + alias Ecto.Multi + alias Philomena.Images.Image alias Philomena.ImageHides.ImageHide - @doc """ - Returns the list of image_hides. - - ## Examples - - iex> list_image_hides() - [%ImageHide{}, ...] - - """ - def list_image_hides do - Repo.all(ImageHide) - end - - @doc """ - Gets a single image_hide. - - Raises `Ecto.NoResultsError` if the Image hide does not exist. - - ## Examples - - iex> get_image_hide!(123) - %ImageHide{} - - iex> get_image_hide!(456) - ** (Ecto.NoResultsError) - - """ - def get_image_hide!(id), do: Repo.get!(ImageHide, id) - @doc """ Creates a image_hide. - ## Examples - - iex> create_image_hide(%{field: value}) - {:ok, %ImageHide{}} - - iex> create_image_hide(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - """ - def create_image_hide(attrs \\ %{}) do - %ImageHide{} - |> ImageHide.changeset(attrs) - |> Repo.insert() - end + def create_hide_transaction(image, user) do + hide = + %ImageHide{image_id: image.id, user_id: user.id} + |> ImageHide.changeset(%{}) - @doc """ - Updates a image_hide. + image_query = + Image + |> where(id: ^image.id) - ## Examples - - iex> update_image_hide(image_hide, %{field: new_value}) - {:ok, %ImageHide{}} - - iex> update_image_hide(image_hide, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_image_hide(%ImageHide{} = image_hide, attrs) do - image_hide - |> ImageHide.changeset(attrs) - |> Repo.update() + Multi.new + |> Multi.insert(:hide, hide) + |> Multi.update_all(:inc_hides_count, image_query, inc: [hides_count: 1]) end @doc """ Deletes a ImageHide. - ## Examples - - iex> delete_image_hide(image_hide) - {:ok, %ImageHide{}} - - iex> delete_image_hide(image_hide) - {:error, %Ecto.Changeset{}} - """ - def delete_image_hide(%ImageHide{} = image_hide) do - Repo.delete(image_hide) - end + def delete_hide_transaction(image, user) do + hide_query = + ImageHide + |> where(image_id: ^image.id) + |> where(user_id: ^user.id) - @doc """ - Returns an `%Ecto.Changeset{}` for tracking image_hide changes. + image_query = + Image + |> where(id: ^image.id) - ## Examples + Multi.new + |> Multi.delete_all(:unhide, hide_query) + |> Multi.run(:dec_hides_count, fn repo, %{unhide: {hides, nil}} -> + {count, nil} = + image_query + |> repo.update_all(inc: [hides_count: -hides]) - iex> change_image_hide(image_hide) - %Ecto.Changeset{source: %ImageHide{}} - - """ - def change_image_hide(%ImageHide{} = image_hide) do - ImageHide.changeset(image_hide, %{}) + {:ok, count} + end) end end diff --git a/lib/philomena/image_votes.ex b/lib/philomena/image_votes.ex index 8dc6451c..95f38c4a 100644 --- a/lib/philomena/image_votes.ex +++ b/lib/philomena/image_votes.ex @@ -4,101 +4,62 @@ defmodule Philomena.ImageVotes do """ import Ecto.Query, warn: false - alias Philomena.Repo + alias Ecto.Multi + alias Philomena.Images.Image alias Philomena.ImageVotes.ImageVote - @doc """ - Returns the list of image_votes. - - ## Examples - - iex> list_image_votes() - [%ImageVote{}, ...] - - """ - def list_image_votes do - Repo.all(ImageVote) - end - - @doc """ - Gets a single image_vote. - - Raises `Ecto.NoResultsError` if the Image vote does not exist. - - ## Examples - - iex> get_image_vote!(123) - %ImageVote{} - - iex> get_image_vote!(456) - ** (Ecto.NoResultsError) - - """ - def get_image_vote!(id), do: Repo.get!(ImageVote, id) - @doc """ Creates a image_vote. - ## Examples - - iex> create_image_vote(%{field: value}) - {:ok, %ImageVote{}} - - iex> create_image_vote(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - """ - def create_image_vote(attrs \\ %{}) do - %ImageVote{} - |> ImageVote.changeset(attrs) - |> Repo.insert() - end + def create_vote_transaction(image, user, up) do + vote = + %ImageVote{image_id: image.id, user_id: user.id, up: up} + |> ImageVote.changeset(%{}) - @doc """ - Updates a image_vote. + image_query = + Image + |> where(id: ^image.id) - ## Examples + upvotes = if up, do: 1, else: 0 + downvotes = if up, do: 0, else: 1 - iex> update_image_vote(image_vote, %{field: new_value}) - {:ok, %ImageVote{}} - - iex> update_image_vote(image_vote, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_image_vote(%ImageVote{} = image_vote, attrs) do - image_vote - |> ImageVote.changeset(attrs) - |> Repo.update() + Multi.new + |> Multi.insert(:vote, vote) + |> Multi.update_all(:inc_vote_count, image_query, inc: [upvotes_count: upvotes, downvotes_count: downvotes, score: upvotes - downvotes]) end @doc """ Deletes a ImageVote. - ## Examples - - iex> delete_image_vote(image_vote) - {:ok, %ImageVote{}} - - iex> delete_image_vote(image_vote) - {:error, %Ecto.Changeset{}} - """ - def delete_image_vote(%ImageVote{} = image_vote) do - Repo.delete(image_vote) - end + def delete_vote_transaction(image, user) do + upvote_query = + ImageVote + |> where(image_id: ^image.id) + |> where(user_id: ^user.id) + |> where(up: true) - @doc """ - Returns an `%Ecto.Changeset{}` for tracking image_vote changes. + downvote_query = + ImageVote + |> where(image_id: ^image.id) + |> where(user_id: ^user.id) + |> where(up: false) - ## Examples + image_query = + Image + |> where(id: ^image.id) - iex> change_image_vote(image_vote) - %Ecto.Changeset{source: %ImageVote{}} + Multi.new + |> Multi.delete_all(:unupvote, upvote_query) + |> Multi.delete_all(:undownvote, downvote_query) + |> Multi.run(:dec_votes_count, fn repo, %{unupvote: {upvotes, nil}, undownvote: {downvotes, nil}} -> + {count, nil} = + image_query + |> repo.update_all(inc: [upvotes_count: -upvotes, downvotes_count: -downvotes, score: downvotes - upvotes]) - """ - def change_image_vote(%ImageVote{} = image_vote) do - ImageVote.changeset(image_vote, %{}) + {:ok, count} + end) end end diff --git a/lib/philomena/images.ex b/lib/philomena/images.ex index 85d48ce1..d7f2134e 100644 --- a/lib/philomena/images.ex +++ b/lib/philomena/images.ex @@ -104,6 +104,22 @@ defmodule Philomena.Images do Image.changeset(image, %{}) end + def reindex_image(%Image{} = image) do + spawn fn -> + Image + |> preload(^indexing_preloads()) + |> where(id: ^image.id) + |> Repo.one() + |> Image.index_document() + end + + image + end + + def indexing_preloads do + [:user, :favers, :downvoters, :upvoters, :hiders, :deleter, :gallery_interactions, tags: [:aliases, :aliased_tag]] + end + alias Philomena.Images.Subscription @doc """ diff --git a/lib/philomena/images/image.ex b/lib/philomena/images/image.ex index 64f0ad20..b6818834 100644 --- a/lib/philomena/images/image.ex +++ b/lib/philomena/images/image.ex @@ -83,4 +83,13 @@ defmodule Philomena.Images.Image do |> cast(attrs, []) |> validate_required([]) end + + def interaction_data(image) do + %{ + score: image.score, + faves: image.faves_count, + upvotes: image.upvotes_count, + downvotes: image.downvotes_count + } + end end diff --git a/lib/philomena/interactions.ex b/lib/philomena/interactions.ex new file mode 100644 index 00000000..98c50dc8 --- /dev/null +++ b/lib/philomena/interactions.ex @@ -0,0 +1,60 @@ +defmodule Philomena.Interactions do + import Ecto.Query + + alias Philomena.ImageHides.ImageHide + alias Philomena.ImageFaves.ImageFave + alias Philomena.ImageVotes.ImageVote + alias Philomena.Repo + + def user_interactions(_images, nil), + do: [] + + def user_interactions(images, user) do + ids = + images + |> Enum.flat_map(fn + nil -> [] + %{id: id} -> [id] + enum -> Enum.map(enum, & &1.id) + end) + |> Enum.uniq() + + hide_interactions = + ImageHide + |> select([h], %{image_id: h.image_id, user_id: h.user_id, interaction_type: ^"hidden", value: ^""}) + |> where([h], h.image_id in ^ids) + |> where(user_id: ^user.id) + + fave_interactions = + ImageFave + |> select([f], %{image_id: f.image_id, user_id: f.user_id, interaction_type: ^"faved", value: ^""}) + |> where([f], f.image_id in ^ids) + |> where(user_id: ^user.id) + + upvote_interactions = + ImageVote + |> select([v], %{image_id: v.image_id, user_id: v.user_id, interaction_type: ^"voted", value: ^"up"}) + |> where([v], v.image_id in ^ids) + |> where(user_id: ^user.id, up: true) + + downvote_interactions = + ImageVote + |> select([v], %{image_id: v.image_id, user_id: v.user_id, interaction_type: ^"voted", value: ^"down"}) + |> where([v], v.image_id in ^ids) + |> where(user_id: ^user.id, up: false) + + [ + hide_interactions, + fave_interactions, + upvote_interactions, + downvote_interactions + ] + |> union_all_queries() + |> Repo.all() + end + + defp union_all_queries([query]), + do: query + defp union_all_queries([query | rest]), + do: query |> union_all(^union_all_queries(rest)) +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/activity_controller.ex b/lib/philomena_web/controllers/activity_controller.ex index 06c19031..e2fd606f 100644 --- a/lib/philomena_web/controllers/activity_controller.ex +++ b/lib/philomena_web/controllers/activity_controller.ex @@ -1,7 +1,9 @@ defmodule PhilomenaWeb.ActivityController do use PhilomenaWeb, :controller - alias Philomena.{Images, Images.Image, Images.Feature, Comments.Comment, Channels.Channel, Topics.Topic, Forums.Forum} + alias Philomena.{Images.Image, ImageFeatures.ImageFeature, Comments.Comment, Channels.Channel, Topics.Topic, Forums.Forum} + alias Philomena.Interactions + alias Philomena.Images alias Philomena.Repo import Ecto.Query @@ -15,8 +17,11 @@ defmodule PhilomenaWeb.ActivityController do %{ query: %{ bool: %{ - must_not: filter, - must: image_query + must: image_query, + must_not: [ + filter, + %{term: %{hidden_from_users: true}} + ], } }, sort: %{created_at: :desc} @@ -30,8 +35,11 @@ defmodule PhilomenaWeb.ActivityController do %{ query: %{ bool: %{ - must_not: filter, - must: %{range: %{first_seen_at: %{gt: "now-3d"}}} + must: %{range: %{first_seen_at: %{gt: "now-3d"}}}, + must_not: [ + filter, + %{term: %{hidden_from_users: true}} + ] } }, sort: [%{score: :desc}, %{first_seen_at: :desc}] @@ -67,8 +75,11 @@ defmodule PhilomenaWeb.ActivityController do %{ query: %{ bool: %{ - must_not: filter, - must: watched_query + must: watched_query, + must_not: [ + filter, + %{term: %{hidden_from_users: true}} + ] } }, sort: %{created_at: :desc} @@ -80,7 +91,7 @@ defmodule PhilomenaWeb.ActivityController do featured_image = Image - |> join(:inner, [i], f in Feature, on: [image_id: i.id]) + |> join(:inner, [i], f in ImageFeature, on: [image_id: i.id]) |> order_by([i, f], desc: f.created_at) |> limit(1) |> preload([:tags]) @@ -105,6 +116,12 @@ defmodule PhilomenaWeb.ActivityController do |> limit(6) |> Repo.all() + interactions = + Interactions.user_interactions( + [images, top_scoring, watched, featured_image], + user + ) + render( conn, "index.html", @@ -114,7 +131,8 @@ defmodule PhilomenaWeb.ActivityController do watched: watched, featured_image: featured_image, streams: streams, - topics: topics + topics: topics, + interactions: interactions ) end end diff --git a/lib/philomena_web/controllers/image/fave_controller.ex b/lib/philomena_web/controllers/image/fave_controller.ex new file mode 100644 index 00000000..484aba29 --- /dev/null +++ b/lib/philomena_web/controllers/image/fave_controller.ex @@ -0,0 +1,60 @@ +defmodule PhilomenaWeb.Image.FaveController do + use PhilomenaWeb, :controller + + alias Philomena.{Images, Images.Image} + alias Philomena.{ImageFaves, ImageVotes} + alias Philomena.Repo + alias Ecto.Multi + + plug PhilomenaWeb.Plugs.FilterBannedUsers + plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true + + def create(conn, _params) do + user = conn.assigns.current_user + image = conn.assigns.image + + Multi.append( + ImageFaves.delete_fave_transaction(image, user), + ImageFaves.create_fave_transaction(image, user) + ) + |> Multi.append(ImageVotes.delete_vote_transaction(image, user)) + |> Multi.append(ImageVotes.create_vote_transaction(image, user, true)) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end + end + + def delete(conn, _params) do + user = conn.assigns.current_user + image = conn.assigns.image + + ImageFaves.delete_fave_transaction(image, user) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/image/hide_controller.ex b/lib/philomena_web/controllers/image/hide_controller.ex new file mode 100644 index 00000000..50870062 --- /dev/null +++ b/lib/philomena_web/controllers/image/hide_controller.ex @@ -0,0 +1,58 @@ +defmodule PhilomenaWeb.Image.HideController do + use PhilomenaWeb, :controller + + alias Philomena.{Images, Images.Image} + alias Philomena.ImageHides + alias Philomena.Repo + alias Ecto.Multi + + plug PhilomenaWeb.Plugs.FilterBannedUsers + plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true + + def create(conn, _params) do + user = conn.assigns.current_user + image = conn.assigns.image + + Multi.append( + ImageHides.delete_hide_transaction(image, user), + ImageHides.create_hide_transaction(image, user) + ) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end + end + + def delete(conn, _params) do + user = conn.assigns.current_user + image = conn.assigns.image + + ImageHides.delete_hide_transaction(image, user) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/image/vote_controller.ex b/lib/philomena_web/controllers/image/vote_controller.ex index f91ee1eb..7c1d0034 100644 --- a/lib/philomena_web/controllers/image/vote_controller.ex +++ b/lib/philomena_web/controllers/image/vote_controller.ex @@ -1,18 +1,58 @@ defmodule PhilomenaWeb.Image.VoteController do use PhilomenaWeb, :controller - alias Philomena.Images.Image - # alias Philomena.Repo - # alias Ecto.Multi + alias Philomena.{Images, Images.Image} + alias Philomena.ImageVotes + alias Philomena.Repo + alias Ecto.Multi plug PhilomenaWeb.Plugs.FilterBannedUsers plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true - def create(conn, _params) do - conn + def create(conn, params) do + user = conn.assigns.current_user + image = conn.assigns.image + + Multi.append( + ImageVotes.delete_vote_transaction(image, user), + ImageVotes.create_vote_transaction(image, user, params["up"] == true) + ) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end end def delete(conn, _params) do - conn + user = conn.assigns.current_user + image = conn.assigns.image + + ImageVotes.delete_vote_transaction(image, user) + |> Repo.transaction() + |> case do + {:ok, _result} -> + image = + Images.get_image!(image.id) + |> Images.reindex_image() + + conn + |> json(Image.interaction_data(image)) + + _error -> + conn + |> Plug.Conn.put_status(409) + |> json(%{}) + end end end \ No newline at end of file diff --git a/lib/philomena_web/controllers/image_controller.ex b/lib/philomena_web/controllers/image_controller.ex index c63fd859..723fd8bf 100644 --- a/lib/philomena_web/controllers/image_controller.ex +++ b/lib/philomena_web/controllers/image_controller.ex @@ -2,6 +2,7 @@ defmodule PhilomenaWeb.ImageController do use PhilomenaWeb, :controller alias Philomena.{Images.Image, Comments.Comment, Textile.Renderer} + alias Philomena.Interactions alias Philomena.Repo import Ecto.Query @@ -20,13 +21,18 @@ defmodule PhilomenaWeb.ImageController do Image |> preload([:tags, :user]) ) - render(conn, "index.html", images: images) + interactions = + Interactions.user_interactions(images, conn.assigns.current_user) + + render(conn, "index.html", images: images, interactions: interactions) end def show(conn, %{"id" => _id}) do + image = conn.assigns.image + comments = Comment - |> where(image_id: ^conn.assigns.image.id) + |> where(image_id: ^image.id) |> preload([:image, user: [awards: :badge]]) |> order_by(desc: :created_at) |> limit(25) @@ -40,9 +46,12 @@ defmodule PhilomenaWeb.ImageController do %{comments | entries: Enum.zip(comments.entries, rendered)} description = - %{body: conn.assigns.image.description} + %{body: image.description} |> Renderer.render_one() - render(conn, "show.html", image: conn.assigns.image, comments: comments, description: description) + interactions = + Interactions.user_interactions([image], conn.assigns.current_user) + + render(conn, "show.html", image: image, comments: comments, description: description, interactions: interactions) end end diff --git a/lib/philomena_web/controllers/search_controller.ex b/lib/philomena_web/controllers/search_controller.ex index 0c07fb7e..6fdfcb31 100644 --- a/lib/philomena_web/controllers/search_controller.ex +++ b/lib/philomena_web/controllers/search_controller.ex @@ -2,13 +2,14 @@ defmodule PhilomenaWeb.SearchController do use PhilomenaWeb, :controller alias Philomena.Images.{Image, Query} + alias Philomena.Interactions alias Pow.Plug import Ecto.Query def index(conn, params) do - filter = conn.assigns[:compiled_filter] - user = conn |> Plug.current_user() + filter = conn.assigns.compiled_filter + user = conn.assigns.current_user with {:ok, query} <- Query.compile(user, params["q"]) do images = @@ -21,8 +22,11 @@ defmodule PhilomenaWeb.SearchController do Image |> preload(:tags) ) + interactions = + Interactions.user_interactions(images, user) + conn - |> render("index.html", images: images, search_query: params["q"]) + |> render("index.html", images: images, search_query: params["q"], interactions: interactions) else {:error, msg} -> conn diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index 72442d2f..8cd4baa8 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -54,6 +54,11 @@ defmodule PhilomenaWeb.Router do resources "/notifications", NotificationController, only: [:index, :delete] resources "/conversations", ConversationController, only: [:index, :show] + resources "/images", ImageController, only: [] do + resources "/vote", Image.VoteController, only: [:create, :delete], singleton: true + resources "/fave", Image.FaveController, only: [:create, :delete], singleton: true + resources "/hide", Image.HideController, only: [:create, :delete], singleton: true + end end scope "/", PhilomenaWeb do