From 566b8f83cfcd60c0895b01eb470a5da3df15a334 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Thu, 6 Dec 2018 13:27:01 +0900 Subject: [PATCH] Improved search --- layout/layout.pixy | 2 +- layout/sidebar/sidebar.pixy | 4 +- mixins/FuzzySearch.pixy | 4 +- pages/index/searchroutes/searchroutes.go | 3 +- pages/search/search.go | 25 +++++---- pages/search/search.pixy | 68 +++++++++++++++--------- pages/search/search.scarlet | 17 +++--- scripts/Actions/Search.ts | 27 +++++++--- utils/SearchClass.go | 13 +++++ 9 files changed, 105 insertions(+), 58 deletions(-) create mode 100644 utils/SearchClass.go diff --git a/layout/layout.pixy b/layout/layout.pixy index 7b43204d..6175900f 100644 --- a/layout/layout.pixy +++ b/layout/layout.pixy @@ -48,7 +48,7 @@ component Layout(app *aero.Application, ctx *aero.Context, user *arn.User, openG body #container(class=utils.GetContainerClass(ctx)) #columns - Sidebar(user) + Sidebar(ctx.Get("term"), user) Content(content) LoadingAnimation diff --git a/layout/sidebar/sidebar.pixy b/layout/sidebar/sidebar.pixy index 184dff3a..57e1b70b 100644 --- a/layout/sidebar/sidebar.pixy +++ b/layout/sidebar/sidebar.pixy @@ -1,4 +1,4 @@ -component Sidebar(user *arn.User) +component Sidebar(searchTerm string, user *arn.User) aside#sidebar //- User avatar .user-image-container @@ -21,7 +21,7 @@ component Sidebar(user *arn.User) div(aria-label="Search") .sidebar-button Icon("search") - FuzzySearch + FuzzySearch(searchTerm) .speech-input.action(data-action="searchBySpeech", data-trigger="click", title="Speech input") RawIcon("microphone") diff --git a/mixins/FuzzySearch.pixy b/mixins/FuzzySearch.pixy index e56577cb..3730b7bb 100644 --- a/mixins/FuzzySearch.pixy +++ b/mixins/FuzzySearch.pixy @@ -1,2 +1,2 @@ -component FuzzySearch - input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F") \ No newline at end of file +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", value=value) \ No newline at end of file diff --git a/pages/index/searchroutes/searchroutes.go b/pages/index/searchroutes/searchroutes.go index 7895b9ad..0ff9571c 100644 --- a/pages/index/searchroutes/searchroutes.go +++ b/pages/index/searchroutes/searchroutes.go @@ -13,7 +13,8 @@ func Register(l *layout.Layout) { l.Page("/empty-search", search.GetEmptySearch) l.Page("/anime-search/*term", search.Anime) 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("/user-search/*term", search.Users) l.Page("/amv-search/*term", search.AMVs) diff --git a/pages/search/search.go b/pages/search/search.go index dcf0ea69..a988d206 100644 --- a/pages/search/search.go +++ b/pages/search/search.go @@ -5,10 +5,7 @@ import ( "github.com/animenotifier/notify.moe/utils" - "github.com/aerogo/flow" - "github.com/aerogo/aero" - "github.com/animenotifier/arn" "github.com/animenotifier/arn/search" "github.com/animenotifier/notify.moe/components" ) @@ -70,22 +67,24 @@ func Characters(ctx *aero.Context) string { return ctx.HTML(components.CharacterSearchResults(characters, user)) } -// Forum search. -func Forum(ctx *aero.Context) string { +// Posts search. +func Posts(ctx *aero.Context) string { term := ctx.Get("term") term = strings.TrimPrefix(term, "/") user := utils.GetUser(ctx) + posts := search.Posts(term, maxPosts) - var posts []*arn.Post - var threads []*arn.Thread + return ctx.HTML(components.PostsSearchResults(posts, user)) +} - flow.Parallel(func() { - posts = search.Posts(term, maxPosts) - }, func() { - threads = search.Threads(term, maxThreads) - }) +// Threads search. +func Threads(ctx *aero.Context) string { + term := ctx.Get("term") + 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. diff --git a/pages/search/search.pixy b/pages/search/search.pixy index a44aa12f..b2e91ff5 100644 --- a/pages/search/search.pixy +++ b/pages/search/search.pixy @@ -2,7 +2,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos h1.page-title= "Search: " + term .search - .widget + .widget(class=utils.SearchClass(animes)) h3.widget-title Icon("tv") span Anime @@ -10,7 +10,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos #anime-search-results AnimeSearchResults(animes, user) - .widget + .widget(class=utils.SearchClass(characters)) h3.widget-title Icon("user") span Characters @@ -18,15 +18,23 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos #character-search-results CharacterSearchResults(characters, user) - .widget + .widget(class=utils.SearchClass(posts)) h3.widget-title Icon("comment") - span Forum + span Posts - #forum-search-results - ForumSearchResults(posts, threads, user) + #posts-search-results + 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 Icon("music") span Soundtracks @@ -34,7 +42,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos #soundtrack-search-results SoundTrackSearchResults(tracks, user) - .widget + .widget(class=utils.SearchClass(amvs)) h3.widget-title Icon("video-camera") span AMVs @@ -50,7 +58,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos //- #quote-search-results //- QuoteSearchResults(quotes) - .widget + .widget(class=utils.SearchClass(companies)) h3.widget-title Icon("building") span Companies @@ -58,7 +66,7 @@ component SearchResults(term string, users []*arn.User, animes []*arn.Anime, pos #company-search-results CompanySearchResults(companies) - .widget + .widget(class=utils.SearchClass(users)) h3.widget-title Icon("user") span Users @@ -84,26 +92,34 @@ component CharacterSearchResults(characters []*arn.Character, user *arn.User) .mountable(data-mountable-type="character") CharacterSmall(character, user) -component ForumSearchResults(posts []*arn.Post, threads []*arn.Thread, user *arn.User) - if len(posts) == 0 && len(threads) == 0 +component PostsSearchResults(posts []*arn.Post, user *arn.User) + if len(posts) == 0 p.no-search-results.mountable No posts found. else - .forum-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 - + .posts-search-results each post in posts - .forum-search-result.mountable(data-mountable-type="forum") - .forum-search-result-header - a.forum-search-result-title(href=post.Link(), data-mountable-type="forum")= post.Parent().TitleByUser(user) + .posts-search-result.mountable(data-mountable-type="post") + .posts-search-result-header + a.posts-search-result-title(href=post.Link(), data-mountable-type="post")= post.Parent().TitleByUser(user) + if post.Creator().HasNick() - .forum-search-result-author= post.Creator().Nick - .forum-search-result-sample= post.Text + .posts-search-result-author= post.Creator().Nick + + .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) if len(tracks) == 0 diff --git a/pages/search/search.scarlet b/pages/search/search.scarlet index a7f1504e..e75d0443 100644 --- a/pages/search/search.scarlet +++ b/pages/search/search.scarlet @@ -10,29 +10,29 @@ width anime-image-small-width !important height anime-image-small-height !important -.forum-search-results +.posts-search-results horizontal-wrap justify-content space-around -.forum-search-result +.posts-search-result vertical flex 1 flex-basis 380px padding 0.75rem overflow hidden -.forum-search-result-header +.posts-search-result-header horizontal -.forum-search-result-title +.posts-search-result-title flex 1 clip-long-text -.forum-search-result-author +.posts-search-result-author text-align right opacity 0.5 -.forum-search-result-sample +.posts-search-result-sample clip-long-text margin-bottom 1rem opacity 0.8 @@ -43,4 +43,7 @@ .no-search-results text-align left - padding-bottom typography-margin \ No newline at end of file + padding-bottom typography-margin + +.search-section-disabled + display none !important \ No newline at end of file diff --git a/scripts/Actions/Search.ts b/scripts/Actions/Search.ts index b6ff8680..51719334 100644 --- a/scripts/Actions/Search.ts +++ b/scripts/Actions/Search.ts @@ -1,5 +1,6 @@ import AnimeNotifier from "../AnimeNotifier" import { delay, requestIdleCallback } from "../Utils" +import Diff from "scripts/Diff"; // Search page reference var emptySearchHTML = "" @@ -8,7 +9,8 @@ var searchPageTitle: HTMLElement var correctResponseRendered = { "anime": false, "character": false, - "forum": false, + "posts": false, + "threads": false, "soundtrack": false, "user": false, "amv": false, @@ -21,7 +23,8 @@ var oldTerm = "" // Containers for all the search results var animeSearchResults: HTMLElement var characterSearchResults: HTMLElement -var forumSearchResults: HTMLElement +var postsSearchResults: HTMLElement +var threadsSearchResults: HTMLElement var soundtrackSearchResults: HTMLElement var userSearchResults: HTMLElement var amvSearchResults: HTMLElement @@ -59,7 +62,8 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?: // Reset correctResponseRendered.anime = false correctResponseRendered.character = false - correctResponseRendered.forum = false + correctResponseRendered.posts = false + correctResponseRendered.threads = false correctResponseRendered.soundtrack = false correctResponseRendered.user = false correctResponseRendered.amv = false @@ -108,7 +112,8 @@ export async function search(arn: AnimeNotifier, search: HTMLInputElement, evt?: if(!animeSearchResults) { animeSearchResults = document.getElementById("anime-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") userSearchResults = document.getElementById("user-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)) .catch(console.error) - fetch("/_/forum-search/" + term, fetchOptions) - .then(showResponseInElement(arn, url, "forum", forumSearchResults)) + fetch("/_/posts-search/" + term, fetchOptions) + .then(showResponseInElement(arn, url, "posts", postsSearchResults)) + .catch(console.error) + + fetch("/_/threads-search/" + term, fetchOptions) + .then(showResponseInElement(arn, url, "threads", threadsSearchResults)) .catch(console.error) fetch("/_/soundtrack-search/" + term, fetchOptions) @@ -170,6 +179,12 @@ function showResponseInElement(arn: AnimeNotifier, url: string, typeName: string return async (response: Response) => { 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) { // Return if this result would overwrite the already arrived correct result if(correctResponseRendered[typeName]) { diff --git a/utils/SearchClass.go b/utils/SearchClass.go new file mode 100644 index 00000000..e9df6b28 --- /dev/null +++ b/utils/SearchClass.go @@ -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 "" +}