Improved search

This commit is contained in:
Eduard Urbach 2018-12-06 13:27:01 +09:00
parent 2fc5a07658
commit 566b8f83cf
9 changed files with 105 additions and 58 deletions

View File

@ -48,7 +48,7 @@ component Layout(app *aero.Application, ctx *aero.Context, user *arn.User, openG
body body
#container(class=utils.GetContainerClass(ctx)) #container(class=utils.GetContainerClass(ctx))
#columns #columns
Sidebar(user) Sidebar(ctx.Get("term"), user)
Content(content) Content(content)
LoadingAnimation LoadingAnimation

View File

@ -1,4 +1,4 @@
component Sidebar(user *arn.User) component Sidebar(searchTerm string, user *arn.User)
aside#sidebar aside#sidebar
//- User avatar //- User avatar
.user-image-container .user-image-container
@ -21,7 +21,7 @@ component Sidebar(user *arn.User)
div(aria-label="Search") div(aria-label="Search")
.sidebar-button .sidebar-button
Icon("search") Icon("search")
FuzzySearch FuzzySearch(searchTerm)
.speech-input.action(data-action="searchBySpeech", data-trigger="click", title="Speech input") .speech-input.action(data-action="searchBySpeech", data-trigger="click", title="Speech input")
RawIcon("microphone") RawIcon("microphone")

View File

@ -1,2 +1,2 @@
component FuzzySearch component FuzzySearch(value string)
input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F") input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F", value=value)

View File

@ -13,7 +13,8 @@ func Register(l *layout.Layout) {
l.Page("/empty-search", search.GetEmptySearch) l.Page("/empty-search", search.GetEmptySearch)
l.Page("/anime-search/*term", search.Anime) l.Page("/anime-search/*term", search.Anime)
l.Page("/character-search/*term", search.Characters) l.Page("/character-search/*term", search.Characters)
l.Page("/forum-search/*term", search.Forum) l.Page("/posts-search/*term", search.Posts)
l.Page("/threads-search/*term", search.Threads)
l.Page("/soundtrack-search/*term", search.SoundTracks) l.Page("/soundtrack-search/*term", search.SoundTracks)
l.Page("/user-search/*term", search.Users) l.Page("/user-search/*term", search.Users)
l.Page("/amv-search/*term", search.AMVs) l.Page("/amv-search/*term", search.AMVs)

View File

@ -5,10 +5,7 @@ import (
"github.com/animenotifier/notify.moe/utils" "github.com/animenotifier/notify.moe/utils"
"github.com/aerogo/flow"
"github.com/aerogo/aero" "github.com/aerogo/aero"
"github.com/animenotifier/arn"
"github.com/animenotifier/arn/search" "github.com/animenotifier/arn/search"
"github.com/animenotifier/notify.moe/components" "github.com/animenotifier/notify.moe/components"
) )
@ -70,22 +67,24 @@ func Characters(ctx *aero.Context) string {
return ctx.HTML(components.CharacterSearchResults(characters, user)) return ctx.HTML(components.CharacterSearchResults(characters, user))
} }
// Forum search. // Posts search.
func Forum(ctx *aero.Context) string { func Posts(ctx *aero.Context) string {
term := ctx.Get("term") term := ctx.Get("term")
term = strings.TrimPrefix(term, "/") term = strings.TrimPrefix(term, "/")
user := utils.GetUser(ctx) user := utils.GetUser(ctx)
posts := search.Posts(term, maxPosts)
var posts []*arn.Post return ctx.HTML(components.PostsSearchResults(posts, user))
var threads []*arn.Thread }
flow.Parallel(func() { // Threads search.
posts = search.Posts(term, maxPosts) func Threads(ctx *aero.Context) string {
}, func() { term := ctx.Get("term")
threads = search.Threads(term, maxThreads) term = strings.TrimPrefix(term, "/")
}) user := utils.GetUser(ctx)
threads := search.Threads(term, maxThreads)
return ctx.HTML(components.ForumSearchResults(posts, threads, user)) return ctx.HTML(components.ThreadsSearchResults(threads, user))
} }
// SoundTracks search. // SoundTracks search.

View File

