mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
galleries index
This commit is contained in:
parent
de48c06f99
commit
1ad4f8f076
12 changed files with 186 additions and 10 deletions
2
.iex.exs
2
.iex.exs
|
@ -1,3 +1,3 @@
|
|||
alias Philomena.{Repo, Comments.Comment, Posts.Post, Images.Image, Tags.Tag, Users.User}
|
||||
alias Philomena.{Repo, Comments.Comment, Galleries.Gallery, Posts.Post, Images.Image, Topics.Topic, Tags.Tag, Users.User}
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
|
46
lib/philomena/galleries/elasticsearch.ex
Normal file
46
lib/philomena/galleries/elasticsearch.ex
Normal file
|
@ -0,0 +1,46 @@
|
|||
defmodule Philomena.Galleries.Elasticsearch do
|
||||
def mapping do
|
||||
%{
|
||||
settings: %{
|
||||
index: %{
|
||||
number_of_shards: 5,
|
||||
max_result_window: 10_000_000
|
||||
}
|
||||
},
|
||||
mappings: %{
|
||||
gallery: %{
|
||||
_all: %{enabled: false},
|
||||
dynamic: false,
|
||||
properties: %{
|
||||
id: %{type: "integer"}, # keyword
|
||||
image_count: %{type: "integer"},
|
||||
watcher_count: %{type: "integer"},
|
||||
updated_at: %{type: "date"},
|
||||
created_at: %{type: "date"},
|
||||
title: %{type: "keyword"},
|
||||
creator: %{type: "keyword"}, # missing creator_id
|
||||
image_ids: %{type: "keyword"},
|
||||
watcher_ids: %{type: "keyword"}, # ???
|
||||
description: %{type: "text", analyzer: "snowball"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
# [:subscribers, :creator, :interactions]
|
||||
def as_json(gallery) do
|
||||
%{
|
||||
id: gallery.id,
|
||||
image_count: gallery.image_count,
|
||||
watcher_count: length(gallery.subscribers),
|
||||
watcher_ids: Enum.map(gallery.subscribers, & &1.id),
|
||||
updated_at: gallery.updated_at,
|
||||
created_at: gallery.created_at,
|
||||
title: String.downcase(gallery.title),
|
||||
creator: String.downcase(gallery.creator.name),
|
||||
image_ids: Enum.map(gallery.interactions, & &1.image_id),
|
||||
description: gallery.description
|
||||
}
|
||||
end
|
||||
end
|
|
@ -2,6 +2,11 @@ defmodule Philomena.Galleries.Gallery do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
use Philomena.Elasticsearch,
|
||||
definition: Philomena.Galleries.Elasticsearch,
|
||||
index_name: "galleries",
|
||||
doc_type: "gallery"
|
||||
|
||||
alias Philomena.Images.Image
|
||||
alias Philomena.Users.User
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ defmodule Philomena.Images do
|
|||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_subscription(image, nil), do: {:ok, nil}
|
||||
def create_subscription(_image, nil), do: {:ok, nil}
|
||||
def create_subscription(image, user) do
|
||||
%Subscription{image_id: image.id, user_id: user.id}
|
||||
|> Subscription.changeset(%{})
|
||||
|
|
|
@ -123,7 +123,7 @@ defmodule Philomena.Topics do
|
|||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_subscription(topic, nil), do: {:ok, nil}
|
||||
def create_subscription(_topic, nil), do: {:ok, nil}
|
||||
def create_subscription(topic, user) do
|
||||
%Subscription{topic_id: topic.id, user_id: user.id}
|
||||
|> Subscription.changeset(%{})
|
||||
|
|
|
@ -38,7 +38,7 @@ defmodule PhilomenaWeb.CommentController do
|
|||
end
|
||||
defp parse_search(_conn, _params), do: [%{match_all: %{}}]
|
||||
|
||||
defp parse_author(%{"author" => author}) when author not in [nil, ""] do
|
||||
defp parse_author(%{"author" => author}) when is_binary(author) and author not in [nil, ""] do
|
||||
case String.contains?(author, ["*", "?"]) do
|
||||
true ->
|
||||
[
|
||||
|
@ -55,7 +55,7 @@ defmodule PhilomenaWeb.CommentController do
|
|||
end
|
||||
defp parse_author(_params), do: []
|
||||
|
||||
defp parse_image_id(conn, %{"image_id" => image_id}) when image_id not in [nil, ""] do
|
||||
defp parse_image_id(conn, %{"image_id" => image_id}) when is_binary(image_id) and image_id not in [nil, ""] do
|
||||
with {image_id, _rest} <- Integer.parse(image_id),
|
||||
true <- valid_image?(conn.assigns.current_user, image_id)
|
||||
do
|
||||
|
@ -67,7 +67,7 @@ defmodule PhilomenaWeb.CommentController do
|
|||
end
|
||||
defp parse_image_id(_conn, _params), do: []
|
||||
|
||||
defp parse_body(%{"body" => body}) when body not in [nil, ""],
|
||||
defp parse_body(%{"body" => body}) when is_binary(body) and body not in [nil, ""],
|
||||
do: [%{match: %{body: body}}]
|
||||
defp parse_body(_params), do: []
|
||||
|
||||
|
|
69
lib/philomena_web/controllers/gallery_controller.ex
Normal file
69
lib/philomena_web/controllers/gallery_controller.ex
Normal file
|
@ -0,0 +1,69 @@
|
|||
defmodule PhilomenaWeb.GalleryController do
|
||||
use PhilomenaWeb, :controller
|
||||
|
||||
alias Philomena.Galleries.Gallery
|
||||
import Ecto.Query
|
||||
|
||||
plug :load_resource, model: Gallery, preload: [:thumbnail, :creator]
|
||||
|
||||
def index(conn, params) do
|
||||
galleries =
|
||||
Gallery.search_records(
|
||||
%{
|
||||
query: %{
|
||||
bool: %{
|
||||
must: parse_search(params)
|
||||
}
|
||||
},
|
||||
sort: parse_sort(params),
|
||||
},
|
||||
conn.assigns.pagination,
|
||||
Gallery |> preload([:thumbnail, :creator])
|
||||
)
|
||||
|
||||
render(conn, "index.html", galleries: galleries, layout_class: "layout--wide")
|
||||
end
|
||||
|
||||
def show(_conn, _params) do
|
||||
end
|
||||
|
||||
defp parse_search(%{"gallery" => gallery_params}) do
|
||||
parse_title(gallery_params) ++
|
||||
parse_creator(gallery_params) ++
|
||||
parse_included_image(gallery_params) ++
|
||||
parse_description(gallery_params)
|
||||
end
|
||||
defp parse_search(_params), do: [%{match_all: %{}}]
|
||||
|
||||
defp parse_title(%{"title" => title}) when is_binary(title) and title not in [nil, ""],
|
||||
do: [%{wildcard: %{title: "*" <> String.downcase(title) <> "*"}}]
|
||||
defp parse_title(_params), do: []
|
||||
|
||||
defp parse_creator(%{"creator" => creator}) when is_binary(creator) and creator not in [nil, ""],
|
||||
do: [%{term: %{creator: String.downcase(creator)}}]
|
||||
defp parse_creator(_params), do: []
|
||||
|
||||
defp parse_included_image(%{"include_image" => image_id}) when is_binary(image_id) and image_id not in [nil, ""] do
|
||||
with {image_id, _rest} <- Integer.parse(image_id) do
|
||||
[%{term: %{image_id: image_id}}]
|
||||
else
|
||||
_ ->
|
||||
[]
|
||||
end
|
||||
end
|
||||
defp parse_included_image(_params), do: []
|
||||
|
||||
defp parse_description(%{"description" => description}) when is_binary(description) and description not in [nil, ""],
|
||||
do: [%{match: %{description: %{query: description, operator: :and}}}]
|
||||
defp parse_description(_params), do: []
|
||||
|
||||
defp parse_sort(%{"gallery" => %{"sf" => sf, "sd" => sd}})
|
||||
when sf in ["created_at", "updated_at", "image_count", "_score"]
|
||||
and sd in ["desc", "asc"]
|
||||
do
|
||||
%{sf => sd}
|
||||
end
|
||||
defp parse_sort(_params) do
|
||||
%{created_at: :desc}
|
||||
end
|
||||
end
|
|
@ -49,7 +49,7 @@ defmodule PhilomenaWeb.PostController do
|
|||
end
|
||||
defp parse_search(_conn, _params), do: [%{match_all: %{}}]
|
||||
|
||||
defp parse_author(%{"author" => author}) when author not in [nil, ""] do
|
||||
defp parse_author(%{"author" => author}) when is_binary(author) and author not in [nil, ""] do
|
||||
case String.contains?(author, ["*", "?"]) do
|
||||
true ->
|
||||
[
|
||||
|
@ -66,12 +66,12 @@ defmodule PhilomenaWeb.PostController do
|
|||
end
|
||||
defp parse_author(_params), do: []
|
||||
|
||||
defp parse_subject(%{"subject" => subject}) when subject not in [nil, ""] do
|
||||
defp parse_subject(%{"subject" => subject}) when is_binary(subject) and subject not in [nil, ""] do
|
||||
[%{match: %{subject: %{query: subject, operator: "and"}}}]
|
||||
end
|
||||
defp parse_subject(_params), do: []
|
||||
|
||||
defp parse_forum_id(conn, %{"forum_id" => forum_id}) when forum_id not in [nil, ""] do
|
||||
defp parse_forum_id(conn, %{"forum_id" => forum_id}) when is_binary(forum_id) and forum_id not in [nil, ""] do
|
||||
with {forum_id, _rest} <- Integer.parse(forum_id),
|
||||
true <- valid_forum?(conn.assigns.current_user, forum_id)
|
||||
do
|
||||
|
@ -83,7 +83,7 @@ defmodule PhilomenaWeb.PostController do
|
|||
end
|
||||
defp parse_forum_id(_conn, _params), do: []
|
||||
|
||||
defp parse_body(%{"body" => body}) when body not in [nil, ""],
|
||||
defp parse_body(%{"body" => body}) when is_binary(body) and body not in [nil, ""],
|
||||
do: [%{match: %{body: body}}]
|
||||
defp parse_body(_params), do: []
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ defmodule PhilomenaWeb.Router do
|
|||
resources "/captchas", CaptchaController, only: [:create]
|
||||
resources "/posts", PostController, only: [:index]
|
||||
resources "/commissions", CommissionController, only: [:index, :show]
|
||||
resources "/galleries", GalleryController, only: [:index, :show]
|
||||
|
||||
get "/:id", ImageController, :show
|
||||
end
|
||||
|
|
10
lib/philomena_web/templates/gallery/_gallery.html.slime
Normal file
10
lib/philomena_web/templates/gallery/_gallery.html.slime
Normal file
|
@ -0,0 +1,10 @@
|
|||
.media-box
|
||||
a.media-box__header.media-box__header--link href=Routes.gallery_path(@conn, :show, @gallery) title=@gallery.title
|
||||
= @gallery.title
|
||||
|
||||
.media-box__overlay
|
||||
= @gallery.spoiler_warning
|
||||
|
||||
.media-box__content.media-box__content--large
|
||||
a href=Routes.gallery_path(@conn, :show, @gallery)
|
||||
= render PhilomenaWeb.ImageView, "_image_container.html", image: @gallery.thumbnail, size: :thumb, conn: @conn
|
42
lib/philomena_web/templates/gallery/index.html.slime
Normal file
42
lib/philomena_web/templates/gallery/index.html.slime
Normal file
|
@ -0,0 +1,42 @@
|
|||
elixir:
|
||||
route = fn p -> Routes.gallery_path(@conn, :index, p) end
|
||||
pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @galleries, route: route
|
||||
|
||||
.column-layout
|
||||
.column-layout__left
|
||||
.block
|
||||
.block__content
|
||||
h3 Search Galleries
|
||||
|
||||
= form_for @conn, Routes.gallery_path(@conn, :index), [as: :gallery, method: "get", class: "hform"], fn f ->
|
||||
.field = label f, :title, "Title"
|
||||
.field = text_input f, :title, class: "input hform__text", placeholder: "Gallery title (* as wildcard)"
|
||||
|
||||
.field = label f, :description, "Description"
|
||||
.field = textarea f, :description, class: "input hform__text", placeholder: "Gallery description"
|
||||
|
||||
.field = label f, :creator, "Creator"
|
||||
.field = text_input f, :creator, class: "input hform__text", placeholder: "Gallery creator (exact match)"
|
||||
|
||||
.field = label f, :include_image, "Include image"
|
||||
.field = number_input f, :include_image, class: "input hform__text", placeholder: "Image ID (e.g. 100)"
|
||||
|
||||
.field = label f, :sf, "Sort by"
|
||||
.field
|
||||
=> select f, :sf, ["Creation Date": "created_at", "Update Date": "updated_at", "Image Count": "image_count", "Relevance": "_score"], class: "input"
|
||||
=> select f, :sd, ["Descending": "desc", "Ascending": "asc"], class: "input"
|
||||
|
||||
.field
|
||||
= submit "Search", class: "button button--state-primary"
|
||||
|
||||
.column-layout__main
|
||||
.block
|
||||
.block__header
|
||||
= pagination
|
||||
|
||||
.block__content.js-resizable-media-container
|
||||
= for gallery <- @galleries do
|
||||
= render PhilomenaWeb.GalleryView, "_gallery.html", gallery: gallery, conn: @conn
|
||||
|
||||
.block__header.block__header--light
|
||||
= pagination
|
3
lib/philomena_web/views/gallery_view.ex
Normal file
3
lib/philomena_web/views/gallery_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule PhilomenaWeb.GalleryView do
|
||||
use PhilomenaWeb, :view
|
||||
end
|
Loading…
Reference in a new issue