Improved search
This commit is contained in:
parent
2fc5a07658
commit
566b8f83cf
@ -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
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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)
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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(class=utils.SearchClass(threads))
|
||||||
|
h3.widget-title
|
||||||
|
Icon("comments")
|
||||||
|
span Threads
|
||||||
|
|
||||||
.widget
|
#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
|
||||||
|
@ -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
|
||||||
@ -43,4 +43,7 @@
|
|||||||
|
|
||||||
.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
|
@ -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
13
utils/SearchClass.go
Normal 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 ""
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user