diff options
Diffstat (limited to 'bin/serve.fnl')
| -rw-r--r-- | bin/serve.fnl | 206 |
1 files changed, 115 insertions, 91 deletions
diff --git a/bin/serve.fnl b/bin/serve.fnl index b1863e0..420100e 100644 --- a/bin/serve.fnl +++ b/bin/serve.fnl @@ -53,16 +53,6 @@ (str.trim (input:gsub "[=()<>']" "") " ") nil)) -(fn category-menu-path [category] - (. {"Красный чай" "red-tea" - "Шен пуэр" "sheng-puer" - "Шу пуэр" "shou-puer" - "Улун" "oolong" - "Зеленый чай" "green-tea" - "Белый чай" "white-tea" - "Желтый чай" "yellow-tea" - "Посуда" "teaware"} category)) - (fn query-string [query key] (if (and query (. query key) @@ -85,10 +75,11 @@ (values k (array.join (map (fn [_ vv] (.. k "=" vv)) v) "&")))) (array.join (array.list flattened-object) "&")) -(fn collect-form [params category] +(fn collect-form [params] {:query (or (query-string params "query") "") + :page (or (query-number params "page") 1) :tags (map #(sanitize-input $2) - (filter #(~= "" $2) (or params.tags [category]))) + (filter #(~= "" $2) (or params.tags []))) :site (or (query-string params "site") "") :sort (or (query-string params "sort") "") :min-price (query-number params "min-price") @@ -162,15 +153,15 @@ products.price, products.weight, products.price_per AS \"price-per\" - FROM products - INNER JOIN product_tags ON product_tags.product = products.url - WHERE products.archived = false - AND product_tags.tag IN ('Красный чай', 'Улун', 'Шен пуэр', 'Шу пуэр', - 'Зеленый чай', 'Белый чай', 'Желтый чай') - GROUP BY products.url - ORDER BY ROW_NUMBER() over (PARTITION BY site ORDER BY products.ROWID) - LIMIT ? - OFFSET ?" + FROM products + INNER JOIN product_tags ON product_tags.product = products.url + WHERE products.archived = false + AND product_tags.tag IN ('Красный чай', 'Улун', 'Шен пуэр', 'Шу пуэр', + 'Зеленый чай', 'Белый чай', 'Желтый чай') + GROUP BY products.url + ORDER BY ROW_NUMBER() over (PARTITION BY site ORDER BY products.ROWID) + LIMIT ? + OFFSET ?" [limit (% the-number (- total limit))]))) (fn all-tags [] @@ -184,6 +175,20 @@ ORDER BY creation_time" [])))) +(fn shops-count [] + (# (must (luna.db.query db "SELECT DISTINCT site FROM products" [])))) + +(fn products-count [] + (. (must (luna.db.query db "SELECT DISTINCT COUNT(url) FROM products" [])) + 1 1)) + +(fn latest-update-date [] + (. (must + (luna.db.query db + "SELECT creation_time FROM products ORDER BY creation_TIME DESC LIMIT 1" + [])) + 1 1)) + (fn query-products [{: query : tags : min-price : max-price : price-per : site : sort} page] (local tags (or tags [])) @@ -376,7 +381,7 @@ (fn aside-template [form path paginator] [:aside {:class "aside"} [:div {:class "aside-content"} - (if (not (form-empty? form)) + (if (or (not (form-empty? form)) (~= path "/")) [:a {:href "/" :style "display: block;"} [:img {:class "logo" :src "/static/logo.svg" :alt "Логотип everytea.ru" :title "Логотип everytea.ru"}]] @@ -426,19 +431,24 @@ :selected (if (= form.sort "expensive-first") "selected" nil)} "Сначала дороже"]]] [:button {:type :submit} "Искать"]] - paginator]]) - -(fn base-template [form path page total items text] - (local menu-path - (if (and form.tags (< 0 (# form.tags))) - (category-menu-path (. form.tags 1)) - nil)) - (local spellfix-suggestion - (if (and (not (str.empty? form.query)) items (= 0 (# items))) - (cache.wrap - db (.. "spellfix:" form.query) - #(spellfix.guess form.query)) - nil)) + (if paginator "")]]) + +(fn home-template [] + [:div {} + [:article {:class "description"} + [:h1 {} "Добро пожаловать!"] + [:div {:class "description-text text"} + [:p {} [:NO-ESCAPE + (string.format texts.home-text + (shops-count) + (products-count) + (latest-update-date))]]]] + (comment [:section {} + [:h2 {} "Чаи дня"] + [:div {:class "list"} + (table.unpack (map #(item-template $2) (teas-of-the-day 10)))]])]) + +(fn base-template [form path content aside-content] [:html {:lang "ru-RU"} [:head {} [:meta {:charset "utf-8"}] @@ -457,76 +467,90 @@ [:body {} [:div {:class "container"} [:div {:class "content"} - (aside-template form path (paginator-template form page 48 total 7)) + (aside-template form path aside-content) [:main {} (menu-template path) - [:article {:class "description"} - (if (. form.tags 1) - [:h1 {} (. form.tags 1)] - "") - (if (and menu-path (. texts (.. menu-path "-description"))) - [:div {:class "description-text text"} - [:NO-ESCAPE (. texts (.. menu-path "-description"))]] - "")] - (if text - [:p {:class "text"} text] - (< 0 (# items)) - [:div {:class "list"} - (table.unpack (map #(item-template $2) items))] - [:p {:class "text"} - (if spellfix-suggestion - [:NO-ESCAPE - (string.format texts.no-results-with-suggestion - spellfix-suggestion - spellfix-suggestion)] - [:NO-ESCAPE texts.no-results])]) - [:div {} (paginator-template form page 48 total 17)] + content [:footer {} [:small {:class "text"} [:NO-ESCAPE texts.footer-text]]]]]]]]) (fn root-handler [{: path : query}] (local cache-key (.. "page:" path "?" (serialize-query query))) (local cached (cache.get db cache-key)) + + (fn render-listing [form category] + (local headers {:content-type "text/html"}) + (when category (table.insert form.tags category)) + + (local {: results : total} (query-products form form.page)) + (local spellfix-suggestion + (if (and (not (str.empty? form.query)) results (= 0 (# results))) + (cache.wrap + db (.. "spellfix:" form.query) + #(spellfix.guess form.query)) + nil)) + + (local description-key (.. (str.trim path "/") "-description")) + (local page + (base-template form path + [:div {} + (if (and (. form.tags 1) (. texts description-key)) + [:article {:class "description"} + [:h1 {} (. form.tags 1)] + [:div {:class "description-text text"} + [:NO-ESCAPE (. texts description-key)]]] + "") + (if (< 0 (# results)) + [:div {:class "list"} + (table.unpack (map #(item-template $2) results))] + [:p {:class "text"} + (if spellfix-suggestion + [:NO-ESCAPE + (string.format texts.no-results-with-suggestion + spellfix-suggestion + spellfix-suggestion)] + [:NO-ESCAPE texts.no-results])]) + [:div {} (paginator-template form form.page 48 total 17)]] + ;; aside + (paginator-template form form.page 48 total 7))) + + (values + 200 headers + (cache.set db cache-key + (.. "<!DOCTYPE html>\n" (html.render page true))))) + + ;; TODO: if !dev && cached (if cached (values 200 {:content-type "text/html"} cached) (do - (fn respond [query category] - (let [headers {:content-type "text/html"} - page (or (query-number query "page") 1) - form (collect-form query category) - {: results : total} - (if (not (form-empty? form)) - (query-products form page) - {:total 10 :results (teas-of-the-day 10)})] - (values - 200 headers - (cache.set db cache-key - (.. "<!DOCTYPE html>\n" - (html.render - (base-template form path page total results) - true)))))) - - (match (str.split path "/") - ["red-tea"] (respond query "Красный чай") - ["sheng-puer"] (respond query "Шен пуэр") - ["shou-puer"] (respond query "Шу пуэр") - ["oolong"] (respond query "Улун") - ["green-tea"] (respond query "Зеленый чай") - ["white-tea"] (respond query "Белый чай") - ["yellow-tea"] (respond query "Желтый чай") - ["teaware"] (respond query "Посуда") - (where t (= 0 (# t))) (respond query) - _ (values - 404 {:content-type "text/html"} + (local form (collect-form query)) + (match (str.split path "/") + ["red-tea"] (render-listing form "Красный чай") + ["sheng-puer"] (render-listing form "Шен пуэр") + ["shou-puer"] (render-listing form "Шу пуэр") + ["oolong"] (render-listing form "Улун") + ["green-tea"] (render-listing form "Зеленый чай") + ["white-tea"] (render-listing form "Белый чай") + ["yellow-tea"] (render-listing form "Желтый чай") + ["teaware"] (render-listing form "Посуда") + (where t (= 0 (# t))) + (if (form-empty? form) + (values + 200 {:content-type "text/html"} (.. "<!DOCTYPE html>\n" - (html.render - (base-template - (collect-form query nil) - "" 1 0 [] "Страница не найдена!") - true))))))) + (html.render (base-template form path (home-template)) + true))) + (render-listing form)) + _ (values + 404 {:content-type "text/html"} + (.. "<!DOCTYPE html>\n" + (html.render + (base-template form path [:div {} "Страница не найдена!"]) + true))))))) (fn robots-handler [] - (values 200 {:content-type "text/plain"} "User-agent: *\nAllow: /")) + (values 200 {:content-type "text/plain"} + "User-agent: *\nAllow: /")) (must (luna.router.route "GET /" root-handler)) (must (luna.router.route "GET /robots.txt" robots-handler)) |
