diff options
Diffstat (limited to 'desk/web/search/search.hoon')
-rw-r--r-- | desk/web/search/search.hoon | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/desk/web/search/search.hoon b/desk/web/search/search.hoon new file mode 100644 index 0000000..1cf58d0 --- /dev/null +++ b/desk/web/search/search.hoon @@ -0,0 +1,441 @@ +/- boke, tp=trill-post, tlonc=tlon-channels, cnt=contact +/+ plib=trill-utils, ui=trill-ui, sr=sortug, lib=boke, const=constants, kaji, wall +/= post-text /web/components/post-text +/= date-div /web/components/date +/= user /web/components/user +/= chat-manx /web/chat/chat +|_ [s=state:boke =bowl:gall] ++* wal ~(. wall src.bowl) +++ css ^~ %- trip +''' +#query-string{ + font-weight: 700; + font-size: 1.3rem; +} +#search{ + + & .form{ + + & .row{ + padding: 0.5rem; + border-bottom: 1px solid var(--text-color); + align-items: center; + + & input{ + line-height: 2rem; + flex-grow:1; + } + & h2{ + margin: 0 1rem 0 0; + color: var(--text-color); + } +} + +#filters{ + display: flex; + justify-content: space-between; + padding-top: 0.5rem; + + & select{ + background-color: var(--background-color); + height: 2rem; + } +} + +} + & fieldset{ + display: block; +} + & section{ + margin: 2rem 0; + + & h3 { + font-size: 1.6rem; + } + } + & .res{ + border-bottom: 1px solid var(--text-color); + padding: 0.5rem; + & .name{ + font-weight: 600; + } + & .snip{ + padding: 0 1rem; + } + + /* comments */ + & .comment-meta{ + display: flex; + flex-wrap: wrap; + font-size: 0.9rem; + + & a{ + font-size: 0.9rem; + } + + & .sep{ + margin: 0 0.3rem; + } + } + + & a { + font-size: 1.3rem; + } + & .tag{ + margin: 0 0.3rem; + padding: 0.1rem; + background-color: var(--huang); + opacity: 0.9; + font-size: 0.7rem; + cursor: pointer; + } + } + & .not-found{ + margin-top: 4rem; + } +& .highlight{ + background-color: var(--huang); + } +& button{ + display: block; + margin: 1rem auto; + } +& .spinner{ + width: 50px; + height: 50px; + margin: 1rem auto; + } +& #spinner-zh{ + width: 100px; + height: 100px; +} +& .tabs { + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); + border-radius: 5px; + overflow: hidden; + + & .tab { + background-color: #f1f1f1; + float: left; + border: none; + outline: none; + cursor: pointer; + padding: 14px 16px; + transition: 0.3s; + } + + & .tab:hover { + background-color: #ddd; + } + /* Style for active tab */ + & .tab.active { + background-color: #ccc; + } + } +} +@media (min-width: 800px){ + #search{ + width: 70%; + margin: auto; + } +} +''' +++ script ^~ %- trip +''' +function highlight(){ + const params = new URLSearchParams(new URL(window.location.href).search); + const query = params.get('query'); + const div = document.getElementById("search"); + const snips = div.querySelectorAll(".snip"); + const titles = div.querySelectorAll(".title"); + [...titles, ...snips].forEach(el => { + const h = el.innerHTML; + const r = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); + const h2 = h.replace(r, `<span class="highlight">$1</span>`) + el.innerHTML = h2 + }); +} +document.addEventListener("kaji-scry", (e) => highlight()); +addEventListener('DOMContentLoaded', async () => highlight()); +addEventListener('kaji-scry', async () => highlight()); +''' ++$ section $?(%blog %comments %chat %threads %replies) +++ cursor +|= [=pars d=(unit time) up=?] ^- marl + ?~ d ~ + =/ cursor-string (scow:parsing:sr %uw `@uw`u.d) + =/ name ?: up "before" "after" + =/ label ?: up "Newer Posts" "Older Posts" + =/ indicator ?: up "#spinner-up" "#spinner-down" + =/ button=manx + ;button + =kaji "iscroll" + =name name + =value cursor-string + =path "/search/f" + =cont "#search-results" + =indicator indicator + ; {label} + == + =/ upc + ;div + ;+ button + ;img#spinner-up.spinner@"spinner.svg"(style "display: none;"); + == + =/ downc + ;div + ;img#spinner-down.spinner@"spinner.svg"(style "display: none;"); + ;+ button + == + ;+ ?: up upc downc + +++ blog-result +|= [fn=full-node:tp snip=@t] ^- manx + =/ ttags (tags:wal ~(tap in tags.p.fn)) + ;div.res + ;header.f1 + ;div + ;a.title/"{(trip (spat (title-to-path:lib title.p.fn id.p.fn)))}":"{(trip title.p.fn)}" + ;div + ;* %+ turn ttags |= t=@t ;a.tag/"/blog?t={(trip t)}": {(trip t)} + == + == + ;div.post-date + ;* (date-div id.p.fn .y) + == + == + ;div.snip + ;p:"{(trip snip)}" + == + == +++ comment-result +|= [fn=full-node:tp snip=@t contacts=whoms:cnt] ^- manx + =/ thread (get:gorm:tp feed.s thread.p.fn) + ?~ thread ;span; + =/ thread-link=tape (trip (spat (title-to-path:lib title.u.thread id.u.thread))) :: TODO check for relative/absolute path + =/ thread-link=tape (find-board-path:lib paths.s u.thread) + =/ uid (enc:kaji [author.p.fn id.p.fn]) + =/ permalink=tape %+ weld thread-link "/{uid}" + =/ time-string=tape (post-date-ago:lib id.p.fn now.bowl %yau) + =/ usr (user author.p.fn contacts 32) +;div.res + =id "comment-{uid}" + ;div.comment-meta + ;a/"/u/{(scow %p author.p.fn)}" + ;+ name.usr + == + ;span.sep:"|" + ;a/"{permalink}":"{time-string} ago" + ;span.sep:"|" + ;a/"{thread-link}":"On: {(trip title.u.thread)}" + == + ;div.snip + ;p:"{(trip snip)}" + == +== +++ thread-result +|= [fn=full-node:tp snip=@t contacts=whoms:cnt] ^- manx + =/ thread-link=tape (find-board-path:lib paths.s p.fn) + =/ time-string=tape (post-date-ago:lib id.p.fn now.bowl %yau) + =/ usr (user author.p.fn contacts 32) + =/ ttags (tags:wal ~(tap in tags.p.fn)) +;div.res + ;header.f1 + ;div + ;a.title/"/board/p/{thread-link}":"{(trip title.p.fn)}" + ;div + ;* %+ turn ttags |= t=@t ;a.tag/"/board?t={(trip t)}": {(trip t)} + == + == + ;div.post-date:"{time-string} ago" + == + ;+ name.usr + ;div.snip + ;p:"{(trip snip)}" + == +== +++ reply-result +|= [fn=full-node:tp snip=@t contacts=whoms:cnt] ^- manx + =/ thread (get:gorm:tp feed.s thread.p.fn) + ?~ thread ;span; + =/ thread-link=tape (find-board-path:lib paths.s u.thread) + =/ uid (enc:kaji [author.p.fn id.p.fn]) + =/ permalink=tape %+ weld thread-link "/{uid}" + =/ time-string=tape (post-date-ago:lib id.p.fn now.bowl %yau) + =/ ttags (tags:wal ~(tap in tags.p.fn)) + =/ usr (user author.p.fn contacts 32) +;div.res + ;header.f1 + ;div + ;a/"/board/p/{permalink}":"{(trip title.p.fn)}" + ;div + ;* %+ turn ttags |= t=@t ;a.tag/"/board?t={(trip t)}": {(trip t)} + == + == + ;div.post-date:"{time-string} ago" + == + ;+ name.usr + ;div.snip + ;p:"{(trip snip)}" + == +== +:: +++ chat-result +|= [r=reference:tlonc =whoms:cnt] ^- manx +=/ chat-core ~(. chat-manx [whoms bowl]) +?- -.r +%post (post-div:chat-core +<.post.r) +%reply (post-div:chat-core +.reply.r) +== +++ make-params +|= [query=@t res=page-req:tp] +:: =/ newer ?~ newer.res "" "&before={(scow %uw `@uw`u.newer.res)}" +:: =/ older ?~ older.res "" "&after={(scow %uw `@uw`u.older.res)}" +:: =/ count ?: .=(count.res page-size:lib) "" "&count={(scow %ud count.res)}" +:: %- en-urlt:html +:: "?query={(trip query)}{newer}{older}{count}" +"?query={(trip query)}" +++ form +|= =pars +^- manx + ;form.form + =swap "swap" + =targ "#search-results" + =path "/search/f" + =show-params "show" + =indicator "#spinner-zh" + + ;div.flex.row + ;a/"/search" + ;h2:"Search" + == + ;input(type "text", name "query", value (trip query.pars)) + =placeholder "Search all Bloody Shovel Content" + =kaji "search" + =bounce "1000" + ; + == + :: ;fieldset + :: ;label + :: ; Tags + :: ;input(type "text", name "tags"); + :: == + :: == + == + ;div#filters.row + ;label + ; Section + ;select + =name "section" + =kaji "scry" + =path "/search/f" + ;* %+ turn ~["blog" "comments" "threads" "replies" "chat"] |= t=tape + ?: .=(section.pars (crip t)) + ;option + =value t + =selected "" + ; {t} + == + ;option + =value t + ; {t} + == + == + == + ;label + ; Date + ;select + =name "interval" + =kaji "scry" + =path "/search/f" + ;option + =value "all" + ; All time + == + ;option + =value "day" + :: =selected "" + ; Past 24h + == + ;option + =value "week" + ; Last week + == + ;option + =value "month" + ; Last month + == + ;option + =value "year" + ; Last year + == + == + == + == + == ++$ pars [=section query=@t tags=(list @t) req=page-req:tp] +++ chat-cursor +|= [query=@t p=chat-page:boke] ^- marl +~ +++ chatp +|= [query=@t r=page-req:tp p=chat-page:boke] ^- marl +?~ p.p + ;+ ;p.xc:"No results for {(trip query)} on Bloody Shovel Chats" +=/ contacts (get-contacts:cnt bowl) + %+ welp + ;* %+ turn p.p |= ref=reference:tlonc + (chat-result ref contacts) + ;* (chat-cursor query p) + +++ tp-page +|= [=pars p=search-page:boke] ^- marl +?~ res.p ~ + :: ;+ ;p:"No results for {(trip query.pars)} under section {(trip section.pars)}" +=/ contacts (get-contacts:cnt bowl) +?- section.pars + %blog %+ welp + ;* %+ turn res.p |= [fn=full-node:tp snip=@t] + (blog-result fn snip) + ;* (cursor pars older.p .n) + %comments %+ welp + ;* %+ turn res.p |= [fn=full-node:tp snip=@t] + (comment-result fn snip contacts) + ;* (cursor pars older.p .n) + %threads %+ welp + ;* %+ turn res.p |= [fn=full-node:tp snip=@t] + (thread-result fn snip contacts) + ;* (cursor pars older.p .n) + + %replies %+ welp + ;* %+ turn res.p |= [fn=full-node:tp snip=@t] + (reply-result fn snip contacts) + ;* (cursor pars older.p .n) + %chat ~ +== + +++ init ^- manx +;div#search.fsy + ;style: {css} + ;+ (form [%blog '' ~ [~ ~ search-page-size:const]]) + ;img#spinner-zh.gc@"spinner.svg"(style "display: none;"); + ;div#search-results; + ;script: {script} +== +++ page +|= [=pars res=search-res:boke] ^- manx +;div#search.fsy + ;style: {css} + ;img#spinner-zh.gc@"spinner.svg"(style "display: none;"); + ;+ (form pars) + ;* ?: .=(query.pars '') ;+ ;p:"Not found" ~ + ;+ (results pars res) + ;script: {script} +== +++ results +|= [=pars res=search-res:boke] ^- manx + ;div#search-results + ;* ?: ?=(%chat -.res) + (chatp query.pars req.pars +.res) + (tp-page pars +.res) + == +-- |