diff options
author | Tim <contact@bytim.eu> | 2025-06-14 11:49:28 +0200 |
---|---|---|
committer | Tim <contact@bytim.eu> | 2025-06-14 11:49:28 +0200 |
commit | 8e23d9dade945f87f5fc7fb15042a53a7eeb9a9e (patch) | |
tree | c0f5b6587b6f9f0b591b395c69ad7da08717a30b /src | |
parent | 229299146376a2b847f4fe3f331efbd26c0abc70 (diff) | |
download | chef-8e23d9dade945f87f5fc7fb15042a53a7eeb9a9e.tar.xz chef-8e23d9dade945f87f5fc7fb15042a53a7eeb9a9e.zip |
Refactor project structure
Diffstat (limited to 'src')
-rw-r--r-- | src/chef/api/admin/category.clj | 35 | ||||
-rw-r--r-- | src/chef/api/admin/recipe.clj | 45 | ||||
-rw-r--r-- | src/chef/components/search.clj | 49 | ||||
-rw-r--r-- | src/chef/frontend/admin.clj (renamed from src/chef/pages/admin.clj) | 55 | ||||
-rw-r--r-- | src/chef/frontend/admin/recipe_editor.clj (renamed from src/chef/pages/admin/recipe_editor.clj) | 30 | ||||
-rw-r--r-- | src/chef/frontend/visitor/home.clj (renamed from src/chef/pages/home.clj) | 28 | ||||
-rw-r--r-- | src/chef/frontend/visitor/recipe.clj (renamed from src/chef/pages/recipe.clj) | 46 | ||||
-rw-r--r-- | src/chef/frontend/visitor/recipe/thumbnail.clj | 10 | ||||
-rw-r--r-- | src/chef/frontend/visitor/search.clj | 38 | ||||
-rw-r--r-- | src/chef/logic/categories.clj | 72 | ||||
-rw-r--r-- | src/chef/logic/recipes.clj | 60 | ||||
-rw-r--r-- | src/chef/pages/admin/api.clj | 126 | ||||
-rw-r--r-- | src/chef/routes.clj | 56 | ||||
-rw-r--r-- | src/chef/utils.clj | 37 |
14 files changed, 347 insertions, 340 deletions
diff --git a/src/chef/api/admin/category.clj b/src/chef/api/admin/category.clj new file mode 100644 index 0000000..2d11510 --- /dev/null +++ b/src/chef/api/admin/category.clj @@ -0,0 +1,35 @@ +(ns chef.api.admin.category + (:require [chef.utils :as cutils] + [chef.logic.categories :as clcategories] + [ring.util.response :as ruresp])) + +;; POST / +(defn handle-edit [req] + (cutils/auth-only req + (if-let [id (cutils/s->int-or-nil (get-in req [:path-params :id]))] + (do (clcategories/update-category! id (merge {} + (when-let [name (get-in req [:params "name"])] + {:name name}) + (when-let [question (get-in req [:params "question"])] + {:question question}))) + (ruresp/response "Updated.")) + (ruresp/bad-request "Bad request.")))) + +;; DELETE / +(defn handle-delete [req] + (cutils/auth-only req + (let [id (cutils/s->int-or-nil (get-in req [:path-params :id]))] + (if (and (some? id) + (not= id -1)) + (do (clcategories/delete-category-and-children! id) + (-> (ruresp/response "Deleted.") + (ruresp/header "HX-Refresh" "true"))) + (ruresp/bad-request "Bad request."))))) + +;; POST /create +(defn handle-create [req] + (cutils/auth-only req + (clcategories/create-category! (or (get-in req [:params "parent"]) + -1)) + (-> (ruresp/created "Created.") + (ruresp/header "HX-Refresh" "true")))) diff --git a/src/chef/api/admin/recipe.clj b/src/chef/api/admin/recipe.clj new file mode 100644 index 0000000..c69ade5 --- /dev/null +++ b/src/chef/api/admin/recipe.clj @@ -0,0 +1,45 @@ +(ns chef.api.admin.recipe + (:require [chef.utils :as cutils] + [chef.logic.recipes :as clrecipes] + [ring.util.response :as ruresp])) + +;; POST / +(defn handle-edit [req] + (cutils/auth-only req + (let [id (cutils/s->int-or-nil (get-in req [:path-params :id])) + ingredients (get-in req [:params "ingredients"])] + (if (and (some? id) + (cutils/valid-ingredients? ingredients)) + (do (when-let [thumbnail (get-in req [:params "thumbnail"])] + (clrecipes/set-recipe-thumbnail! id thumbnail)) + (clrecipes/update-recipe! id {:title (get-in req [:params "title"]) + :category (get-in req [:params "category"]) + :unit (get-in req [:params "ingredients-unit"]) + :ingredients ingredients + :preparation (get-in req [:params "preparation"])}) + (ruresp/response "Saved.")) + (ruresp/bad-request "Bad request."))))) + +;; DELETE / +(defn handle-delete [req] + (cutils/auth-only req + (if-let [id (cutils/s->int-or-nil (get-in req [:path-params :id]))] + (do (clrecipes/delete-recipe! id) + (-> (ruresp/response "Deleted.") + (ruresp/header "HX-Refresh" "true"))) + (ruresp/bad-request "Bad request.")))) + +;; POST /create +(defn handle-create [req] + (cutils/auth-only req + (clrecipes/create-recipe!) + (-> (ruresp/created "Created.") + (ruresp/header "HX-Refresh" "true")))) + +;; DELETE /thumbnail +(defn handle-delete-thumbnail [req] + (cutils/auth-only req + (if-let [id (cutils/s->int-or-nil (get-in req [:path-params :id]))] + (do (clrecipes/remove-recipe-thumbnail! id) + (ruresp/response "Done.")) + (ruresp/bad-request "Bad request.")))) diff --git a/src/chef/components/search.clj b/src/chef/components/search.clj deleted file mode 100644 index e428a23..0000000 --- a/src/chef/components/search.clj +++ /dev/null @@ -1,49 +0,0 @@ -(ns chef.components.search - (:require [chef.database :as cdb] - [chef.utils :as cutils] - [clojure.string :as cstr] - [hiccup2.core :as html] - [honey.sql :as sql] - [next.jdbc :as jdbc] - [ring.util.response :as ruresp])) - -(defn render [query category] - [:table - [:tr - [:th "Rezept"] - [:th "Kategorie"]] - (for [recipe (jdbc/execute! @cdb/db - (sql/format {:select [:*] - :from [:recipes]})) - :let [recipe-category (->> {:select [:*] - :from [:categories] - :where [:= :id (:recipes/category recipe)]} - sql/format - (jdbc/execute! @cdb/db) - first)]] - (when (or (= category -1) - (and (cstr/includes? (-> recipe - :recipes/title - cstr/lower-case) - query) - (some #(= (:categories/id %) category) - (cutils/category-parents recipe-category)))) - [:tr - [:td - [:b [:a {:href (str "/recipes/" (:recipes/id recipe))} (:recipes/title recipe)]]] - [:td - (cutils/category-path (->> {:select [:*] - :from [:categories] - :where [:= :id (:recipes/category recipe)]} - sql/format - (jdbc/execute! @cdb/db) - first))]]))]) - -(defn handler [req] - (if-let [query (get-in req [:params "query"])] - (-> (render query (try (Integer/parseInt (get-in req [:params "category"])) - (catch Exception _ -1))) - html/html - str - ruresp/response) - (ruresp/bad-request "No search query provide."))) diff --git a/src/chef/pages/admin.clj b/src/chef/frontend/admin.clj index ea19cc3..89a2462 100644 --- a/src/chef/pages/admin.clj +++ b/src/chef/frontend/admin.clj @@ -1,10 +1,10 @@ -(ns chef.pages.admin +(ns chef.frontend.admin (:require [chef.utils :as cutils] [hiccup2.core :as html] [ring.util.response :as ruresp] - [chef.database :as cdb] - [next.jdbc :as jdbc] - [honey.sql :as sql])) + + [chef.logic.categories :as clcategories] + [chef.logic.recipes :as clrecipes])) (defn- render-category [data children] [:li @@ -13,14 +13,12 @@ [:input {:type :text :placeholder "Name" :value (:categories/name data) :name "name" - :hx-post (str "/api/admin/edit-category/" (:categories/id data)) + :hx-post (str "/api/admin/category/" (:categories/id data)) :hx-trigger "change"}] "Startseite")] (when (or (neg? (:categories/id data)) - (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :parent (:categories/id data)]}) - (jdbc/execute! @cdb/db) + (->> (:categories/id data) + clcategories/find-categories-with-parent count pos?)) (list [:p {:style {:display :inline-block @@ -31,26 +29,25 @@ :width :auto} :value (:categories/question data) :name "question" - :hx-post (str "/api/admin/edit-category/" (:categories/id data)) + :hx-post (str "/api/admin/category/" (:categories/id data)) :hx-trigger "change"}])) [:img {:src "/static/icons/plus.svg" :height "30em" :style {:vertical-align :middle :margin-left "1em"} - :hx-post (str "/api/admin/create-category" + :hx-post (str "/api/admin/category/create/" (when (pos? (:categories/id data)) (str "?parent=" (:categories/id data)))) :hx-swap "none"}] (when (pos? (:categories/id data)) [:img {:src "/static/icons/trash.svg" :height "30em" :style {:vertical-align :middle :margin-left "1em"} - :hx-delete (str "/api/admin/delete-category/" (:categories/id data)) + :hx-delete (str "/api/admin/category/" (:categories/id data)) :hx-swap "none"}]) [:ul (for [child children] - (render-category child (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :parent (:categories/id child)]}) - (jdbc/execute! @cdb/db))))]]) + (->> (:categories/id child) + clcategories/find-categories-with-parent + (render-category child)))]]) (defn- render-recipe-table-row [recipe] (let [tr-id (str "recipe-" (:recipes/id recipe))] @@ -58,12 +55,8 @@ [:td [:p (:recipes/title recipe)]] [:td - (let [category (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :id (:recipes/category recipe)]}) - (jdbc/execute! @cdb/db) - first)] - [:p (cutils/category-path category)])] + (let [category (clcategories/get-category (:recipes/category recipe))] + [:p (clcategories/generate-path category)])] [:td [:div [:button {:class ["button" "primary"] @@ -74,7 +67,7 @@ [:button {:class ["button error"] :hx-trigger "click" :hx-swap :none - :hx-delete (str "/api/admin/delete-recipe/" (:recipes/id recipe))} + :hx-delete (str "/api/admin/recipe/" (:recipes/id recipe))} "Löschen"]]]])) (defn- render [] @@ -83,28 +76,20 @@ [:h1 "chef - Admin"] [:h2 "Kategorien"] [:ul - (render-category (first (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :id -1]}) - (jdbc/execute! @cdb/db))) - (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :parent -1]}) - (jdbc/execute! @cdb/db)))] + (render-category (clcategories/get-category -1) + (clcategories/find-categories-with-parent -1))] [:h2 "Rezepte"] [:table [:tr [:th "Titel"] [:th "Kategorie"] [:th "Aktionen"]] - (for [recipe (jdbc/execute! @cdb/db - (sql/format {:select [:*] - :from [:recipes]}))] + (for [recipe (clrecipes/get-all-recipes)] (render-recipe-table-row recipe))] [:button {:class "button primary" :hx-trigger "click" :hx-swap :none - :hx-post "/api/admin/create-recipe"} + :hx-post "/api/admin/recipe/create/"} "Rezept erstellen"]])) (defn handler [req] diff --git a/src/chef/pages/admin/recipe_editor.clj b/src/chef/frontend/admin/recipe_editor.clj index cc30942..69c84ba 100644 --- a/src/chef/pages/admin/recipe_editor.clj +++ b/src/chef/frontend/admin/recipe_editor.clj @@ -1,18 +1,18 @@ -(ns chef.pages.admin.recipe-editor +(ns chef.frontend.admin.recipe-editor (:require [hiccup2.core :as html] [hiccup.util :as hutil] - [honey.sql :as sql] - [next.jdbc :as jdbc] - [chef.database :as cdb] [ring.util.response :as ruresp] - [chef.utils :as cutils])) + [chef.utils :as cutils] + + [chef.logic.categories :as clcategories] + [chef.logic.recipes :as clrecipes])) (defn render [recipe] (cutils/gen-page "chef - Rezept bearbeiten" [:div {:style {:margin-left "1em"}} [:h1 "Rezept bearbeiten"] [:form {:style {:width "50%"} - :hx-post (str "/api/admin/edit-recipe/" (:recipes/id recipe)) + :hx-post (str "/api/admin/recipe/" (:recipes/id recipe)) :hx-swap "none" :enctype "multipart/form-data"} [:input {:type :text :name "title" :placeholder "Titel" @@ -24,18 +24,15 @@ :padding "0.3em"}}]] [:button {:class ["button" "error"] :hx-trigger "click" - :hx-delete (str "/api/admin/delete-thumbnail/" (:recipes/id recipe)) + :hx-delete (str "/api/admin/recipe/" (:recipes/id recipe) "/thumbnail/") :hx-swap :none} "Thumbnail entfernen"] [:h2 "Kategorie"] [:select {:name "category"} - (for [category (->> (sql/format {:select [:*] - :from [:categories]}) - (jdbc/execute! @cdb/db) - (filter #(pos? (:categories/id %))))] + (for [category (clcategories/get-all-categories)] [:option {:value (:categories/id category) :selected (= (:categories/id category) (:recipes/category recipe))} - (cutils/category-path category)])] + (clcategories/generate-path category)])] [:h2 "Zutaten"] [:div {:style {:display :flex}} [:p {:style {:margin-right "0.5em"}} "Pro"] @@ -57,13 +54,8 @@ (defn handler [req] (cutils/auth-only req - (if-let [id (try (Integer/parseInt (get-in req [:path-params :id])) - (catch Exception _ nil))] - (->> (sql/format {:select [:*] - :from [:recipes] - :where [:= :id id]}) - (jdbc/execute! @cdb/db) - first + (if-let [id (cutils/s->int-or-nil (get-in req [:path-params :id]))] + (->> (clrecipes/get-recipe id) render html/html str diff --git a/src/chef/pages/home.clj b/src/chef/frontend/visitor/home.clj index 9bc82fb..6503983 100644 --- a/src/chef/pages/home.clj +++ b/src/chef/frontend/visitor/home.clj @@ -1,38 +1,28 @@ -(ns chef.pages.home - (:require [chef.database :as cdb] - [hiccup2.core :as html] - [honey.sql :as sql] - [next.jdbc :as jdbc] +(ns chef.frontend.visitor.home + (:require [hiccup2.core :as html] [ring.util.response :as ruresp] [chef.utils :as cutils] - [chef.components.search :as ccsearch])) + [chef.frontend.visitor.search :as cfvsearch] + + [chef.logic.categories :as clcategories])) (defn- render [req] (cutils/gen-page "chef" - (let [category (->> {:select [:*] - :from [:categories] - :where [:= :id (or (get-in req [:params "category"]) -1)]} - sql/format - (jdbc/execute! @cdb/db) - first)] + (let [category (clcategories/get-category (or (get-in req [:params "category"]) -1))] [:div {:style {:text-align :center}} [:h1 "chef"] [:h2 "Finde das perfekte Gericht für dich!"] [:b (:categories/question category)] [:div - (for [child-category (->> {:select [:*] - :from [:categories] - :where [:= :parent (:categories/id category)]} - sql/format - (jdbc/execute! @cdb/db))] + (for [child-category (clcategories/find-categories-with-parent (:categories/id category))] [:div [:button {:style {:margin-bottom "1em"} :onclick (str "window.location = \"/?category=" (:categories/id child-category) "\"")} (:categories/name child-category)] [:br]])] (when (pos? (:categories/id category)) - [:h3 (cutils/category-path category)]) + [:h3 (clcategories/generate-path category)]) [:input {:type :text :style {:width "90%" :margin :auto} :placeholder "Suche" @@ -41,7 +31,7 @@ :hx-swap "innerHTML" :hx-target "#search-results"}] [:div {:id "search-results"} - (ccsearch/render "" (:categories/id category))]]))) + (cfvsearch/render "" (:categories/id category))]]))) (defn handler [req] (-> req diff --git a/src/chef/pages/recipe.clj b/src/chef/frontend/visitor/recipe.clj index be88b2d..e3dbf97 100644 --- a/src/chef/pages/recipe.clj +++ b/src/chef/frontend/visitor/recipe.clj @@ -1,12 +1,11 @@ -(ns chef.pages.recipe - (:require [chef.database :as cdb] - [chef.utils :as cutils] +(ns chef.frontend.visitor.recipe + (:require [chef.utils :as cutils] [clojure.string :as cstr] [hiccup2.core :as html] - [honey.sql :as sql] - [next.jdbc :as jdbc] - [ring.util.response :as ruresp]) - (:import java.io.File)) + [ring.util.response :as ruresp] + + [chef.logic.recipes :as clrecipes] + [chef.logic.categories :as clcategories])) (defn- render [portions recipe] (cutils/gen-page (str "chef - " (:recipes/title recipe)) @@ -15,13 +14,10 @@ [:h1 {:style {:display :inline-block :margin-right "0.5em"}} (:recipes/title recipe)] - [:i (str "(" (cutils/category-path (->> {:select [:*] - :from [:categories] - :where [:= :id (:recipes/category recipe)]} - sql/format - (jdbc/execute! @cdb/db) - first)) ")")]] - (when (some? (cutils/get-thumbnail-file recipe)) + [:i (str "(" (-> (:recipes/category recipe) + clcategories/get-category + clcategories/generate-path) ")")]] + (when (some? (clrecipes/get-recipe-thumbnail (:recipes/id recipe))) [:img {:src (str "/recipes/" (:recipes/id recipe) "/thumbnail") :width "50%"}]) [:h2 @@ -51,27 +47,9 @@ [:p %])))])) (defn handler [req] - (->> {:select [:*] - :from [:recipes] - :where [:= :id (get-in req [:path-params :id])]} - sql/format - (jdbc/execute! @cdb/db) - first - (render (or (try (Integer/parseInt (get-in req [:params "portions"])) - (catch Exception _ nil)) + (->> (clrecipes/get-recipe (get-in req [:path-params :id])) + (render (or (cutils/s->int-or-nil (get-in req [:params "portions"])) 1)) html/html str ruresp/response)) - -(defn thumbnail-handler [req] - (if-let [id (get-in req [:path-params :id])] - (when-let [thumbnail-file (->> {:select [:*] - :from [:recipes] - :where [:= :id id]} - sql/format - (jdbc/execute! @cdb/db) - first - cutils/get-thumbnail-file)] - (ruresp/file-response (.getPath ^File thumbnail-file))) - (ruresp/bad-request "Bad request."))) diff --git a/src/chef/frontend/visitor/recipe/thumbnail.clj b/src/chef/frontend/visitor/recipe/thumbnail.clj new file mode 100644 index 0000000..c14f491 --- /dev/null +++ b/src/chef/frontend/visitor/recipe/thumbnail.clj @@ -0,0 +1,10 @@ +(ns chef.frontend.visitor.recipe.thumbnail + (:require [ring.util.response :as ruresp] + [chef.logic.recipes :as clrecipes]) + (:import java.io.File)) + +(defn handler [req] + (if-let [id (get-in req [:path-params :id])] + (when-let [thumbnail-file (clrecipes/get-recipe-thumbnail id)] + (ruresp/file-response (.getPath ^File thumbnail-file))) + (ruresp/bad-request "Bad request."))) diff --git a/src/chef/frontend/visitor/search.clj b/src/chef/frontend/visitor/search.clj new file mode 100644 index 0000000..7a2db93 --- /dev/null +++ b/src/chef/frontend/visitor/search.clj @@ -0,0 +1,38 @@ +(ns chef.frontend.visitor.search + (:require [chef.utils :as cutils] + [clojure.string :as cstr] + [hiccup2.core :as html] + [ring.util.response :as ruresp] + + [chef.logic.categories :as clcategories] + [chef.logic.recipes :as clrecipes])) + +(defn render [query category] + [:table + [:tr + [:th "Rezept"] + [:th "Kategorie"]] + (for [recipe (clrecipes/get-all-recipes) + :let [recipe-category (clcategories/get-category (:recipes/category recipe))]] + (when (or (= category -1) + (and (cstr/includes? (-> recipe + :recipes/title + cstr/lower-case) + query) + (some #(= (:categories/id %) category) + (clcategories/get-parents recipe-category)))) + [:tr + [:td + [:b [:a {:href (str "/recipes/" (:recipes/id recipe))} (:recipes/title recipe)]]] + [:td + (-> (:recipes/category recipe) + clcategories/get-category + clcategories/generate-path)]]))]) + +(defn handler [req] + (if-let [query (get-in req [:params "query"])] + (-> (render query (or (cutils/s->int-or-nil (get-in req [:params "category"])) -1)) + html/html + str + ruresp/response) + (ruresp/bad-request "No search query provide."))) diff --git a/src/chef/logic/categories.clj b/src/chef/logic/categories.clj new file mode 100644 index 0000000..aa9931e --- /dev/null +++ b/src/chef/logic/categories.clj @@ -0,0 +1,72 @@ +(ns chef.logic.categories + (:require [clojure.string :as cstr] + [honey.sql :as sql] + [next.jdbc :as jdbc] + [chef.database :as cdb])) + +(defn get-all-categories [] + (->> {:select [:*] + :from [:categories]} + sql/format + (jdbc/execute! @cdb/db) + (filter #(pos? (:categories/id %))) ; Filter out root category + )) + +(defn get-category [id] + (->> {:select [:*] + :from [:categories] + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db) + first)) + +(defn find-categories-with-parent [parent-id] + (->> {:select [:*] + :from [:categories] + :where [:= :parent parent-id]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn create-category! [parent] + (->> {:insert-into [:categories] + :values [{:name "New category" + :parent parent}]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn- delete-category! [id] + (->> {:delete-from [:categories] + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn- delete-category-children! [id] + (doseq [child (find-categories-with-parent id)] + (delete-category! (:categories/id child)) + (delete-category-children! (:categories/id child)))) + +(defn delete-category-and-children! [id] + (delete-category! id) + (delete-category-children! id)) + +(defn update-category! [id updates] + (->> {:update :categories + :set updates + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn get-parents [category] + (loop [parents (list) + category category] + (let [updated-parents (conj parents category)] + (if (not= -1 (:categories/parent category)) + (recur updated-parents + (get-category (:categories/parent category))) + updated-parents)))) + +(defn generate-path [category] + (->> category + get-parents + (map #(:categories/name %)) + (cstr/join " > "))) diff --git a/src/chef/logic/recipes.clj b/src/chef/logic/recipes.clj new file mode 100644 index 0000000..1fd1db5 --- /dev/null +++ b/src/chef/logic/recipes.clj @@ -0,0 +1,60 @@ +(ns chef.logic.recipes + (:require [clojure.java.io :as cjio] + [clojure.string :as cstr] + [honey.sql :as sql] + [next.jdbc :as jdbc] + [chef.database :as cdb]) + (:import java.io.File)) + +(defn get-all-recipes [] + (->> {:select [:*] + :from [:recipes]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn get-recipe [id] + (->> {:select [:*] + :from [:recipes] + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db) + first)) + +(defn create-recipe! [] + (->> {:insert-into [:recipes] + :values [{:title "New recipe"}]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn delete-recipe! [id] + (->> {:delete-from [:recipes] + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn update-recipe! [id updates] + (->> {:update :recipes + :set updates + :where [:= :id id]} + sql/format + (jdbc/execute! @cdb/db))) + +(defn get-recipe-thumbnail [recipe-id] + (let [thumbnails-folder (File. "./thumbnails/")] + (->> thumbnails-folder + .listFiles + (filter #(cstr/starts-with? (.getName ^File %) + (str recipe-id "."))) + first))) + +(defn remove-recipe-thumbnail! [id] + (when-let [file (get-recipe-thumbnail id)] + (.delete ^File file))) + +(defn set-recipe-thumbnail! [id multipart-param] + (when-let [existing-thumbnail-file (get-recipe-thumbnail id)] + (.delete ^File existing-thumbnail-file)) + (cjio/copy (:tempfile multipart-param) + (File. (str "./thumbnails/" id "." (-> (:filename multipart-param) + (cstr/split #"\.") + last))))) diff --git a/src/chef/pages/admin/api.clj b/src/chef/pages/admin/api.clj deleted file mode 100644 index 1119607..0000000 --- a/src/chef/pages/admin/api.clj +++ /dev/null @@ -1,126 +0,0 @@ -(ns chef.pages.admin.api - (:require [chef.utils :as cutils] - [chef.database :as cdb] - [clojure.string :as cstr] - [next.jdbc :as jdbc] - [honey.sql :as sql] - [ring.util.response :as ruresp] - [clojure.java.io :as cjio]) - (:import java.io.File)) - -(defn create-category [req] - (cutils/auth-only req - (jdbc/execute! @cdb/db - (sql/format {:insert-into [:categories] - :values [(merge {:name "New category" - :parent (or (get-in req [:params "parent"]) - -1)})]})) - (-> (ruresp/created "Created.") - (ruresp/header "HX-Refresh" "true")))) - -(defn- delete-category-children! [id] - (let [children (->> (sql/format {:select [:*] - :from [:categories] - :where [:= :parent id]}) - (jdbc/execute! @cdb/db) - (map #(:categories/id %)))] - (doseq [child children] - (jdbc/execute! @cdb/db - (sql/format {:delete-from [:categories] - :where [:= :id child]})) - (delete-category-children! child)))) - -(defn delete-category [req] - (cutils/auth-only req - (if-let [id (try (Integer/parseInt (get-in req [:path-params :id])) - (catch Exception _ nil))] - (when (not= id -1) - (do (jdbc/execute! @cdb/db - (sql/format {:delete-from [:categories] - :where [:= :id id]})) - (delete-category-children! id) - (-> (ruresp/response "Deleted.") - (ruresp/header "HX-Refresh" "true")))) - (ruresp/bad-request "Bad request.")))) - -(defn edit-category [req] - (cutils/auth-only req - (if-let [id (try (Integer/parseInt (get-in req [:path-params :id])) - (catch Exception _ nil))] - (do (when-let [name (get-in req [:params "name"])] - (jdbc/execute! @cdb/db (sql/format {:update :categories - :set {:name name} - :where [:= :id id]}))) - (when-let [question (get-in req [:params "question"])] - (jdbc/execute! @cdb/db (sql/format {:update :categories - :set {:question question} - :where [:= :id id]}))) - (ruresp/response "Updated.")) - (ruresp/bad-request "Bad request.")))) - -(defn create-recipe [req] - (cutils/auth-only req - (jdbc/execute! @cdb/db - (sql/format {:insert-into [:recipes] - :values [{:title "New recipe"}]})) - (-> (ruresp/created "Created.") - (ruresp/header "HX-Refresh" "true")))) - -(defn delete-recipe [req] - (cutils/auth-only req - (if-let [id (try (Integer/parseInt (get-in req [:path-params :id])) - (catch Exception _ nil))] - (do (jdbc/execute! @cdb/db - (sql/format {:delete-from [:recipes] - :where [:= :id id]})) - (-> (ruresp/response "Deleted.") - (ruresp/header "HX-Refresh" "true"))) - (ruresp/bad-request "Bad request.")))) - -(defn edit-recipe [req] - (cutils/auth-only req - (let [id (try (Integer/parseInt (get-in req [:path-params :id])) - (catch Exception _ nil)) - ingredients (get-in req [:params "ingredients"])] - (if (and (some? id) - (cutils/valid-ingredients? ingredients)) - (do (when-let [thumbnail (get-in req [:params "thumbnail"])] - (when-let [existing-thumbnail-file (->> {:select [:*] - :from [:recipes] - :where [:= :id id]} - sql/format - (jdbc/execute! @cdb/db) - first - cutils/get-thumbnail-file)] - (.delete ^File existing-thumbnail-file)) - (cjio/copy (:tempfile thumbnail) - (File. (str "./thumbnails/" id "." - (-> thumbnail - :filename - (cstr/split #"\.") - last))))) - (jdbc/execute! @cdb/db - (sql/format {:update :recipes - :set {:title (get-in req [:params "title"]) - :category (get-in req [:params "category"]) - |