diff --git a/src/clj/auto_ap/datomic/migrate/add_client_codes.clj b/src/clj/auto_ap/datomic/migrate/add_client_codes.clj index 0f41cdaf..aa569463 100644 --- a/src/clj/auto_ap/datomic/migrate/add_client_codes.clj +++ b/src/clj/auto_ap/datomic/migrate/add_client_codes.clj @@ -38,8 +38,7 @@ :where ['[?e :client/name ?name]]} :args [(d/db a)]}) (reduce (fn [result [name id]] - (conj result [:db/add id :client/code (name->code name)])) - []) - - - )]) + (if (name->code name) + (conj result [:db/add id :client/code (name->code name)]) + result)) + []))]) diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 7c7b72c7..b5d6b032 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -256,6 +256,7 @@ :edit_client {:fields {:id {:type :id} :name {:type 'String} + :code {:type 'String} :email {:type 'String} :address {:type :add_address} :locations {:type '(list String)} diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index 577d9b98..1b44ec34 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -2,7 +2,8 @@ (:require [auto-ap.datomic.clients :as d-clients] [datomic.api :as d] [auto-ap.datomic :refer [uri remove-nils]] - [auto-ap.graphql.utils :refer [->graphql assert-admin can-see-client?]])) + [auto-ap.graphql.utils :refer [->graphql assert-admin can-see-client?]] + [clojure.string :as str])) #_(def role->datomic-role {":none" :user-role/none ":admin" :user-role/admin @@ -10,18 +11,19 @@ (defn edit-client [context {:keys [edit_client new_bank_accounts] :as args} value] (assert-admin (:id context)) - (println (:address edit_client)) + (let [client (d-clients/get-by-id (:id edit_client)) #_#_new-clients (set (map #(Long/parseLong %) (:clients edit_user))) #_#_clients-to-remove (->> (:user/clients user) (map :db/id) (filter #(not (new-clients %)) ))] - (println edit_client) - @(d/transact (d/connect uri) (doto (-> [(remove-nils {:db/id (:db/id client) + :client/code (if (str/blank? (:client/code client)) + (:code edit_client) + (:client/code client)) :client/name (:name edit_client) :client/email (:email edit_client) :client/locations (filter identity (:locations edit_client)) diff --git a/src/cljc/auto_ap/entities/clients.cljc b/src/cljc/auto_ap/entities/clients.cljc index 92599c3c..1b9e3022 100644 --- a/src/cljc/auto_ap/entities/clients.cljc +++ b/src/cljc/auto_ap/entities/clients.cljc @@ -8,6 +8,8 @@ (s/def ::id int) (s/def ::name ::shared/required-identifier) +(s/def ::code (s/and ::shared/required-identifier + #(re-matches #"[A-Z0-9]+" %))) (s/def ::address (s/nilable ::address/address)) (s/def ::location string?) diff --git a/src/cljs/auto_ap/events/admin/clients.cljs b/src/cljs/auto_ap/events/admin/clients.cljs index d437ca83..461b518f 100644 --- a/src/cljs/auto_ap/events/admin/clients.cljs +++ b/src/cljs/auto_ap/events/admin/clients.cljs @@ -28,7 +28,7 @@ :operation/name "EditClient"} :venia/queries [{:query/data [:upsert-client {:client edited-client} - [:id :name] + [:id :name :code] ]}]} :on-success [::save-complete] :on-error [::save-error]}}))) diff --git a/src/cljs/auto_ap/views/pages/admin/clients.cljs b/src/cljs/auto_ap/views/pages/admin/clients.cljs index 9c092d2a..2be74ac8 100644 --- a/src/cljs/auto_ap/views/pages/admin/clients.cljs +++ b/src/cljs/auto_ap/views/pages/admin/clients.cljs @@ -1,7 +1,9 @@ (ns auto-ap.views.pages.admin.clients - (:require-macros [cljs.core.async.macros :refer [go]]) + (:require-macros [cljs.core.async.macros :refer [go]] + [clojure.string :as str]) (:require [re-frame.core :as re-frame] [reagent.core :as reagent] + [clojure.string :as str] [auto-ap.subs :as subs] [auto-ap.events :as events] [auto-ap.entities.clients :as entity] @@ -24,7 +26,7 @@ (re-frame/reg-event-fx ::save (fn [{:keys [db]} _] - (let [edited-client (-> (get-in db [:admin :client]) + (let [edited-client (-> (:client @(re-frame/subscribe [::subs/admin])) (dissoc :location))] {:db (assoc-in db [:admin :client :saving?] true) :graphql @@ -38,7 +40,7 @@ (update :bank-accounts #(into % (map (fn [ba] (dissoc ba :is-new?)) (:new-bank-accounts edited-client)))) (dissoc :new-bank-accounts)) } - [:id :name [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name]]] + [:id :name :code [:address [:street1 :street2 :city :state :zip]] [:bank-accounts [:id :number :check-number :name]]] ]}]} :on-success [::save-complete] :on-error [::save-error]}}))) @@ -46,7 +48,7 @@ (re-frame/reg-event-fx ::save-complete (fn [{:keys [db]} [_ client]] - (println client) + {:dispatch [::events/modal-completed :auto-ap.views.pages.admin.clients/edit] :db (-> db @@ -63,6 +65,7 @@ (re-frame/reg-event-db ::change (fn [db [_ path value]] + (assoc-in db (concat [:admin :client] path) value))) @@ -102,15 +105,159 @@ [:table {:class "table", :style {:width "100%"}} [:thead [:tr - [:th "Name"] - [:th "Email"]]] - [:tbody (for [{:keys [id name email] :as c} @clients] + [:th {:style {:width "50%"}} "Name"] + [:th {:style {:width "10%"}} "Name"] + [:th {:style {:width "20%"}} "Locations"] + [:th {:style {:width "20%"}} "Email"]]] + [:tbody (for [{:keys [id name email code locations] :as c} @clients] ^{:key (str name "-" id )} [:tr {:on-click (fn [] (re-frame/dispatch [::edit id])) :style {"cursor" "pointer"}} [:td name] + [:td code] + [:td (str/join ", " locations)] [:td email]])]])) +(defn clients-modal [] + (let [original-client-code (:code (:client @(re-frame/subscribe [::subs/admin])))] + (fn [] + (let [editing-client (:client @(re-frame/subscribe [::subs/admin]))] + [action-modal {:id ::edit + :title (str "Edit " (:name editing-client)) + :action-text "Save" + :save-event [::save]} + [horizontal-field + [:label.label "Name"] + [:div.control + [bind-field + [:input.input {:type "text" + :field :name + :spec ::entity/name + :event ::change + :subscription editing-client}]]]] + + [horizontal-field + [:label.label "Client code"] + [:div.control + [bind-field + [:input.input {:type "code" + :field :code + :disabled (if (str/blank? original-client-code) + "" + "disabled") + :spec ::entity/code + :event ::change + :subscription editing-client}]]]] + + [horizontal-field + [:label.label "Email"] + [:div.control + [bind-field + [:input.input {:type "email" + :field :email + :spec ::entity/email + :event ::change + :subscription editing-client}]]]] + + [horizontal-field + [:label.label "Locations"] + [:div.control + [:div.field.has-addons + [:p.control + [bind-field + [:input.input {:type "text" + :field :location + :event ::change + :subscription editing-client}]]] + [:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-location])} "Add"]]] + [:ul + (for [location (:locations editing-client)] + ^{:key location} [:li location ])]]] + [:h2.subtitle "Address"] + + + [address-field {:field [:address] + :event ::change + :subscription editing-client}] + [:h2.subtitle "Add account"] + + [horizontal-field + [:label.label "Bank"] + [:div.control + + [bind-field + [:input.input {:placeholder "Bank Name" + :type "text" + :field [:new-account :bank-name] + :event ::change + :subscription editing-client}]]] + [:div.control + + [bind-field + [:input.input {:placeholder "Routing" + :type "text" + :field [:new-account :routing] + :event ::change + :subscription editing-client}]]] + [:div.control + + [bind-field + [:input.input {:placeholder "Code" + :type "text" + :field [:new-account :bank-code] + :event ::change + :subscription editing-client}]]]] + [horizontal-field + [:label.label "Account"] + [:div.control + [bind-field + [:input.input {:placeholder "Nickname" + :type "text" + :field [:new-account :name] + :event ::change + :subscription editing-client}]]] + [:div.control + [bind-field + [:input.input {:placeholder "Acct #" + :type "text" + :field [:new-account :number] + :event ::change + :subscription editing-client}]]] + [:div.control + [bind-field + [:input.input {:placeholder "Check #" + :type "text" + :field [:new-account :check-number] + :event ::change + :subscription editing-client}]]]] + [horizontal-field + [:label.label "Yodlee Account"] + [:div.control + [bind-field + [:input.input {:placeholder "Yodlee Account #" + :type "text" + :field [:new-account :yodlee-account-id] + :event ::change + :subscription editing-client}]]] + [:div.control + [:button.button.is-primary.is-pulled-right {:on-click (dispatch-event [::add-new-bank-account])} "Add"]]] + + + + [:h2.subtitle "Bank Accounts"] + [horizontal-field + nil + [:div.control + [:ul + + (for [{:keys [name number check-number id]} (:bank-accounts editing-client)] + ^{:key id} [:li name]) + (for [[index {:keys [name number check-number]}] (map vector (range) (:new-bank-accounts editing-client))] + ^{:key index} [:li [:strong "* " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account index])} [:span.icon [:i.fa.fa-times]]]])]]] + + (when (:saving? editing-client) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]))) + ) + (defn admin-clients-content [] [:div (let [clients (re-frame/subscribe [::subs/clients]) @@ -119,128 +266,12 @@ [:div [:h1.title "Clients"] [clients-table] + (when editing-client + [clients-modal]) - [action-modal {:id ::edit - :title (str "Edit " (:name editing-client)) - :action-text "Save" - :save-event [::save]} - [horizontal-field - [:label.label "Name"] - [:div.control - [bind-field - [:input.input {:type "text" - :field :name - :spec ::entity/name - :event ::change - :subscription editing-client}]]]] - - [horizontal-field - [:label.label "Email"] - [:div.control - [bind-field - [:input.input {:type "email" - :field :email - :spec ::entity/name - :event ::change - :subscription editing-client}]]]] - - [horizontal-field - [:label.label "Locations"] - [:div.control - [:div.field.has-addons - [:p.control - [bind-field - [:input.input {:type "text" - :field :location - :event ::change - :subscription editing-client}]]] - [:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-location])} "Add"]]] - [:ul - (for [location (:locations editing-client)] - ^{:key location} [:li location ])]]] - [:h2.subtitle "Address"] - - - [address-field {:field [:address] - :event ::change - :subscription editing-client}] - [:h2.subtitle "Add account"] - - [horizontal-field - [:label.label "Bank"] - [:div.control - - [bind-field - [:input.input {:placeholder "Bank Name" - :type "text" - :field [:new-account :bank-name] - :event ::change - :subscription editing-client}]]] - [:div.control - - [bind-field - [:input.input {:placeholder "Routing" - :type "text" - :field [:new-account :routing] - :event ::change - :subscription editing-client}]]] - [:div.control - - [bind-field - [:input.input {:placeholder "Code" - :type "text" - :field [:new-account :bank-code] - :event ::change - :subscription editing-client}]]]] - [horizontal-field - [:label.label "Account"] - [:div.control - [bind-field - [:input.input {:placeholder "Nickname" - :type "text" - :field [:new-account :name] - :event ::change - :subscription editing-client}]]] - [:div.control - [bind-field - [:input.input {:placeholder "Acct #" - :type "text" - :field [:new-account :number] - :event ::change - :subscription editing-client}]]] - [:div.control - [bind-field - [:input.input {:placeholder "Check #" - :type "text" - :field [:new-account :check-number] - :event ::change - :subscription editing-client}]]]] - [horizontal-field - [:label.label "Yodlee Account"] - [:div.control - [bind-field - [:input.input {:placeholder "Yodlee Account #" - :type "text" - :field [:new-account :yodlee-account-id] - :event ::change - :subscription editing-client}]]] - [:div.control - [:button.button.is-primary.is-pulled-right {:on-click (dispatch-event [::add-new-bank-account])} "Add"]]] - - - - [:h2.subtitle "Bank Accounts"] - [horizontal-field - nil - [:div.control - [:ul - - (for [{:keys [name number check-number id]} (:bank-accounts editing-client)] - ^{:key id} [:li name]) - (for [[index {:keys [name number check-number]}] (map vector (range) (:new-bank-accounts editing-client))] - ^{:key index} [:li [:strong "* " name] [:button.button {:on-click (dispatch-event [::remove-new-bank-account index])} [:span.icon [:i.fa.fa-times]]]])]]] - - (when (:saving? editing-client) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])]])]) + ])] + + ) (defn admin-clients-page [] [side-bar-layout {:side-bar [admin-side-bar {}]