@ -2,7 +2,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
h1.page-title= "Search: " + term h1.page-title= "Search: " + term
.search .search
.widget .widget(class=utils.SearchClass(animes))
h3.widget-title h3.widget-title
Icon("tv") Icon("tv")
span Anime span Anime
@ -10,7 +10,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
#anime-search-results #anime-search-results
AnimeSearchResults(animes, user) AnimeSearchResults(animes, user)
.widget .widget(class=utils.SearchClass(characters))
h3.widget-title h3.widget-title
Icon("user") Icon("user")
span Characters span Characters
@ -18,15 +18,23 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
#character-search-results #character-search-results
CharacterSearchResults(characters, user) CharacterSearchResults(characters, user)
.widget .widget(class=utils.SearchClass(posts))
h3.widget-title h3.widget-title
Icon("comment") Icon("comment")
span Forum span Posts
#forum-search-results #posts-search-results
ForumSearchResults(posts, threads, user) PostsSearchResults(posts, user)
.widget .widget(class=utils.SearchClass(threads))
h3.widget-title
Icon("comments")
span Threads
#threads-search-results
ThreadsSearchResults(threads, user)
.widget(class=utils.SearchClass(tracks))
h3.widget-title h3.widget-title
Icon("music") Icon("music")
span Soundtracks span Soundtracks
@ -34,7 +42,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
#soundtrack-search-results #soundtrack-search-results
SoundTrackSearchResults(tracks, user) SoundTrackSearchResults(tracks, user)
.widget .widget(class=utils.SearchClass(amvs))
h3.widget-title h3.widget-title
Icon("video-camera") Icon("video-camera")
span AMVs span AMVs
@ -50,7 +58,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
//- #quote-search-results //- #quote-search-results
//- QuoteSearchResults(quotes) //- QuoteSearchResults(quotes)
.widget .widget(class=utils.SearchClass(companies))
h3.widget-title h3.widget-title
Icon("building") Icon("building")
span Companies span Companies
@ -58,7 +66,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos
#company-search-results #company-search-results
CompanySearchResults(companies) CompanySearchResults(companies)
.widget .widget(class=utils.SearchClass(users))
h3.widget-title h3.widget-title
Icon("user") Icon("user")
span Users span Users
@ -84,26 +92,34 @@ component CharacterSearchResults(characters []*arn.Character, user *arn.User)
.mountable(data-mountable-type="character") .mountable(data-mountable-type="character")
CharacterSmall(character, user) CharacterSmall(character, user)
component ForumSearchResults(posts []*arn.Post, threads []*arn.Thread, user *arn.User) component PostsSearchResults(posts []*arn.Post, user *arn.User)
if len(posts) == 0 && len(threads) == 0 if len(posts) == 0
p.no-search-results.mountable No posts found. p.no-search-results.mountable No posts found.
else else
.forum-search-results .posts-search-results
each thread in threads
.forum-search-result.mountable(data-mountable-type="forum")
.forum-search-result-header
a.forum-search-result-title(href=thread.Link())= thread.Title
if thread.Creator().HasNick()
.forum-search-result-author= thread.Creator().Nick
.forum-search-result-sample= thread.Text
each post in posts each post in posts
.forum-search-result.mountable(data-mountable-type="forum") .posts-search-result.mountable(data-mountable-type="post")
.forum-search-result-header .posts-search-result-header
a.forum-search-result-title(href=post.Link(), data-mountable-type="forum")= post.Parent().TitleByUser(user) a.posts-search-result-title(href=post.Link(), data-mountable-type="post")= post.Parent().TitleByUser(user)
if post.Creator().HasNick() if post.Creator().HasNick()
.forum-search-result-author= post.Creator().Nick .posts-search-result-author= post.Creator().Nick
.forum-search-result-sample= post.Text
.posts-search-result-sample= post.Text
component ThreadsSearchResults(threads []*arn.Thread, user *arn.User)
if len(threads) == 0
p.no-search-results.mountable No threads found.
else
each thread in threads
.posts-search-result.mountable(data-mountable-type="thread")
.posts-search-result-header
a.posts-search-result-title(href=thread.Link())= thread.Title
if thread.Creator().HasNick()
.posts-search-result-author= thread.Creator().Nick
.posts-search-result-sample= thread.Text
component SoundTrackSearchResults(tracks []*arn.SoundTrack, user *arn.User) component SoundTrackSearchResults(tracks []*arn.SoundTrack, user *arn.User)
if len(tracks) == 0 if len(tracks) == 0

View File

@ -10,29 +10,29 @@
width anime-image-small-width !important width anime-image-small-width !important
height anime-image-small-height !important height anime-image-small-height !important
.forum-search-results .posts-search-results
horizontal-wrap horizontal-wrap
justify-content space-around justify-content space-around
.forum-search-result .posts-search-result
vertical vertical
flex 1 flex 1
flex-basis 380px flex-basis 380px
padding 0.75rem padding 0.75rem
overflow hidden overflow hidden
.forum-search-result-header .posts-search-result-header
horizontal horizontal
.forum-search-result-title .posts-search-result-title
flex 1 flex 1
clip-long-text clip-long-text
.forum-search-result-author .posts-search-result-author
text-align right text-align right
opacity 0.5 opacity 0.5
.forum-search-result-sample .posts-search-result-sample
clip-long-text clip-long-text
margin-bottom 1rem margin-bottom 1rem
opacity 0.8 opacity 0.8
@ -44,3 +44,6 @@
.no-search-results .no-search-results
text-align left text-align left
padding-bottom typography-margin padding-bottom typography-margin
.search-section-disabled
display none !important

