diff --git a/src/clj/auto_ap/routes/checks.clj b/src/clj/auto_ap/routes/checks.clj index 78125b4f..f82ae5ab 100644 --- a/src/clj/auto_ap/routes/checks.clj +++ b/src/clj/auto_ap/routes/checks.clj @@ -162,7 +162,7 @@ :content-type "application/pdf"}) (str "http://" (:data-bucket env) ".s3-website-us-east-1.amazonaws.com/merged-checks/" uuid ".pdf"))) -(defn check-for-invoices [invoices vendor-id vendors company bank-account-id index] +(defn check-for-invoices [invoices vendor-id vendors company bank-account-id index invoice-amounts] (let [uuid (str (UUID/randomUUID)) vendor (vendors vendor-id) bank-account (first (filter #(= (:id %) bank-account-id) (:bank-accounts company))) @@ -170,19 +170,19 @@ memo (str "Invoice #'s: " (str/join ", " (map (fn [i] - (str (:invoice-number i) "(" (:total i) ")")) + (str (:invoice-number i) "(" (invoice-amounts (:id i)) ")")) invoices)))] {:s3-uuid uuid :s3-key (str "checks/" uuid ".pdf") :s3-url (str "http://" (:data-bucket env) ".s3-website-us-east-1.amazonaws.com/checks/" uuid ".pdf") :check-number (+ index (:check-number bank-account)) - :amount (reduce + 0 (map :total invoices)) + :amount (reduce + 0 (map (comp invoice-amounts :id) invoices)) :memo memo :vendor-id (:id vendor) :company-id (:id company) :pdf-data {:vendor vendor :paid-to (:name vendor) - :amount (reduce + 0 (map :total invoices)) + :amount (reduce + 0 (map (comp invoice-amounts :id) invoices)) :check (str (+ index (:check-number bank-account))) :memo memo :date (date->str (local-now)) @@ -201,7 +201,7 @@ invoice-amounts (by :invoice-id :amount invoice-payments) invoices-grouped-by-vendor (group-by :vendor-id invoices) checks (-> (for [[[vendor-id invoices] index] (map vector invoices-grouped-by-vendor (range))] - [invoices (checks/insert! (check-for-invoices invoices vendor-id vendors company bank-account-id index))]) + [invoices (checks/insert! (check-for-invoices invoices vendor-id vendors company bank-account-id index invoice-amounts))]) doall) invoice-checks (invoices-checks/insert-multi! (mapcat diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index 524f1d08..16ddd9c9 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -9,7 +9,8 @@ [cljs-time.format :as format] [goog.string :as gstring])) -;; TODO partial payments +;; TODO graphql schema enforcement +;; TODO postgres constraints for data integrity ;; TODO performance ;; TODO refactor graphql diff --git a/src/cljs/auto_ap/views/components/modal.cljs b/src/cljs/auto_ap/views/components/modal.cljs new file mode 100644 index 00000000..4d734604 --- /dev/null +++ b/src/cljs/auto_ap/views/components/modal.cljs @@ -0,0 +1,18 @@ +(ns auto-ap.views.components.modal + (:require [re-frame.core :as re-frame])) + +(defn modal [{:keys [title foot hide-event]} & body] + [:div.modal.is-active + [:div.modal-background {:on-click (fn [] (re-frame/dispatch hide-event ))}] + + [:div.modal-card + [:header.modal-card-head + [:p.modal-card-title + title] + [:button.delete {:on-click (fn [] (re-frame/dispatch hide-event))}]] + [:section.modal-card-body + body] + + (when foot + [:footer.modal-card-foot + foot])]]) diff --git a/src/cljs/auto_ap/views/pages/admin/companies.cljs b/src/cljs/auto_ap/views/pages/admin/companies.cljs index 7b51e9ae..b6af28d2 100644 --- a/src/cljs/auto_ap/views/pages/admin/companies.cljs +++ b/src/cljs/auto_ap/views/pages/admin/companies.cljs @@ -7,6 +7,7 @@ [auto-ap.entities.companies :as entity] [auto-ap.views.components.address :refer [address-field]] [auto-ap.views.utils :refer [login-url dispatch-value-change bind-field horizontal-field]] + [auto-ap.views.components.modal :refer [modal]] [cljs.reader :as edn] [auto-ap.routes :as routes] [bidi.bidi :as bidi])) @@ -34,58 +35,46 @@ [:h1.title "Companies"] [companies-table] - - (when editing-company - [:div.modal.is-active - [:div.modal-background {:on-click (fn [] (re-frame/dispatch [::events/edit 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 nil]))}]] - [:section.modal-card-body - - [horizontal-field - [:label.label "Name"] - [:div.control - [bind-field - [:input.input {:type "text" - :field :name - :spec ::entity/name - :event ::events/change - :subscription editing-company}]]]] - - [horizontal-field - [:label.label "Email"] - [:div.control - [bind-field - [:input.input {:type "email" - :field :email - :spec ::entity/name - :event ::events/change - :subscription editing-company}]]]] - - [:h2.subtitle "Address"] - - [address-field {:field [:address] + [modal {:title (str "Edit " (:name editing-company)) + :foot [:a.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/save]))} + [:span "Save"] + (when (:saving? editing-company) + [:span.icon + [:i.fa.fa-spin.fa-spinner]])] + :hide-event [::events/edit nil]} + [horizontal-field + [:label.label "Name"] + [:div.control + [bind-field + [:input.input {:type "text" + :field :name + :spec ::entity/name :event ::events/change - :subscription editing-company}] + :subscription editing-company}]]]] - [horizontal-field - [:label.label "Bank Accounts"] - [:div.control - [:ul - (for [{:keys [number check-number id]} (:bank-accounts editing-company)] - ^{:key id} [:li number " - " check-number])]]] - - - (when (:saving? editing-company) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])] - - [:footer.modal-card-foot - [:a.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/save]))} - [:span "Save"] - (when (:saving? editing-company) - [:span.icon - [:i.fa.fa-spin.fa-spinner]])]]]])])]) + [horizontal-field + [:label.label "Email"] + [:div.control + [bind-field + [:input.input {:type "email" + :field :email + :spec ::entity/name + :event ::events/change + :subscription editing-company}]]]] + + [:h2.subtitle "Address"] + + [address-field {:field [:address] + :event ::events/change + :subscription editing-company}] + + [horizontal-field + [:label.label "Bank Accounts"] + [:div.control + [:ul + (for [{:keys [number check-number id]} (:bank-accounts editing-company)] + ^{:key id} [:li number " - " check-number])]]] + + + (when (:saving? editing-company) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])])])]) diff --git a/src/cljs/auto_ap/views/pages/admin/vendors.cljs b/src/cljs/auto_ap/views/pages/admin/vendors.cljs index c3c72a20..a3555a80 100644 --- a/src/cljs/auto_ap/views/pages/admin/vendors.cljs +++ b/src/cljs/auto_ap/views/pages/admin/vendors.cljs @@ -7,6 +7,7 @@ [auto-ap.events.admin.vendors :as events] [auto-ap.entities.vendors :as entity] [auto-ap.views.components.address :refer [address-field]] + [auto-ap.views.components.modal :refer [modal]] [clojure.spec.alpha :as s] [auto-ap.views.utils :refer [login-url dispatch-value-change dispatch-event bind-field horizontal-field]] [cljs.reader :as edn] @@ -55,188 +56,179 @@ (let [editing-vendor (:vendor @(re-frame/subscribe [::subs/admin])) companies-by-id @(re-frame/subscribe [::subs/companies-by-id])] - [:div.modal.is-active - [:div.modal-background {:on-click (fn [] (re-frame/dispatch [::events/edit nil]))}] + [modal {:title [:span (if (:id editing-vendor) + (str "Edit " (or (:name editing-vendor) "")) + (str "Add " (or (:name editing-vendor) ""))) + (when (:error editing-vendor) + [:span.icon.has-text-danger + [:i.fa.fa-exclamation-triangle]])] + :foot [:button.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/save])) + :disabled (when (not (s/valid? ::entity/vendor editing-vendor )) + "disabled")} + [:span "Save"] + (when (:saving? editing-vendor) + [:span.icon + [:i.fa.fa-spin.fa-spinner]])] + :hide-event [::events/edit nil]} - [:div.modal-card - [:header.modal-card-head - [:p.modal-card-title - (if (:id editing-vendor) - (str "Edit " (or (:name editing-vendor) "")) - (str "Add " (or (:name editing-vendor) "")))] - (when (:error editing-vendor) - [:span.icon.has-text-danger - [:i.fa.fa-exclamation-triangle]]) - [:button.delete {:on-click (fn [] (re-frame/dispatch [::events/edit nil]))}]] - [:section.modal-card-body - [horizontal-field - [:label.label "Name"] - [:div.control - [bind-field - [:input.input {:type "text" - :field :name - :spec ::entity/name - :event ::events/change - :subscription editing-vendor}]]]] - - [horizontal-field - [:label.label "Code"] - [:div.control - - [bind-field - [:input.input.is-expanded {:type "text" - :field :code - :spec ::entity/code - :event ::events/change - :subscription editing-vendor}]] - [:p.help "The vendor code is used for invoice parsing. Only one vendor at a time can use a code"]]] - - [:h2.subtitle "Address"] - [address-field {:field [:address] + [horizontal-field + [:label.label "Name"] + [:div.control + [bind-field + [:input.input {:type "text" + :field :name + :spec ::entity/name :event ::events/change - :subscription editing-vendor}] - - - - [:h2.subtitle "Contact"] - [horizontal-field - [:label.label "Primary"] - [:div.control.has-icons-left - [bind-field - [:input.input.is-expanded {:type "text" - :field :primary-contact - :spec ::entity/primary-contact - :event ::events/change - :subscription editing-vendor}]] - [:span.icon.is-small.is-left - [:i.fa.fa-user]]] + :subscription editing-vendor}]]]] + + [horizontal-field + [:label.label "Code"] + [:div.control - [:div.control.has-icons-left - [:span.icon.is-small.is-left - [:i.fa.fa-envelope]] - [bind-field - [:input.input {:type "email" - :field :primary-email - :spec ::entity/primary-email - :event ::events/change - :subscription editing-vendor}]]] + [bind-field + [:input.input.is-expanded {:type "text" + :field :code + :spec ::entity/code + :event ::events/change + :subscription editing-vendor}]] + [:p.help "The vendor code is used for invoice parsing. Only one vendor at a time can use a code"]]] - [:div.control.has-icons-left - [bind-field - [:input.input {:type "phone" - :field :primary-phone - :spec ::entity/primary-phone - :event ::events/change - :subscription editing-vendor}]] - [:span.icon.is-small.is-left - [:i.fa.fa-phone]]]] - - [horizontal-field - [:label.label "Secondary"] - [:div.control.has-icons-left - [bind-field - [:input.input.is-expanded {:type "text" - :field :secondary-contact - :spec ::entity/secondary-contact - :event ::events/change - :subscription editing-vendor}]] - [:span.icon.is-small.is-left - [:i.fa.fa-user]]] - [:div.control.has-icons-left - [:span.icon.is-small.is-left - [:i.fa.fa-envelope]] - [bind-field - [:input.input {:type "email" - :field :secondary-email - :spec ::entity/secondary-email - :event ::events/change - :subscription editing-vendor}]]] - [:div.control.has-icons-left - [bind-field - [:input.input {:type "phone" - :field :secondary-phone - :spec ::entity/secondary-phone - :event ::events/change - :subscription editing-vendor}]] - [:span.icon.is-small.is-left - [:i.fa.fa-phone]]]] - - [horizontal-field - [:label.label "Invoice Reminders"] - [:div.control - [:label.radio - [bind-field - [:input {:type "radio" - :name "schedule" - :value "Weekly" - :field :invoice-reminder-schedule - :spec ::entity/invoice-reminder-schedule - :event ::events/change - :subscription editing-vendor}]] - " Send weekly"] - - [:label.radio - [bind-field - [:input {:type "radio" - :name "schedule" - :value "Never" - :field :invoice-reminder-schedule - :spec ::entity/invoice-reminder-schedule - :event ::events/change - :subscription editing-vendor}]] - " Never"]]] - - - [:h2.subtitle "Clients"] - - [horizontal-field - nil - [:div.control - [:div.select.is-expanded - [bind-field - [:select {:type "select" - :field :new-relationship-company + [:h2.subtitle "Address"] + [address-field {:field [:address] :event ::events/change - :subscription editing-vendor - } - (for [company @(re-frame/subscribe [::subs/companies])] - [:option {:value (:id company)} (:name company)])]]]] - [:div.control - [bind-field - [:input.input {:type "text" - :field :new-relationship-account-number - :subscription editing-vendor - :event ::events/change - :placeholder "Account number"}]]] - [:div.control - [:button.button.is-primary - {:on-click (dispatch-event [::events/add-relationship])} - [:span.icon - [:i.fa.fa-plus]]]]] - [horizontal-field - nil - [:ul - (for [[i r] (map vector (range) (:relationships editing-vendor))] - ^{:key i} - [:li - (:name (companies-by-id (js/parseInt (:company-id r)))) ": " - (:account-number r) - [:a - {:on-click (dispatch-event [::events/remove-relationship i])} - [:span.icon - [:i.fa.fa-times]]]])]] - - - (when (:saving? editing-vendor) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])] - - [:footer.modal-card-foot - [:button.button.is-primary {:on-click (fn [] (re-frame/dispatch [::events/save])) - :disabled (when (not (s/valid? ::entity/vendor editing-vendor )) - "disabled")} - [:span "Save"] - (when (:saving? editing-vendor) - [:span.icon - [:i.fa.fa-spin.fa-spinner]])]]]])) + :subscription editing-vendor}] + + + + [:h2.subtitle "Contact"] + [horizontal-field + [:label.label "Primary"] + [:div.control.has-icons-left + [bind-field + [:input.input.is-expanded {:type "text" + :field :primary-contact + :spec ::entity/primary-contact + :event ::events/change + :subscription editing-vendor}]] + [:span.icon.is-small.is-left + [:i.fa.fa-user]]] + + [:div.control.has-icons-left + [:span.icon.is-small.is-left + [:i.fa.fa-envelope]] + [bind-field + [:input.input {:type "email" + :field :primary-email + :spec ::entity/primary-email + :event ::events/change + :subscription editing-vendor}]]] + + [:div.control.has-icons-left + [bind-field + [:input.input {:type "phone" + :field :primary-phone + :spec ::entity/primary-phone + :event ::events/change + :subscription editing-vendor}]] + [:span.icon.is-small.is-left + [:i.fa.fa-phone]]]] + + [horizontal-field + [:label.label "Secondary"] + [:div.control.has-icons-left + [bind-field + [:input.input.is-expanded {:type "text" + :field :secondary-contact + :spec ::entity/secondary-contact + :event ::events/change + :subscription editing-vendor}]] + [:span.icon.is-small.is-left + [:i.fa.fa-user]]] + [:div.control.has-icons-left + [:span.icon.is-small.is-left + [:i.fa.fa-envelope]] + [bind-field + [:input.input {:type "email" + :field :secondary-email + :spec ::entity/secondary-email + :event ::events/change + :subscription editing-vendor}]]] + [:div.control.has-icons-left + [bind-field + [:input.input {:type "phone" + :field :secondary-phone + :spec ::entity/secondary-phone + :event ::events/change + :subscription editing-vendor}]] + [:span.icon.is-small.is-left + [:i.fa.fa-phone]]]] + + [horizontal-field + [:label.label "Invoice Reminders"] + [:div.control + [:label.radio + [bind-field + [:input {:type "radio" + :name "schedule" + :value "Weekly" + :field :invoice-reminder-schedule + :spec ::entity/invoice-reminder-schedule + :event ::events/change + :subscription editing-vendor}]] + " Send weekly"] + + [:label.radio + [bind-field + [:input {:type "radio" + :name "schedule" + :value "Never" + :field :invoice-reminder-schedule + :spec ::entity/invoice-reminder-schedule + :event ::events/change + :subscription editing-vendor}]] + " Never"]]] + + + [:h2.subtitle "Clients"] + + [horizontal-field + nil + [:div.control + [:div.select.is-expanded + [bind-field + [:select {:type "select" + :field :new-relationship-company + :event ::events/change + :subscription editing-vendor} + (for [company @(re-frame/subscribe [::subs/companies])] + [:option {:value (:id company)} (:name company)])]]]] + [:div.control + [bind-field + [:input.input {:type "text" + :field :new-relationship-account-number + :subscription editing-vendor + :event ::events/change + :placeholder "Account number"}]]] + [:div.control + [:button.button.is-primary + {:on-click (dispatch-event [::events/add-relationship])} + [:span.icon + [:i.fa.fa-plus]]]]] + [horizontal-field + nil + [:ul + (for [[i r] (map vector (range) (:relationships editing-vendor))] + ^{:key i} + [:li + (:name (companies-by-id (js/parseInt (:company-id r)))) ": " + (:account-number r) + [:a + {:on-click (dispatch-event [::events/remove-relationship i])} + [:span.icon + [:i.fa.fa-times]]]])]] + + + (when (:saving? editing-vendor) [:div.is-overlay {:style {"backgroundColor" "rgba(150,150,150, 0.5)"}}])])) (defn admin-vendors-page [] [(with-meta diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index b3df9743..b6b0d01b 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -3,10 +3,11 @@ [auto-ap.entities.companies :as company] [auto-ap.entities.vendors :as vendor] [auto-ap.events :as events] - [auto-ap.views.utils :refer [dispatch-event]] + [auto-ap.views.utils :refer [dispatch-event bind-field]] [auto-ap.utils :refer [by]] [auto-ap.views.pages.check :as check] [auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table] + [auto-ap.views.components.modal :refer [modal]] [auto-ap.subs :as subs] [auto-ap.events :as events])) @@ -15,6 +16,12 @@ (fn [db] (-> db ::invoice-page))) +(re-frame/reg-sub + ::advanced-print-checks + (fn [db] + (-> db ::advanced-print-checks))) + + (re-frame/reg-sub ::params (fn [db] @@ -52,29 +59,86 @@ (fn [db _] (update-in db [::invoice-page :print-checks-shown?] #(not %) ))) +(re-frame/reg-event-db + ::advanced-print-checks + (fn [db _] + (let [{:keys [checked invoices]} (get-in db [::invoice-page])] + (-> db + (update-in [::invoice-page :print-checks-shown?] #(not %) ) + (assoc-in [::advanced-print-checks] {:shown? true + :bank-account-id (:id (first (:bank-accounts @(re-frame/subscribe [::subs/company])))) + :invoices (->> invoices + (filter (comp checked :id)) + (map #(assoc % :amount (:outstanding-balance %))))} ))))) + +(re-frame/reg-event-db + ::cancel-advanced-print + (fn [db _] + (assoc-in db [::advanced-print-checks :shown?] false ))) + +(re-frame/reg-event-db + ::edit-payment-bank-account + (fn [db [_ f v]] + (assoc-in db [::advanced-print-checks :bank-account-id] v))) + +(re-frame/reg-event-db + ::edit-payment + (fn [db [_ which f v]] + (update-in db [::advanced-print-checks :invoices] + (fn [is] + (for [i is] + (if (= which (:id i)) + (assoc-in i f v) + i)))))) + +(defn print-checks-query [invoice-payments bank-account-id company-id] + {:venia/operation {:operation/type :mutation + :operation/name "PrintChecks"} + + :venia/queries [[:print-checks + {:invoice_payments invoice-payments + :bank_account_id bank-account-id + :company_id company-id} + [[:invoices [:id :outstanding-balance [:checks [:amount [:check [:amount :s3_url :check_number ]]]]]] + :pdf_url]]]}) + (re-frame/reg-event-fx ::print-checks (fn [{:keys [db]} [_ bank-account-id]] - (let [invoice-amounts (by :id :total (get-in db [::invoice-page :invoices]))] - { - :db (-> db + (let [invoice-amounts (by :id :outstanding-balance (get-in db [::invoice-page :invoices]))] + + {:db (-> db (assoc-in [::invoice-page :print-checks-shown?] false ) (assoc-in [::invoice-page :print-checks-loading?] true )) :graphql {:token (-> db :user) - :query-obj {:venia/operation {:operation/type :mutation - :operation/name "PrintChecks"} - - :venia/queries [[:print-checks - {:invoice_payments (map (fn [id] - {:invoice-id id - :amount (invoice-amounts id)}) - (get-in db [::invoice-page :checked])) - :bank_account_id bank-account-id - :company_id (:company db)} - [[:invoices [:id :outstanding-balance [:checks [:amount [:check [:amount :s3_url :check_number ]]]]]] - :pdf_url]]]} + :query-obj (print-checks-query (map (fn [id] + {:invoice-id id + :amount (invoice-amounts id)}) + (get-in db [::invoice-page :checked])) + bank-account-id + (:company db)) + :on-success [::checks-created]}}))) + + + +(re-frame/reg-event-fx + ::advanced-print-checks-submitted + (fn [{:keys [db]} [_ bank-account-id]] + (let [invoice-amounts (by :id (comp js/parseFloat :amount) (get-in db [::advanced-print-checks :invoices])) + bank-account-id (get-in db [::advanced-print-checks :bank-account-id])] + {:db (-> db + (assoc-in [::advanced-print-checks :printing?] true )) + :graphql + {:token (-> db :user) + + :query-obj (print-checks-query (map (fn [x] + {:invoice-id (:id x) + :amount (invoice-amounts (:id x))}) + (get-in db [::advanced-print-checks :invoices])) + bank-account-id + (:company db)) :on-success [::checks-created]}}))) @@ -91,23 +155,74 @@ (merge i (invoices-by-id (:id i)))) invoices))) (assoc-in [::invoice-page :checked] nil) - (assoc-in [::invoice-page :print-checks-loading?] false))}))) + (assoc-in [::invoice-page :print-checks-loading?] false) + (assoc-in [::advanced-print-checks :printing?] false) + (assoc-in [::advanced-print-checks :shown?] false) + )}))) (re-frame/reg-event-fx ::invalidated (fn [cofx [_ params]] {:dispatch [::params-change @(re-frame/subscribe [::params])]})) +(defn modal-dialog [] + (let [{:keys [checked]} @(re-frame/subscribe [::invoice-page]) + {:keys [shown? invoices printing?] :as advanced-print-checks} @(re-frame/subscribe [::advanced-print-checks]) + current-company @(re-frame/subscribe [::subs/company])] + + (when shown? + [modal {:title "Print Checks" + :foot [:button.button.is-primary {:on-click (dispatch-event [::advanced-print-checks-submitted]) + :class (if printing? "is-loading" "")} + [:span "Print"]] + :hide-event [::cancel-advanced-print]} + "Print using" + [:span.field + [:span.select + [bind-field + + [:select {:type "select" + :field :bank-account-id + :event ::edit-payment-bank-account + :subscription advanced-print-checks} + (for [{:keys [id number name]} (:bank-accounts current-company)] + ^{:key id} [:option {:value id} name])]]]] + + [:table.table + [:thead + [:tr + [:th "Vendor"] + [:th "Invoice ID"] + [:th {:style {"width" "10em"}} "Payment"]]] + [:tbody + (for [{:keys [vendor payment outstanding-balance invoice-number id] :as i} invoices] + ^{:key id} + [:tr + [:td (:name vendor)] + [:td invoice-number] + + [:td [:div.field.has-addons.is-extended + [:p.control [:a.button.is-static "$"]] + [:p.control + [bind-field + [:input.input {:type "number" + :field :amount + :event [::edit-payment id] + :subscription i + :value payment + :max outstanding-balance + :step "0.01"}]]]]]])]]]))) + (def unpaid-invoices-page (with-meta (fn [] - (let [{:keys [checked print-checks-shown? print-checks-loading?]} @(re-frame/subscribe [::invoice-page]) + (let [{:keys [checked print-checks-shown? print-checks-loading? advanced-print-shown?]} @(re-frame/subscribe [::invoice-page]) current-company @(re-frame/subscribe [::subs/company])] [:div [:h1.title "Unpaid invoices"] [:div.is-pulled-right (when current-company - [:div.dropdown {:class (if print-checks-shown? + [:div.dropdown.is-right {:class (if print-checks-shown? "is-active" "")} [:div.dropdown-trigger @@ -119,15 +234,16 @@ :class (if print-checks-loading? "is-loading" - "") - } + "")} "Print checks " [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]] [:div.dropdown-menu {:role "menu"} [:div.dropdown-content - (for [{:keys [id number name]} (:bank-accounts current-company)] - ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id])} name])]]])] - + (list + (for [{:keys [id number name]} (:bank-accounts current-company)] + ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id])} name]) + ^{:key "advanced-divider"} [:hr.dropdown-divider] + ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]]])] [invoice-table {:id :unpaid :params (re-frame/subscribe [::params]) :invoice-page (re-frame/subscribe [::invoice-page]) @@ -137,5 +253,8 @@ :check-boxes true :checked checked :on-check-changed (fn [which] - (re-frame/dispatch [::toggle-check which]))}]])) + (re-frame/dispatch [::toggle-check which]))}] + + [modal-dialog] + ])) {:component-will-mount #(re-frame/dispatch-sync [::params-change {}]) })) diff --git a/src/cljs/auto_ap/views/utils.cljs b/src/cljs/auto_ap/views/utils.cljs index 817e1fc2..8bb4f965 100644 --- a/src/cljs/auto_ap/views/utils.cljs +++ b/src/cljs/auto_ap/views/utils.cljs @@ -39,8 +39,9 @@ (defmethod do-bind "select" [dom {:keys [field subscription event class value spec] :as keys} & rest] (let [field (if (keyword? field) [field] field) + event (if (keyword? event) [event] event) keys (assoc keys - :on-change (dispatch-value-change [event field]) + :on-change (dispatch-value-change (conj event field)) :class (str class (when (and spec (not (s/valid? spec (get-in subscription field)))) " is-danger"))) @@ -50,8 +51,9 @@ (defmethod do-bind "radio" [dom {:keys [field subscription event class value spec] :as keys} & rest] (let [field (if (keyword? field) [field] field) + event (if (keyword? event) [event] event) keys (assoc keys - :on-change (dispatch-value-change [event field]) + :on-change (dispatch-value-change (conj event field)) :checked (= (get-in subscription field) value) :class (str class (when (and spec (not (s/valid? spec (get-in subscription field )))) @@ -62,8 +64,10 @@ (defmethod do-bind :default [dom {:keys [field event subscription class spec] :as keys} & rest] (let [field (if (keyword? field) [field] field) + event (if (keyword? event) [event] event) + _ (println field event dom rest) keys (assoc keys - :on-change (dispatch-value-change [event field]) + :on-change (dispatch-value-change (conj event field)) :value (get-in subscription field) :class (str class (when (and spec (not (s/valid? spec (get-in subscription field))))