/- 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, `$1`) 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) == --