View File

@ -1,5 +1,6 @@
import AnimeNotifier from "../AnimeNotifier" import AnimeNotifier from "../AnimeNotifier"
import { delay, requestIdleCallback } from "../Utils" import { delay, requestIdleCallback } from "../Utils"
import Diff from "scripts/Diff";
// Search page reference // Search page reference
var emptySearchHTML = "" var emptySearchHTML = ""
@ -8,7 +9,8 @@ var searchPageTitle: HTMLElement
var correctResponseRendered = { var correctResponseRendered = {
"anime": false, "anime": false,
"character": false, "character": false,
"forum": false, "posts": false,
"threads": false,
"soundtrack": false, "soundtrack": false,
"user": false, "user": false,
"amv": false, "amv": false,
@ -21,7 +23,8 @@ var oldTerm = ""
// Containers for all the search results // Containers for all the search results
var animeSearchResults: HTMLElement var animeSearchResults: HTMLElement
var characterSearchResults: HTMLElement var characterSearchResults: HTMLElement
var forumSearchResults: HTMLElement var postsSearchResults: HTMLElement
var threadsSearchResults: HTMLElement
var soundtrackSearchResults: HTMLElement var soundtrackSearchResults: HTMLElement
var userSearchResults: HTMLElement var userSearchResults: HTMLElement
var amvSearchResults: HTMLElement var amvSearchResults: HTMLElement
@ -59,7 +62,8 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
// Reset // Reset
correctResponseRendered.anime = false correctResponseRendered.anime = false
correctResponseRendered.character = false correctResponseRendered.character = false
correctResponseRendered.forum = false correctResponseRendered.posts = false
correctResponseRendered.threads = false
correctResponseRendered.soundtrack = false correctResponseRendered.soundtrack = false
correctResponseRendered.user = false correctResponseRendered.user = false
correctResponseRendered.amv = false correctResponseRendered.amv = false
@ -108,7 +112,8 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
if(!animeSearchResults) { if(!animeSearchResults) {
animeSearchResults = document.getElementById("anime-search-results") animeSearchResults = document.getElementById("anime-search-results")
characterSearchResults = document.getElementById("character-search-results") characterSearchResults = document.getElementById("character-search-results")
forumSearchResults = document.getElementById("forum-search-results") postsSearchResults = document.getElementById("posts-search-results")
threadsSearchResults = document.getElementById("threads-search-results")
soundtrackSearchResults = document.getElementById("soundtrack-search-results") soundtrackSearchResults = document.getElementById("soundtrack-search-results")
userSearchResults = document.getElementById("user-search-results") userSearchResults = document.getElementById("user-search-results")
amvSearchResults = document.getElementById("amv-search-results") amvSearchResults = document.getElementById("amv-search-results")
@ -139,8 +144,12 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?:
.then(showResponseInElement(arn, url, "character", characterSearchResults)) .then(showResponseInElement(arn, url, "character", characterSearchResults))
.catch(console.error) .catch(console.error)
fetch("/_/forum-search/" + term, fetchOptions) fetch("/_/posts-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "forum", forumSearchResults)) .then(showResponseInElement(arn, url, "posts", postsSearchResults))
.catch(console.error)
fetch("/_/threads-search/" + term, fetchOptions)
.then(showResponseInElement(arn, url, "threads", threadsSearchResults))
.catch(console.error) .catch(console.error)
fetch("/_/soundtrack-search/" + term, fetchOptions) fetch("/_/soundtrack-search/" + term, fetchOptions)
@ -170,6 +179,12 @@ function showResponseInElement(arn: AnimeNotifier, url: string, typeName: string
return async (response: Response) => { return async (response: Response) => {
let html = await response.text() let html = await response.text()
if(html.includes("no-search-results")) {
Diff.mutations.queue(() => element.parentElement.classList.add("search-section-disabled"))
} else {
Diff.mutations.queue(() => element.parentElement.classList.remove("search-section-disabled"))
}
if(arn.app.currentPath !== url) { if(arn.app.currentPath !== url) {
// Return if this result would overwrite the already arrived correct result // Return if this result would overwrite the already arrived correct result
if(correctResponseRendered[typeName]) { if(correctResponseRendered[typeName]) {

13
utils/SearchClass.go Normal file
View File

@ -0,0 +1,13 @@
package utils
import "reflect"
// SearchClass returns the class for a search section
// depending on the length of the search results.
func SearchClass(results interface{}) string {
if reflect.ValueOf(results).Len() == 0 {
return "search-section-disabled"
}
return ""
}