diff --git a/migrator/migrations/1522944238-DOWN-add-email-to-customer.sql b/migrator/migrations/1522944238-DOWN-add-email-to-customer.sql new file mode 100644 index 00000000..073a6704 --- /dev/null +++ b/migrator/migrations/1522944238-DOWN-add-email-to-customer.sql @@ -0,0 +1,3 @@ +-- 1522944238 DOWN add-email-to-customer + +ALTER table companies drop column email; diff --git a/migrator/migrations/1522944238-UP-add-email-to-customer.sql b/migrator/migrations/1522944238-UP-add-email-to-customer.sql new file mode 100644 index 00000000..bb7d301d --- /dev/null +++ b/migrator/migrations/1522944238-UP-add-email-to-customer.sql @@ -0,0 +1,2 @@ +-- 1522944238 UP add-email-to-customer +ALTER table companies add column email varchar(255); diff --git a/project.clj b/project.clj index 31945ad8..227edc36 100644 --- a/project.clj +++ b/project.clj @@ -85,5 +85,5 @@ :uberjar-name "auto-ap.jar" - :prep-tasks [["cljsbuild" "once" "min"] "compile"]) + :prep-tasks [ "compile"]) diff --git a/src/clj/auto_ap/db/companies.clj b/src/clj/auto_ap/db/companies.clj index 3728060e..870eda5b 100644 --- a/src/clj/auto_ap/db/companies.clj +++ b/src/clj/auto_ap/db/companies.clj @@ -3,8 +3,21 @@ [auto-ap.db.utils :refer [clj->db db->clj get-conn]] [clojure.edn :as edn])) +(defn merge-data [{:keys [data] :as x}] + (merge x (edn/read-string data))) + +(defn parse [x] + (-> x + (db->clj) + merge-data + )) + + (defn get-all [] (->> (j/query (get-conn) "SELECT * FROM companies") - (map db->clj ) - (map (fn [{:keys [data] :as x}] - (merge x (edn/read-string data)))))) + (map parse) + )) + +(defn upsert [id data] + (j/update! (get-conn) :companies data ["id = ?" (Integer/parseInt id)] ) + (merge-data (first (j/query (get-conn) ["SELECT * FROM companies WHERE id = ?" (Integer/parseInt id)])))) diff --git a/src/clj/auto_ap/handler.clj b/src/clj/auto_ap/handler.clj index 5634d1b7..ae02e73d 100644 --- a/src/clj/auto_ap/handler.clj +++ b/src/clj/auto_ap/handler.clj @@ -103,6 +103,11 @@ :body (pr-str (invoices/get-pending (query-params "company"))) :headers {"Content-Type" "application/edn"}}) + (PUT "/api/companies/:id" {:keys [edn-params] {:keys [id]} :route-params :as r} + {:status 200 + :body (pr-str (companies/upsert id edn-params)) + :headers {"Content-Type" "application/edn"}}) + (POST "/api/invoices" {:keys [edn-params]} (invoices/insert-multi! (:rows edn-params)) {:status 200 diff --git a/src/cljs/auto_ap/events.cljs b/src/cljs/auto_ap/events.cljs index 9dbc4d93..7b2b61f4 100644 --- a/src/cljs/auto_ap/events.cljs +++ b/src/cljs/auto_ap/events.cljs @@ -39,12 +39,44 @@ (re-frame/reg-event-db ::received-companies (fn [db [_ companies]] - (assoc db :companies companies))) + + (assoc db :companies (reduce (fn [companies company] + (assoc companies (:id company) company)) + {} + companies)))) (re-frame/reg-event-db - ::select-company + ::edit-company + (fn [db [_ company-id]] + (assoc-in db [:admin-companies :editing] + (get (:companies db) company-id)))) + +(re-frame/reg-event-fx + ::save-editing-company + (fn [{:keys [db]} _] + (let [edited-company (get-in db [:admin-companies :editing])] + {:db (assoc-in db [:admin-companies :editing :saving?] true) + :http {:method :put + :token (:user db) + :body (pr-str (select-keys edited-company [:name :email :data])) + :headers {"Content-Type" "application/edn"} + :uri (str "/api/companies/" (:id edited-company)) + :on-success [::finish-saving-company]}}))) + +(re-frame/reg-event-db + ::finish-saving-company (fn [db [_ company]] - (assoc-in db [:admin-companies :selected] company))) + (-> db + + (assoc-in [:admin-companies :editing] nil) + (assoc-in [:companies (:id company)] company)))) + +(re-frame/reg-event-db + ::change-editing-company + (fn [db [_ path value]] + (assoc-in db (concat [:admin-companies :editing] path) + value))) + (re-frame/reg-event-db ::swap-company diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index 5bf5a3d1..bee704cc 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -12,7 +12,7 @@ ::companies (fn [db] (when (:user db) - (:companies db)))) + (vals (:companies db))))) (re-frame/reg-sub ::menu @@ -27,10 +27,7 @@ (re-frame/reg-sub ::admin-companies (fn [db] - (assoc - (:admin-companies db) - :selected - (first (filter #(= (:id %) (:selected (:admin-companies db))) (:companies db)))))) + (:admin-companies db))) (re-frame/reg-sub ::user diff --git a/src/cljs/auto_ap/views/pages/admin/companies.cljs b/src/cljs/auto_ap/views/pages/admin/companies.cljs index d63ec7e7..1fdc04d8 100644 --- a/src/cljs/auto_ap/views/pages/admin/companies.cljs +++ b/src/cljs/auto_ap/views/pages/admin/companies.cljs @@ -11,20 +11,18 @@ (defn companies-table [] (let [companies (re-frame/subscribe [::subs/companies]) admin-companies (re-frame/subscribe [::subs/admin-companies]) - selected-company (:selected @admin-companies)] + editing-company (:editing @admin-companies)] [:table {:class "table", :style {:width "100%"}} [:thead [:tr - [:th ""] [:th "Name"] - [:th ""]]] - [:tbody (for [{:keys [id name data] :as c} @companies] + [:th "Email"]]] + [:tbody (for [{:keys [id name email data] :as c} @companies] ^{:key (str name "-" id )} - [:tr {:on-click (fn [] (re-frame/dispatch [::events/select-company id])) + [:tr {:on-click (fn [] (re-frame/dispatch [::events/edit-company id])) :style {"cursor" "pointer"}} - [:td id] [:td name] - [:td [:i.fa.fa-pencil]]])]])) + [:td email]])]])) (defn admin-companies-page [] [:div {:class "inbox-messages"} @@ -33,28 +31,48 @@ [:div.container (let [companies (re-frame/subscribe [::subs/companies]) admin-companies (re-frame/subscribe [::subs/admin-companies]) - selected-company (:selected @admin-companies)] - (if selected-company - [:div - [:h1.title "Companies > " (:name selected-company)] - - [:label {:for "company-name"} "Name"] - [:input#company-name.input {:type "text" :value (:name selected-company)}] + editing-company (:editing @admin-companies)] + + [:div + [:h1.title "Companies"] + [companies-table] + [:a.button.is-primary "New Company"] - [:label {:for "email"} "Email"] - [:input#email.input {:type "email" :value (:email selected-company)}] - [:label {:for "data"} "Data"] - [:input#data.input {:type "text" :value (:data selected-company)}] + (when editing-company + [:div.modal.is-active + [:div.modal-background {:on-click (fn [] (re-frame/dispatch [::events/edit-company nil]))}] + + [:div.modal-card + [:header.modal-card-head + [:p.modal-card-title + (str "Edit " (:name editing-company))] + [:button.delete {:on-click (fn [] (re-frame/dispatch [::events/edit-company nil]))}]] + [:section.modal-card-body + [:label {:for "company-name"} "Name"] + [:input#company-name.input {:type "text" :value (:name editing-company) + :on-change (fn [e] + (re-frame/dispatch [::events/change-editing-company [:name] + (.. e -target -value)]))}] - [:label {:for "check"} "Send invoice reminders?"] - [:input#check.checkbox {:type "checkbox" :value (:send-reminders selected-company)}] - [:div] - - [:a.button {:on-click (fn [] (re-frame/dispatch [::events/select-company nil]))} "Back"] - [:a.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/select-company nil]))} "Save"]] - [:div - [:h1.title "Companies"] - [companies-table] - [:a.button.is-primary "New Company"]]))]]]]) + [:label {:for "email"} "Email"] + [:input#email.input {:type "email" + :value (:email editing-company) + :on-change (fn [e] + (re-frame/dispatch [::events/change-editing-company [:email] + (.. e -target -value)]))}] + [:div.control + [:label {:for "check"} "Send invoice reminders?" + [:input#check.checkbox {:type "checkbox" :value (:send-reminders editing-company)}]]] + + + + (when (:saving? editing-company) [:div.is-overlay {:style {"background-color" "rgba(150,150,150, 0.5)"}}])] + + [:footer.modal-card-foot + [:a.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/save-editing-company]))} + [:span "Save"] + (when (:saving? editing-company) + [:span.icon + [:i.fa.fa-spin.fa-spinner]])]]]])])]]]])