mirror of
https://gitea.invidious.io/iv-org/invidious-copy-2022-03-16.git
synced 2024-08-15 00:53:18 +00:00
Use Search::Filters and make filters an HTML form
This commit is contained in:
parent
ab43053844
commit
9b56e05c2a
6 changed files with 147 additions and 252 deletions
128
src/invidious/frontend/search_filters.cr
Normal file
128
src/invidious/frontend/search_filters.cr
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
module Invidious::Frontend::SearchFilters
|
||||||
|
extend self
|
||||||
|
|
||||||
|
# Generate the search filters collapsable widget.
|
||||||
|
def generate(filters : Search::Filters, query : String, page : Int, locale : String) : String
|
||||||
|
return String.build(8000) do |str|
|
||||||
|
str << "<div id='filters'>\n"
|
||||||
|
str << "\t<details id='filters-collapse'>"
|
||||||
|
str << "\t\t<summary><h3>" << translate(locale, "search_filters_title") << "</h3></summary>\n"
|
||||||
|
|
||||||
|
str << "\t\t<div id='filters-box' class=\"pure-g h-box\">\n"
|
||||||
|
str << "\t\t\t<form action='/search' method='get'>\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='hidden' name='q' value='" << HTML.escape(query) << "'>\n"
|
||||||
|
str << "\t\t\t\t<input type='hidden' name='page' value='" << page << "'>\n"
|
||||||
|
|
||||||
|
str << filter_wrapper(date)
|
||||||
|
str << filter_wrapper(type)
|
||||||
|
str << filter_wrapper(duration)
|
||||||
|
str << filter_wrapper(features)
|
||||||
|
str << filter_wrapper(sort)
|
||||||
|
|
||||||
|
str << "\t\t\t\t<div class=\"pure-controls\">"
|
||||||
|
str << "<button type='submit' class=\"pure-button pure-button-primary\">"
|
||||||
|
str << translate(locale, "Save preferences")
|
||||||
|
str << "</button></div>\n"
|
||||||
|
|
||||||
|
str << "\t\t\t</form>\n"
|
||||||
|
str << "\t\t</div>\n"
|
||||||
|
|
||||||
|
str << "\t</details>\n"
|
||||||
|
str << "</div>\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate wrapper HTML (`<div>`, filter name, etc...) around the
|
||||||
|
# `<input>` elements of a search filter
|
||||||
|
macro filter_wrapper(name)
|
||||||
|
str << "\t\t\t\t<div class=\"filter-column\">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<div class=\"filter-name\"><span>"
|
||||||
|
str << translate(locale, "search_filters_{{name}}_label")
|
||||||
|
str << "</span></div>\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<div class=\"filter-options\"><span>"
|
||||||
|
str << make_{{name}}_filter_options(str, filters.{{name}}, locale)
|
||||||
|
str << "</span></div>\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t</div>\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates the HTML for the list of radio buttons of the "date" search filter
|
||||||
|
def make_date_filter_options(str : String::Builder, value : Search::Filters::Date, locale : String)
|
||||||
|
{% for value in Invidious::Search::Filters::Date.constants %}
|
||||||
|
{% date = value.underscore %}
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='radio' name='date' id='filter-date-{{date}}' value='{{date}}'"
|
||||||
|
str << " checked" if value.{{date}}?
|
||||||
|
str << ">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<label for='filter-date-{{date}}'>"
|
||||||
|
str << translate(locale, "search_filters_date_option_{{date}}")
|
||||||
|
str << "</label><br>\n"
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates the HTML for the list of radio buttons of the "type" search filter
|
||||||
|
def make_type_filter_options(str : String::Builder, value : Search::Filters::Type, locale : String)
|
||||||
|
{% for value in Invidious::Search::Filters::Type.constants %}
|
||||||
|
{% type = value.underscore %}
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='radio' name='type' id='filter-type-{{type}}' value='{{type}}'"
|
||||||
|
str << " checked" if value.{{type}}?
|
||||||
|
str << ">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<label for='filter-type-{{type}}'>"
|
||||||
|
str << translate(locale, "search_filters_type_option_{{type}}")
|
||||||
|
str << "</label><br>\n"
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates the HTML for the list of radio buttons of the "duration" search filter
|
||||||
|
def make_duration_filter_options(str : String::Builder, value : Search::Filters::Duration, locale : String)
|
||||||
|
{% for value in Invidious::Search::Filters::Duration.constants %}
|
||||||
|
{% duration = value.underscore %}
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='radio' name='duration' id='filter-duration-{{duration}}' value='{{duration}}'"
|
||||||
|
str << " checked" if value.{{duration}}?
|
||||||
|
str << ">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<label for='filter-duration-{{duration}}'>"
|
||||||
|
str << translate(locale, "search_filters_type_option_{{duration}}")
|
||||||
|
str << "</label><br>\n"
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates the HTML for the list of checkboxes of the "features" search filter
|
||||||
|
def make_features_filter_options(str : String::Builder, value : Search::Filters::Features, locale : String)
|
||||||
|
{% for value in Invidious::Search::Filters::Features.constants %}
|
||||||
|
{% if value.stringify != "All" && value.stringify != "None" %}
|
||||||
|
{% feature = value.underscore %}
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='checkbox' name='features' id='filter-features-{{feature}}' value='{{feature}}'"
|
||||||
|
str << " checked" if value.{{feature}}?
|
||||||
|
str << ">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<label for='filter-feature-{{feature}}'>"
|
||||||
|
str << translate(locale, "search_filters_type_option_{{feature}}")
|
||||||
|
str << "</label><br>\n"
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates the HTML for the list of radio buttons of the "sort" search filter
|
||||||
|
def make_sort_filter_options(str : String::Builder, value : Search::Filters::Sort, locale : String)
|
||||||
|
{% for value in Invidious::Search::Filters::Sort.constants %}
|
||||||
|
{% sort = value.underscore %}
|
||||||
|
|
||||||
|
str << "\t\t\t\t<input type='radio' name='sort' id='filter-sort-{{sort}}' value='{{sort}}'"
|
||||||
|
str << " checked" if value.{{sort}}?
|
||||||
|
str << ">\n"
|
||||||
|
|
||||||
|
str << "\t\t\t\t<label for='filter-sort-{{sort}}'>"
|
||||||
|
str << translate(locale, "search_filters_type_option_{{sort}}")
|
||||||
|
str << "</label><br>\n"
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,28 +11,15 @@ module Invidious::Routes::API::V1::Search
|
||||||
page = env.params.query["page"]?.try &.to_i?
|
page = env.params.query["page"]?.try &.to_i?
|
||||||
page ||= 1
|
page ||= 1
|
||||||
|
|
||||||
sort_by = env.params.query["sort_by"]?.try &.downcase
|
filters = Invidious::Search::Filters.from_iv_params(env.params.query)
|
||||||
sort_by ||= "relevance"
|
search_params = filters.to_yt_params
|
||||||
|
|
||||||
date = env.params.query["date"]?.try &.downcase
|
|
||||||
date ||= ""
|
|
||||||
|
|
||||||
duration = env.params.query["duration"]?.try &.downcase
|
|
||||||
duration ||= ""
|
|
||||||
|
|
||||||
features = env.params.query["features"]?.try &.split(",").map(&.downcase)
|
|
||||||
features ||= [] of String
|
|
||||||
|
|
||||||
content_type = env.params.query["type"]?.try &.downcase
|
|
||||||
content_type ||= "video"
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
search_params = produce_search_params(page, sort_by, date, content_type, duration, features)
|
search_results = search(query, search_params, region)
|
||||||
rescue ex
|
rescue ex
|
||||||
return error_json(400, ex)
|
return error_json(400, ex)
|
||||||
end
|
end
|
||||||
|
|
||||||
search_results = search(query, search_params, region)
|
|
||||||
JSON.build do |json|
|
JSON.build do |json|
|
||||||
json.array do
|
json.array do
|
||||||
search_results.each do |item|
|
search_results.each do |item|
|
||||||
|
|
|
@ -239,7 +239,7 @@ module Invidious::Routes::Playlists
|
||||||
query = env.params.query["q"]?
|
query = env.params.query["q"]?
|
||||||
if query
|
if query
|
||||||
begin
|
begin
|
||||||
search_query, items, operators = process_search_query(query, page, user, region: nil)
|
search_query, items, _ = process_search_query(query, page, user, region: nil)
|
||||||
videos = items.select(SearchVideo).map(&.as(SearchVideo))
|
videos = items.select(SearchVideo).map(&.as(SearchVideo))
|
||||||
rescue ex
|
rescue ex
|
||||||
videos = [] of SearchVideo
|
videos = [] of SearchVideo
|
||||||
|
|
|
@ -54,19 +54,13 @@ module Invidious::Routes::Search
|
||||||
user = env.get? "user"
|
user = env.get? "user"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
search_query, videos, operators = process_search_query(query, page, user, region: region)
|
search_query, videos, filters = process_search_query(query, page, user, region: region)
|
||||||
rescue ex : ChannelSearchException
|
rescue ex : ChannelSearchException
|
||||||
return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.")
|
return error_template(404, "Unable to find channel with id of '#{HTML.escape(ex.channel)}'. Are you sure that's an actual channel id? It should look like 'UC4QobU6STFB0P71PMvOGN5A'.")
|
||||||
rescue ex
|
rescue ex
|
||||||
return error_template(500, ex)
|
return error_template(500, ex)
|
||||||
end
|
end
|
||||||
|
|
||||||
operator_hash = {} of String => String
|
|
||||||
operators.each do |operator|
|
|
||||||
key, value = operator.downcase.split(":")
|
|
||||||
operator_hash[key] = value
|
|
||||||
end
|
|
||||||
|
|
||||||
env.set "search", query
|
env.set "search", query
|
||||||
templated "search"
|
templated "search"
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class ChannelSearchException < InfoException
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def search(query, search_params = produce_search_params(content_type: "all"), region = nil) : Array(SearchItem)
|
def search(query, search_params, region = nil) : Array(SearchItem)
|
||||||
return [] of SearchItem if query.empty?
|
return [] of SearchItem if query.empty?
|
||||||
|
|
||||||
client_config = YoutubeAPI::ClientConfig.new(region: region)
|
client_config = YoutubeAPI::ClientConfig.new(region: region)
|
||||||
|
@ -14,104 +14,6 @@ def search(query, search_params = produce_search_params(content_type: "all"), re
|
||||||
return extract_items(initial_data)
|
return extract_items(initial_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def produce_search_params(page = 1, sort : String = "relevance", date : String = "", content_type : String = "",
|
|
||||||
duration : String = "", features : Array(String) = [] of String)
|
|
||||||
object = {
|
|
||||||
"1:varint" => 0_i64,
|
|
||||||
"2:embedded" => {} of String => Int64,
|
|
||||||
"9:varint" => ((page - 1) * 20).to_i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
case sort
|
|
||||||
when "relevance"
|
|
||||||
object["1:varint"] = 0_i64
|
|
||||||
when "rating"
|
|
||||||
object["1:varint"] = 1_i64
|
|
||||||
when "upload_date", "date"
|
|
||||||
object["1:varint"] = 2_i64
|
|
||||||
when "view_count", "views"
|
|
||||||
object["1:varint"] = 3_i64
|
|
||||||
else
|
|
||||||
raise "No sort #{sort}"
|
|
||||||
end
|
|
||||||
|
|
||||||
case date
|
|
||||||
when "hour"
|
|
||||||
object["2:embedded"].as(Hash)["1:varint"] = 1_i64
|
|
||||||
when "today"
|
|
||||||
object["2:embedded"].as(Hash)["1:varint"] = 2_i64
|
|
||||||
when "week"
|
|
||||||
object["2:embedded"].as(Hash)["1:varint"] = 3_i64
|
|
||||||
when "month"
|
|
||||||
object["2:embedded"].as(Hash)["1:varint"] = 4_i64
|
|
||||||
when "year"
|
|
||||||
object["2:embedded"].as(Hash)["1:varint"] = 5_i64
|
|
||||||
else nil # Ignore
|
|
||||||
end
|
|
||||||
|
|
||||||
case content_type
|
|
||||||
when "video"
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 1_i64
|
|
||||||
when "channel"
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 2_i64
|
|
||||||
when "playlist"
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 3_i64
|
|
||||||
when "movie"
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 4_i64
|
|
||||||
when "show"
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 5_i64
|
|
||||||
when "all"
|
|
||||||
#
|
|
||||||
else
|
|
||||||
object["2:embedded"].as(Hash)["2:varint"] = 1_i64
|
|
||||||
end
|
|
||||||
|
|
||||||
case duration
|
|
||||||
when "short"
|
|
||||||
object["2:embedded"].as(Hash)["3:varint"] = 1_i64
|
|
||||||
when "long"
|
|
||||||
object["2:embedded"].as(Hash)["3:varint"] = 2_i64
|
|
||||||
else nil # Ignore
|
|
||||||
end
|
|
||||||
|
|
||||||
features.each do |feature|
|
|
||||||
case feature
|
|
||||||
when "hd"
|
|
||||||
object["2:embedded"].as(Hash)["4:varint"] = 1_i64
|
|
||||||
when "subtitles"
|
|
||||||
object["2:embedded"].as(Hash)["5:varint"] = 1_i64
|
|
||||||
when "creative_commons", "cc"
|
|
||||||
object["2:embedded"].as(Hash)["6:varint"] = 1_i64
|
|
||||||
when "3d"
|
|
||||||
object["2:embedded"].as(Hash)["7:varint"] = 1_i64
|
|
||||||
when "live", "livestream"
|
|
||||||
object["2:embedded"].as(Hash)["8:varint"] = 1_i64
|
|
||||||
when "purchased"
|
|
||||||
object["2:embedded"].as(Hash)["9:varint"] = 1_i64
|
|
||||||
when "4k"
|
|
||||||
object["2:embedded"].as(Hash)["14:varint"] = 1_i64
|
|
||||||
when "360"
|
|
||||||
object["2:embedded"].as(Hash)["15:varint"] = 1_i64
|
|
||||||
when "location"
|
|
||||||
object["2:embedded"].as(Hash)["23:varint"] = 1_i64
|
|
||||||
when "hdr"
|
|
||||||
object["2:embedded"].as(Hash)["25:varint"] = 1_i64
|
|
||||||
else nil # Ignore
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if object["2:embedded"].as(Hash).empty?
|
|
||||||
object.delete("2:embedded")
|
|
||||||
end
|
|
||||||
|
|
||||||
params = object.try { |i| Protodec::Any.cast_json(i) }
|
|
||||||
.try { |i| Protodec::Any.from_json(i) }
|
|
||||||
.try { |i| Base64.urlsafe_encode(i) }
|
|
||||||
.try { |i| URI.encode_www_form(i) }
|
|
||||||
|
|
||||||
return params
|
|
||||||
end
|
|
||||||
|
|
||||||
def produce_channel_search_continuation(ucid, query, page)
|
def produce_channel_search_continuation(ucid, query, page)
|
||||||
if page <= 1
|
if page <= 1
|
||||||
idx = 0_i64
|
idx = 0_i64
|
||||||
|
@ -146,39 +48,8 @@ def produce_channel_search_continuation(ucid, query, page)
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_search_query(query, page, user, region)
|
def process_search_query(query, page, user, region)
|
||||||
channel = nil
|
# Parse legacy query
|
||||||
content_type = "all"
|
filters, channel, search_query, subscriptions = Invidious::Search::Filters.from_legacy_filters(query)
|
||||||
date = ""
|
|
||||||
duration = ""
|
|
||||||
features = [] of String
|
|
||||||
sort = "relevance"
|
|
||||||
subscriptions = nil
|
|
||||||
|
|
||||||
operators = query.split(" ").select(&.match(/\w+:[\w,]+/))
|
|
||||||
operators.each do |operator|
|
|
||||||
key, value = operator.downcase.split(":")
|
|
||||||
|
|
||||||
case key
|
|
||||||
when "channel", "user"
|
|
||||||
channel = operator.split(":")[-1]
|
|
||||||
when "content_type", "type"
|
|
||||||
content_type = value
|
|
||||||
when "date"
|
|
||||||
date = value
|
|
||||||
when "duration"
|
|
||||||
duration = value
|
|
||||||
when "feature", "features"
|
|
||||||
features = value.split(",")
|
|
||||||
when "sort"
|
|
||||||
sort = value
|
|
||||||
when "subscriptions"
|
|
||||||
subscriptions = value == "true"
|
|
||||||
else
|
|
||||||
operators.delete(operator)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
search_query = (query.split(" ") - operators).join(" ")
|
|
||||||
|
|
||||||
if channel
|
if channel
|
||||||
items = Invidious::Search::Processors.channel(search_query, page, channel)
|
items = Invidious::Search::Processors.channel(search_query, page, channel)
|
||||||
|
@ -190,9 +61,7 @@ def process_search_query(query, page, user, region)
|
||||||
items = [] of ChannelVideo
|
items = [] of ChannelVideo
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
search_params = produce_search_params(page: page, sort: sort, date: date, content_type: content_type,
|
search_params = filters.to_yt_params(page: page)
|
||||||
duration: duration, features: features)
|
|
||||||
|
|
||||||
items = search(search_query, search_params, region)
|
items = search(search_query, search_params, region)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -211,5 +80,5 @@ def process_search_query(query, page, user, region)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
{search_query, items_without_category, operators}
|
{search_query, items_without_category, filters}
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,94 +9,11 @@
|
||||||
<h3 style="text-align: center">
|
<h3 style="text-align: center">
|
||||||
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Broken? Try another Invidious Instance!") %></a>
|
<a href="/redirect?referer=<%= env.get?("current_page") %>"><%= translate(locale, "Broken? Try another Invidious Instance!") %></a>
|
||||||
</h3>
|
</h3>
|
||||||
<% else %>
|
<%
|
||||||
<details id="filters">
|
else
|
||||||
<summary>
|
Invidious::Frontend::SearchFilters.generate(filters, search_query, page, locale)
|
||||||
<h3 style="display:inline"> <%= translate(locale, "filter") %> </h3>
|
end
|
||||||
</summary>
|
%>
|
||||||
<div id="filters" class="pure-g h-box">
|
|
||||||
<div class="pure-u-1-3 pure-u-md-1-5">
|
|
||||||
<b><%= translate(locale, "date") %></b>
|
|
||||||
<hr/>
|
|
||||||
<% ["hour", "today", "week", "month", "year"].each do |date| %>
|
|
||||||
<div class="pure-u-1 pure-md-1-5">
|
|
||||||
<% if operator_hash.fetch("date", "all") == date %>
|
|
||||||
<b><%= translate(locale, date) %></b>
|
|
||||||
<% else %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil!.gsub(/ ?date:[a-z]+/, "") + " date:" + date) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, date) %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="pure-u-1-3 pure-u-md-1-5">
|
|
||||||
<b><%= translate(locale, "content_type") %></b>
|
|
||||||
<hr/>
|
|
||||||
<% ["video", "channel", "playlist", "movie", "show"].each do |content_type| %>
|
|
||||||
<div class="pure-u-1 pure-md-1-5">
|
|
||||||
<% if operator_hash.fetch("content_type", "all") == content_type %>
|
|
||||||
<b><%= translate(locale, content_type) %></b>
|
|
||||||
<% else %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil!.gsub(/ ?content_type:[a-z]+/, "") + " content_type:" + content_type) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, content_type) %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="pure-u-1-3 pure-u-md-1-5">
|
|
||||||
<b><%= translate(locale, "duration") %></b>
|
|
||||||
<hr/>
|
|
||||||
<% ["short", "long"].each do |duration| %>
|
|
||||||
<div class="pure-u-1 pure-md-1-5">
|
|
||||||
<% if operator_hash.fetch("duration", "all") == duration %>
|
|
||||||
<b><%= translate(locale, duration) %></b>
|
|
||||||
<% else %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil!.gsub(/ ?duration:[a-z]+/, "") + " duration:" + duration) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, duration) %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="pure-u-1-3 pure-u-md-1-5">
|
|
||||||
<b><%= translate(locale, "features") %></b>
|
|
||||||
<hr/>
|
|
||||||
<% ["hd", "subtitles", "creative_commons", "3d", "live", "purchased", "4k", "360", "location", "hdr"].each do |feature| %>
|
|
||||||
<div class="pure-u-1 pure-md-1-5">
|
|
||||||
<% if operator_hash.fetch("features", "all").includes?(feature) %>
|
|
||||||
<b><%= translate(locale, feature) %></b>
|
|
||||||
<% elsif operator_hash.has_key?("features") %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil!.gsub(/features:/, "features:" + feature + ",")) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, feature) %>
|
|
||||||
</a>
|
|
||||||
<% else %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil! + " features:" + feature) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, feature) %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="pure-u-1-3 pure-u-md-1-5">
|
|
||||||
<b><%= translate(locale, "sort") %></b>
|
|
||||||
<hr/>
|
|
||||||
<% ["relevance", "rating", "date", "views"].each do |sort| %>
|
|
||||||
<div class="pure-u-1 pure-md-1-5">
|
|
||||||
<% if operator_hash.fetch("sort", "relevance") == sort %>
|
|
||||||
<b><%= translate(locale, sort) %></b>
|
|
||||||
<% else %>
|
|
||||||
<a href="/search?q=<%= URI.encode_www_form(query.not_nil!.gsub(/ ?sort:[a-z]+/, "") + " sort:" + sort) %>&page=<%= page %>">
|
|
||||||
<%= translate(locale, sort) %>
|
|
||||||
</a>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if videos.size == 0 %>
|
<% if videos.size == 0 %>
|
||||||
<hr style="margin: 0;"/>
|
<hr style="margin: 0;"/>
|
||||||
|
@ -107,7 +24,7 @@
|
||||||
<div class="pure-g h-box v-box">
|
<div class="pure-g h-box v-box">
|
||||||
<div class="pure-u-1 pure-u-lg-1-5">
|
<div class="pure-u-1 pure-u-lg-1-5">
|
||||||
<% if page > 1 %>
|
<% if page > 1 %>
|
||||||
<a href="/search?q=<%= search_query_encoded %>&page=<%= page - 1 %>">
|
<a href="/search?q=<%= search_query_encoded %>&<% filters.to_iv_params %>&page=<%= page - 1 %>">
|
||||||
<%= translate(locale, "Previous page") %>
|
<%= translate(locale, "Previous page") %>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -115,7 +32,7 @@
|
||||||
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
||||||
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
||||||
<% if videos.size >= 20 %>
|
<% if videos.size >= 20 %>
|
||||||
<a href="/search?q=<%= search_query_encoded %>&page=<%= page + 1 %>">
|
<a href="/search?q=<%= search_query_encoded %>&<% filters.to_iv_params %>&page=<%= page + 1 %>">
|
||||||
<%= translate(locale, "Next page") %>
|
<%= translate(locale, "Next page") %>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -131,7 +48,7 @@
|
||||||
<div class="pure-g h-box">
|
<div class="pure-g h-box">
|
||||||
<div class="pure-u-1 pure-u-lg-1-5">
|
<div class="pure-u-1 pure-u-lg-1-5">
|
||||||
<% if page > 1 %>
|
<% if page > 1 %>
|
||||||
<a href="/search?q=<%= search_query_encoded %>&page=<%= page - 1 %>">
|
<a href="/search?q=<%= search_query_encoded %>&<% filters.to_iv_params %>&page=<%= page - 1 %>">
|
||||||
<%= translate(locale, "Previous page") %>
|
<%= translate(locale, "Previous page") %>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -139,7 +56,7 @@
|
||||||
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
<div class="pure-u-1 pure-u-lg-3-5"></div>
|
||||||
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
<div class="pure-u-1 pure-u-lg-1-5" style="text-align:right">
|
||||||
<% if videos.size >= 20 %>
|
<% if videos.size >= 20 %>
|
||||||
<a href="/search?q=<%= search_query_encoded %>&page=<%= page + 1 %>">
|
<a href="/search?q=<%= search_query_encoded %>&<% filters.to_iv_params %>&page=<%= page + 1 %>">
|
||||||
<%= translate(locale, "Next page") %>
|
<%= translate(locale, "Next page") %>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
Loading…
Reference in a new issue