Add the search for articles on the index page.

main
KKlochko 1 year ago
parent e464e9d70f
commit 2f82f419d7

@ -46,6 +46,24 @@
(catch js/Error err (js/console.log (ex-cause err))))) (catch js/Error err (js/console.log (ex-cause err)))))
channel) channel)
(defn search-articles-briefly
"Search all articles by titles and contents and returns via channel. It gets and returns the same channel. The content will be brief (<=60 characters)."
[client search channel]
(go
(try
(let [res (<p! (.query client
(str "select id, title, "
"substr(content, 0, 60) content, "
"length(content) content_length, "
"created from articles "
"where title like $1 "
"or content like $1 "
"order by created desc")
(clj->js [(str "%" search "%")])))]
(>! channel (.-rows res)))
(catch js/Error err (js/console.log (ex-cause err)))))
channel)
(defn get-article (defn get-article
"Reads an article with the id and returns via channel. It gets and returns the same channel. Empty collection if not found." "Reads an article with the id and returns via channel. It gets and returns the same channel. Empty collection if not found."
[client id channel] [client id channel]

@ -112,6 +112,23 @@
(res/status 500) (res/status 500)
(res/send (ex-message err)))))))) (res/send (ex-message err))))))))
(defn htmx-search-articles-handler-factory
[client]
(fn [req res]
(let [channel (chan)
search (.-search (.-body req))]
(go
(try
(let [articles (<! (db/search-articles-briefly client search channel))]
(res/status 200)
(.render res "articles_briefly"
(-> {:articles articles
:layout false}
(cljs.core/clj->js))))
(catch js/Error err
(res/status 500)
(res/send (ex-message err))))))))
(defn htmx-create-article-handler-factory (defn htmx-create-article-handler-factory
[client] [client]
(fn [req res] (fn [req res]

@ -70,6 +70,9 @@
(. app get "/admin" (. app get "/admin"
(handlers/admin-panel-handler-factory client)) (handlers/admin-panel-handler-factory client))
(. app post "/htmx/search/articles/"
(handlers/htmx-search-articles-handler-factory client))
(. app post "/htmx/articles/" (. app post "/htmx/articles/"
(handlers/htmx-create-article-handler-factory client)) (handlers/htmx-create-article-handler-factory client))

@ -1,6 +1,9 @@
<main class="bg-white dark:bg-gray-800 py-4 grow"> <main class="bg-white dark:bg-gray-800 py-4 grow">
<h1 class="mb-4 text-5xl tracking-tight font-extrabold text-gray-900 dark:text-white text-center">Articles</h1> <h1 class="mb-4 text-5xl tracking-tight font-extrabold text-gray-900 dark:text-white text-center">Articles</h1>
{{> search_articles }}
<div id="articles">
{{#each articles as |article|}} {{#each articles as |article|}}
{{> article_briefly article=article }} {{> article_briefly article=article }}
@ -8,4 +11,5 @@
<hr class="w-48 h-1 mx-auto my-4 bg-gray-100 border-0 rounded md:my-10 dark:bg-gray-700"> <hr class="w-48 h-1 mx-auto my-4 bg-gray-100 border-0 rounded md:my-10 dark:bg-gray-700">
{{/unless}} {{/unless}}
{{/each}} {{/each}}
</div>
</main> </main>

@ -0,0 +1,9 @@
<div id="articles">
{{#each articles as |article|}}
{{> article_briefly article=article }}
{{#unless @last}}
<hr class="w-48 h-1 mx-auto my-4 bg-gray-100 border-0 rounded md:my-10 dark:bg-gray-700">
{{/unless}}
{{/each}}
</div>

@ -0,0 +1,19 @@
<form class="max-w-md mx-auto" method="POST">
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
<div class="relative">
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
</svg>
</div>
<input type="search"
id="search"
name="search"
hx-post="/htmx/search/articles/"
hx-trigger="input changed delay:500ms, search"
hx-target="#articles"
hx-swap="outerHTML"
class="block w-full p-4 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Search articles by title or content" required />
</div>
</form>
Loading…
Cancel
Save