mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
add image navigation
This commit is contained in:
parent
e91154e3c3
commit
d94a09c2d9
14 changed files with 396 additions and 81 deletions
171
lib/philomena/image_navigator.ex
Normal file
171
lib/philomena/image_navigator.ex
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
defmodule Philomena.ImageNavigator do
|
||||||
|
alias Philomena.ImageSorter
|
||||||
|
alias Philomena.Images.{Image, Elasticsearch}
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
# We get consecutive images by finding all images greater than or less than
|
||||||
|
# the current image, and grabbing the FIRST one
|
||||||
|
@range_comparison_for_order %{
|
||||||
|
asc: :gt,
|
||||||
|
desc: :lt
|
||||||
|
}
|
||||||
|
|
||||||
|
# If we didn't reverse for prev, it would be the LAST image, which would
|
||||||
|
# make Elasticsearch choke on deep pagination
|
||||||
|
@order_for_dir %{
|
||||||
|
next: %{"asc" => :asc, "desc" => :desc},
|
||||||
|
prev: %{"asc" => :desc, "desc" => :asc}
|
||||||
|
}
|
||||||
|
|
||||||
|
@range_map %{
|
||||||
|
gt: :gte,
|
||||||
|
lt: :lte
|
||||||
|
}
|
||||||
|
|
||||||
|
def find_consecutive(image, rel, params, compiled_query, compiled_filter) do
|
||||||
|
image_index =
|
||||||
|
Image
|
||||||
|
|> where(id: ^image.id)
|
||||||
|
|> preload(:gallery_interactions)
|
||||||
|
|> Repo.one()
|
||||||
|
|> Map.merge(empty_fields())
|
||||||
|
|> Elasticsearch.as_json()
|
||||||
|
|
||||||
|
sort_data = ImageSorter.parse_sort(params)
|
||||||
|
|
||||||
|
{sorts, filters} =
|
||||||
|
sort_data.sorts
|
||||||
|
|> Enum.map(&extract_filters(&1, image_index, rel))
|
||||||
|
|> Enum.unzip()
|
||||||
|
|
||||||
|
sorts = sortify(sorts, image_index)
|
||||||
|
filters = filterify(filters, image_index)
|
||||||
|
|
||||||
|
Image.search_records(
|
||||||
|
%{
|
||||||
|
query: %{
|
||||||
|
bool: %{
|
||||||
|
must: List.flatten([compiled_query, sort_data.queries, filters]),
|
||||||
|
must_not: [
|
||||||
|
compiled_filter,
|
||||||
|
%{term: %{hidden_from_users: true}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sort: List.flatten(sorts)
|
||||||
|
},
|
||||||
|
%{page_size: 1}
|
||||||
|
)
|
||||||
|
|> Enum.to_list()
|
||||||
|
|> case do
|
||||||
|
[] -> image
|
||||||
|
[next_image] -> next_image
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp extract_filters(%{"galleries.position" => term} = sort, image, rel) do
|
||||||
|
# Extract gallery ID and current position
|
||||||
|
gid = term["nested_filter"]["term"]["galleries.id"]
|
||||||
|
pos = Enum.find(image[:galleries], & &1.id == gid).position
|
||||||
|
|
||||||
|
# Sort in the other direction if we are going backwards
|
||||||
|
sd = term["order"]
|
||||||
|
order = @order_for_dir[rel][sd]
|
||||||
|
term = %{term | "order" => order}
|
||||||
|
sort = %{sort | "galleries.position" => term}
|
||||||
|
|
||||||
|
filter = gallery_range_filter(@range_comparison_for_order[order], pos)
|
||||||
|
|
||||||
|
{[sort], [filter]}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp extract_filters(sort, image, rel) do
|
||||||
|
[{sf, sd}] = Enum.to_list(sort)
|
||||||
|
order = @order_for_dir[rel][sd]
|
||||||
|
sort = %{sort | sf => order}
|
||||||
|
|
||||||
|
field = String.to_existing_atom(sf)
|
||||||
|
filter = range_filter(sf, @range_comparison_for_order[order], image[field])
|
||||||
|
|
||||||
|
cond do
|
||||||
|
sf in [:_random, :_score] ->
|
||||||
|
{[sort], []}
|
||||||
|
|
||||||
|
true ->
|
||||||
|
{[sort], [filter]}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sortify(sorts, _image) do
|
||||||
|
List.flatten(sorts)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp filterify(filters, image) do
|
||||||
|
filters = List.flatten(filters)
|
||||||
|
|
||||||
|
filters =
|
||||||
|
filters
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.map(fn
|
||||||
|
{filter, 0} -> filter.this
|
||||||
|
{filter, i} ->
|
||||||
|
filters_so_far =
|
||||||
|
filters
|
||||||
|
|> Enum.take(i)
|
||||||
|
|> Enum.map(& &1.for_next)
|
||||||
|
|
||||||
|
%{
|
||||||
|
bool: %{
|
||||||
|
must: [filter.this | filters_so_far]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
%{
|
||||||
|
bool: %{
|
||||||
|
should: filters,
|
||||||
|
must_not: %{term: %{id: image.id}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp range_filter(sf, dir, val) do
|
||||||
|
%{
|
||||||
|
this: %{range: %{sf => %{dir => parse_val(val)}}},
|
||||||
|
next: %{range: %{sf => %{@range_map[dir] => parse_val(val)}}}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp gallery_range_filter(dir, val) do
|
||||||
|
%{
|
||||||
|
this: %{
|
||||||
|
nested: %{
|
||||||
|
path: :galleries,
|
||||||
|
query: %{range: %{"galleries.position" => %{dir => val}}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
next: %{
|
||||||
|
nested: %{
|
||||||
|
path: :galleries,
|
||||||
|
query: %{range: %{"galleries.position" => %{@range_map[dir] => val}}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp empty_fields do
|
||||||
|
%{
|
||||||
|
user: nil,
|
||||||
|
deleter: nil,
|
||||||
|
upvoters: [],
|
||||||
|
downvoters: [],
|
||||||
|
favers: [],
|
||||||
|
hiders: [],
|
||||||
|
tags: []
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_val(%NaiveDateTime{} = value), do: NaiveDateTime.to_iso8601(value)
|
||||||
|
defp parse_val(value), do: value
|
||||||
|
end
|
16
lib/philomena/image_scope.ex
Normal file
16
lib/philomena/image_scope.ex
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
defmodule Philomena.ImageScope do
|
||||||
|
def scope(conn) do
|
||||||
|
[]
|
||||||
|
|> scope(conn, "q")
|
||||||
|
|> scope(conn, "sf")
|
||||||
|
|> scope(conn, "sd")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp scope(list, conn, key) do
|
||||||
|
case conn.params[key] do
|
||||||
|
nil -> list
|
||||||
|
"" -> list
|
||||||
|
val -> [{key, val} | list]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
70
lib/philomena/image_sorter.ex
Normal file
70
lib/philomena/image_sorter.ex
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
defmodule Philomena.ImageSorter do
|
||||||
|
def parse_sort(params) do
|
||||||
|
sd = parse_sd(params)
|
||||||
|
|
||||||
|
parse_sf(params, sd)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_sd(%{"sd" => sd}) when sd in ~W(asc desc), do: sd
|
||||||
|
defp parse_sd(_params), do: "desc"
|
||||||
|
|
||||||
|
defp parse_sf(%{"sf" => sf}, sd) when
|
||||||
|
sf in ~W(created_at updated_at first_seen_at width height score comment_count tag_count wilson_score _score)
|
||||||
|
do
|
||||||
|
%{queries: [], sorts: [%{sf => sd}]}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_sf(%{"sf" => "random"}, sd) do
|
||||||
|
random_query(:rand.uniform(4_294_967_296), sd)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_sf(%{"sf" => <<"random:", seed::binary>>}, sd) do
|
||||||
|
case Integer.parse(seed) do
|
||||||
|
{seed, _rest} ->
|
||||||
|
random_query(seed, sd)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
random_query(:rand.uniform(4_294_967_296), sd)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_sf(%{"sf" => <<"gallery_id:", gallery::binary>>}, sd) do
|
||||||
|
case Integer.parse(gallery) do
|
||||||
|
{gallery, _rest} ->
|
||||||
|
%{
|
||||||
|
queries: [],
|
||||||
|
sorts: [%{
|
||||||
|
"galleries.position" => %{
|
||||||
|
order: sd,
|
||||||
|
nested_path: :galleries,
|
||||||
|
nested_filter: %{
|
||||||
|
term: %{
|
||||||
|
"galleries.id": gallery
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
%{queries: [%{match_none: %{}}], sorts: []}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp parse_sf(_params, sd) do
|
||||||
|
%{queries: [], sorts: [%{"created_at" => sd}]}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp random_query(seed, sd) do
|
||||||
|
%{
|
||||||
|
queries: [%{
|
||||||
|
function_score: %{
|
||||||
|
query: %{match_all: %{}},
|
||||||
|
random_score: %{seed: seed},
|
||||||
|
boost_mode: :replace
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
sorts: [%{"_score" => sd}]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
69
lib/philomena_web/controllers/image/navigate_controller.ex
Normal file
69
lib/philomena_web/controllers/image/navigate_controller.ex
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
defmodule PhilomenaWeb.Image.NavigateController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias Philomena.Images.Image
|
||||||
|
alias Philomena.Images.Query
|
||||||
|
alias Philomena.ImageNavigator
|
||||||
|
|
||||||
|
plug PhilomenaWeb.CanaryMapPlug, index: :show
|
||||||
|
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
|
||||||
|
|
||||||
|
def index(conn, %{"rel" => rel} = params) when rel in ~W(prev next) do
|
||||||
|
image = conn.assigns.image
|
||||||
|
filter = conn.assigns.compiled_filter
|
||||||
|
rel = String.to_existing_atom(rel)
|
||||||
|
|
||||||
|
next_image = ImageNavigator.find_consecutive(image, rel, params, compile_query(conn), filter)
|
||||||
|
scope = Philomena.ImageScope.scope(conn)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> redirect(to: Routes.image_path(conn, :show, next_image, scope))
|
||||||
|
end
|
||||||
|
|
||||||
|
def index(conn, %{"rel" => "find"}) do
|
||||||
|
image = conn.assigns.image
|
||||||
|
filter = conn.assigns.compiled_filter
|
||||||
|
pagination = conn.assigns.pagination
|
||||||
|
|
||||||
|
# Global find does not use the current search scope.
|
||||||
|
resp =
|
||||||
|
Image.search(
|
||||||
|
%{
|
||||||
|
query: %{
|
||||||
|
bool: %{
|
||||||
|
must: %{
|
||||||
|
range: %{id: %{gt: image.id}}
|
||||||
|
},
|
||||||
|
must_not: [
|
||||||
|
filter,
|
||||||
|
%{term: %{hidden_from_users: true}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sort: %{created_at: :desc},
|
||||||
|
size: 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
page_num = page_for_offset(pagination.page_size, resp["hits"]["total"])
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> redirect(to: Routes.image_path(conn, :index, page: page_num))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp page_for_offset(_per_page, 0), do: 1
|
||||||
|
defp page_for_offset(per_page, offset) do
|
||||||
|
((offset + 1) / per_page)
|
||||||
|
|> Float.ceil()
|
||||||
|
|> trunc()
|
||||||
|
|> to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp compile_query(conn) do
|
||||||
|
user = conn.assigns.current_user
|
||||||
|
|
||||||
|
{:ok, query} = Query.compile(user, conn.params["q"] || "")
|
||||||
|
|
||||||
|
query
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,6 +2,7 @@ defmodule PhilomenaWeb.SearchController do
|
||||||
use PhilomenaWeb, :controller
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
alias Philomena.Images.{Image, Query}
|
alias Philomena.Images.{Image, Query}
|
||||||
|
alias Philomena.ImageSorter
|
||||||
alias Philomena.Interactions
|
alias Philomena.Interactions
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
@ -9,16 +10,14 @@ defmodule PhilomenaWeb.SearchController do
|
||||||
def index(conn, params) do
|
def index(conn, params) do
|
||||||
filter = conn.assigns.compiled_filter
|
filter = conn.assigns.compiled_filter
|
||||||
user = conn.assigns.current_user
|
user = conn.assigns.current_user
|
||||||
|
sort = ImageSorter.parse_sort(params)
|
||||||
|
|
||||||
with {:ok, query} <- Query.compile(user, params["q"]) do
|
with {:ok, query} <- Query.compile(user, params["q"]) do
|
||||||
sd = parse_sd(params)
|
|
||||||
sf = parse_sf(params, sd)
|
|
||||||
|
|
||||||
images =
|
images =
|
||||||
Image.search_records(
|
Image.search_records(
|
||||||
%{
|
%{
|
||||||
query: %{bool: %{must: [query | sf.query], must_not: [filter, %{term: %{hidden_from_users: true}}]}},
|
query: %{bool: %{must: [query | sort.queries], must_not: [filter, %{term: %{hidden_from_users: true}}]}},
|
||||||
sort: sf.sort
|
sort: sort.sorts
|
||||||
},
|
},
|
||||||
conn.assigns.pagination,
|
conn.assigns.pagination,
|
||||||
Image |> preload(:tags)
|
Image |> preload(:tags)
|
||||||
|
@ -40,67 +39,4 @@ defmodule PhilomenaWeb.SearchController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp parse_sd(%{"sd" => sd}) when sd in ~W(asc desc),
|
|
||||||
do: sd
|
|
||||||
defp parse_sd(_params), do: :desc
|
|
||||||
|
|
||||||
defp parse_sf(%{"sf" => sf}, sd) when
|
|
||||||
sf in ~W(created_at updated_at first_seen_at width height score comment_count tag_count wilson_score _score)
|
|
||||||
do
|
|
||||||
%{query: [], sort: %{sf => sd}}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp parse_sf(%{"sf" => "random"}, sd) do
|
|
||||||
random_query(:rand.uniform(4_294_967_296), sd)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp parse_sf(%{"sf" => <<"random:", seed::binary>>}, sd) do
|
|
||||||
case Integer.parse(seed) do
|
|
||||||
{seed, _rest} ->
|
|
||||||
random_query(seed, sd)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
random_query(:rand.uniform(4_294_967_296), sd)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp parse_sf(%{"sf" => <<"gallery_id:", gallery::binary>>}, sd) do
|
|
||||||
case Integer.parse(gallery) do
|
|
||||||
{gallery, _rest} ->
|
|
||||||
%{
|
|
||||||
query: [],
|
|
||||||
sort: %{
|
|
||||||
"galleries.position": %{
|
|
||||||
order: sd,
|
|
||||||
nested_path: :galleries,
|
|
||||||
nested_filter: %{
|
|
||||||
term: %{
|
|
||||||
"galleries.id": gallery
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
%{query: [], sort: %{match_none: %{}}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp parse_sf(_params, sd) do
|
|
||||||
%{query: [], sort: %{created_at: sd}}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp random_query(seed, sd) do
|
|
||||||
%{
|
|
||||||
query: [%{
|
|
||||||
function_score: %{
|
|
||||||
query: %{match_all: %{}},
|
|
||||||
random_score: %{seed: seed},
|
|
||||||
boost_mode: :replace
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
sort: %{_score: sd}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,6 +66,50 @@ defmodule PhilomenaWeb.TagController do
|
||||||
dnp_entries =
|
dnp_entries =
|
||||||
Enum.zip(dnp_bodies, tag.dnp_entries)
|
Enum.zip(dnp_bodies, tag.dnp_entries)
|
||||||
|
|
||||||
render(conn, "show.html", tag: tag, body: body, dnp_entries: dnp_entries, interactions: interactions, images: images, layout_class: "layout--wide")
|
search_query = escape_name(tag)
|
||||||
|
|
||||||
|
render(
|
||||||
|
conn,
|
||||||
|
"show.html",
|
||||||
|
tag: tag,
|
||||||
|
body: body,
|
||||||
|
search_query: search_query,
|
||||||
|
dnp_entries: dnp_entries,
|
||||||
|
interactions: interactions,
|
||||||
|
images: images,
|
||||||
|
layout_class: "layout--wide"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def escape_name(%{name: name}) do
|
||||||
|
name =
|
||||||
|
name
|
||||||
|
|> String.replace(~r/\s+/, " ")
|
||||||
|
|> String.trim()
|
||||||
|
|> String.downcase()
|
||||||
|
|
||||||
|
cond do
|
||||||
|
String.contains?(name, "(") or String.contains?(name, ")") ->
|
||||||
|
# \ * ? " should be escaped, wrap in quotes so parser doesn't
|
||||||
|
# choke on parens.
|
||||||
|
name =
|
||||||
|
name
|
||||||
|
|> String.replace("\\", "\\\\")
|
||||||
|
|> String.replace("*", "\\*")
|
||||||
|
|> String.replace("?", "\\?")
|
||||||
|
|> String.replace("\"", "\\\"")
|
||||||
|
|
||||||
|
"\"#{name}\""
|
||||||
|
|
||||||
|
true ->
|
||||||
|
# \ * ? - ! " all must be escaped.
|
||||||
|
name
|
||||||
|
|> String.replace(~r/\A-/, "\\-")
|
||||||
|
|> String.replace(~r/\A!/, "\\!")
|
||||||
|
|> String.replace("\\", "\\\\")
|
||||||
|
|> String.replace("*", "\\*")
|
||||||
|
|> String.replace("?", "\\?")
|
||||||
|
|> String.replace("\"", "\\\"")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -99,6 +99,7 @@ defmodule PhilomenaWeb.Router do
|
||||||
resources "/tag_changes", Image.TagChangeController, only: [:index]
|
resources "/tag_changes", Image.TagChangeController, only: [:index]
|
||||||
resources "/source_changes", Image.SourceChangeController, only: [:index]
|
resources "/source_changes", Image.SourceChangeController, only: [:index]
|
||||||
resources "/description", Image.DescriptionController, only: [:update], singleton: true
|
resources "/description", Image.DescriptionController, only: [:update], singleton: true
|
||||||
|
resources "/navigate", Image.NavigateController, only: [:index]
|
||||||
end
|
end
|
||||||
scope "/tags", Tag, as: :tag do
|
scope "/tags", Tag, as: :tag do
|
||||||
resources "/autocomplete", AutocompleteController, only: [:show], singleton: true
|
resources "/autocomplete", AutocompleteController, only: [:show], singleton: true
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
elixir:
|
elixir:
|
||||||
|
link = assigns[:link] || Routes.image_path(@conn, :show, @image)
|
||||||
size_class =
|
size_class =
|
||||||
case @size do
|
case @size do
|
||||||
:thumb ->
|
:thumb ->
|
||||||
|
@ -34,4 +35,4 @@ elixir:
|
||||||
a.interaction--hide href="#" rel="nofollow" data-image-id=@image.id
|
a.interaction--hide href="#" rel="nofollow" data-image-id=@image.id
|
||||||
i.fa.fa-eye-slash title='Hide'
|
i.fa.fa-eye-slash title='Hide'
|
||||||
.media-box__content.flex.flex--centered.flex--center-distributed class=size_class
|
.media-box__content.flex.flex--centered.flex--center-distributed class=size_class
|
||||||
= render PhilomenaWeb.ImageView, "_image_container.html", image: @image, size: @size, conn: @conn
|
= render PhilomenaWeb.ImageView, "_image_container.html", link: link, image: @image, size: @size, conn: @conn
|
|
@ -1,11 +1,11 @@
|
||||||
.block.block__header
|
.block.block__header
|
||||||
.flex.flex--wrap.image-metabar.center--layout id="image_meta_#{@image.id}"
|
.flex.flex--wrap.image-metabar.center--layout id="image_meta_#{@image.id}"
|
||||||
.stretched-mobile-links
|
.stretched-mobile-links
|
||||||
a.js-prev href="/" title="Previous Image (j)"
|
a.js-prev href=Routes.image_navigate_path(@conn, :index, @image, [rel: "prev"] ++ scope(@conn)) title="Previous Image (j)"
|
||||||
i.fa.fa-chevron-left
|
i.fa.fa-chevron-left
|
||||||
a.js-up href="/" title="Find this image in the global image list (i)"
|
a.js-up href=Routes.image_navigate_path(@conn, :index, @image, [rel: "find"] ++ scope(@conn)) title="Find this image in the global image list (i)"
|
||||||
i.fa.fa-chevron-up
|
i.fa.fa-chevron-up
|
||||||
a.js-next href="/" title="Next Image (k)"
|
a.js-next href=Routes.image_navigate_path(@conn, :index, @image, [rel: "next"] ++ scope(@conn)) title="Next Image (k)"
|
||||||
i.fa.fa-chevron-right
|
i.fa.fa-chevron-right
|
||||||
a.js-rand href="/" title="Random (r)"
|
a.js-rand href="/" title="Random (r)"
|
||||||
i.fa.fa-random
|
i.fa.fa-random
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
- header = assigns[:header] || ""
|
elixir:
|
||||||
- route = assigns[:route] || fn p -> Routes.image_path(@conn, :index, p) end
|
header = assigns[:header] || ""
|
||||||
- params = assigns[:params] || []
|
params = assigns[:params] || assigns[:scope] || []
|
||||||
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @images, route: route, params: params
|
scope = assigns[:scope] || []
|
||||||
- info = render PhilomenaWeb.PaginationView, "_pagination_info.html", page: @images
|
route = assigns[:route] || fn p -> Routes.image_path(@conn, :index, p) end
|
||||||
|
image_url = fn image -> Routes.image_path(@conn, :show, image, scope) end
|
||||||
|
pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @images, route: route, params: params
|
||||||
|
info = render PhilomenaWeb.PaginationView, "_pagination_info.html", page: @images
|
||||||
|
|
||||||
.block#imagelist-container
|
.block#imagelist-container
|
||||||
section.block__header.flex
|
section.block__header.flex
|
||||||
|
@ -12,7 +15,7 @@
|
||||||
|
|
||||||
.block__content.js-resizable-media-container
|
.block__content.js-resizable-media-container
|
||||||
= for image <- @images do
|
= for image <- @images do
|
||||||
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, size: assigns[:size] || :thumb, conn: @conn
|
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, link: image_url.(image), size: assigns[:size] || :thumb, conn: @conn
|
||||||
|
|
||||||
.block__header.block__header--light.flex
|
.block__header.block__header--light.flex
|
||||||
= pagination
|
= pagination
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
= cond do
|
= cond do
|
||||||
- Enum.any?(@images) ->
|
- Enum.any?(@images) ->
|
||||||
= render PhilomenaWeb.ImageView, "index.html", conn: @conn, images: @images, route: fn p -> Routes.search_path(@conn, :index, p) end, params: [q: @search_query]
|
= render PhilomenaWeb.ImageView, "index.html", conn: @conn, images: @images, route: fn p -> Routes.search_path(@conn, :index, p) end, scope: [q: @conn.params["q"], sf: @conn.params["sf"], sd: @conn.params["sd"]]
|
||||||
- assigns[:error] ->
|
- assigns[:error] ->
|
||||||
p
|
p
|
||||||
' Oops, there was an error evaluating your query:
|
' Oops, there was an error evaluating your query:
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
= render PhilomenaWeb.TagView, "_tag_info_row.html", tag: @tag, body: @body, dnp_entries: @dnp_entries, conn: @conn
|
= render PhilomenaWeb.TagView, "_tag_info_row.html", tag: @tag, body: @body, dnp_entries: @dnp_entries, conn: @conn
|
||||||
= render PhilomenaWeb.ImageView, "index.html", conn: @conn, images: @images
|
= render PhilomenaWeb.ImageView, "index.html", conn: @conn, images: @images, scope: [q: @search_query]
|
|
@ -81,6 +81,8 @@ defmodule PhilomenaWeb.ImageView do
|
||||||
Tag.display_order(tags)
|
Tag.display_order(tags)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def scope(conn), do: Philomena.ImageScope.scope(conn)
|
||||||
|
|
||||||
defp thumb_format("svg"), do: "png"
|
defp thumb_format("svg"), do: "png"
|
||||||
defp thumb_format(format), do: format
|
defp thumb_format(format), do: format
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
defmodule PhilomenaWeb.SearchView do
|
defmodule PhilomenaWeb.SearchView do
|
||||||
use PhilomenaWeb, :view
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
|
def scope(conn), do: Philomena.ImageScope.scope(conn)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue