working on UI.
This commit is contained in:
@@ -47,6 +47,12 @@
|
||||
:else
|
||||
false))
|
||||
|
||||
(defn disabled-if-any [states]
|
||||
(if (some #(= :loading (:state %))
|
||||
(vals states))
|
||||
true
|
||||
false))
|
||||
|
||||
|
||||
(re-frame/reg-sub
|
||||
::multi
|
||||
|
||||
@@ -94,25 +94,23 @@
|
||||
[grid/header-cell {:style {:width (action-cell-width 3)}} ]]]
|
||||
[grid/body
|
||||
(for [{:keys [id name accounts status detailed-status last-updated clients] :as c} (:data page)]
|
||||
(do
|
||||
(println c)
|
||||
^{:key (str name "-" id )}
|
||||
[grid/row {:class (:class c) :id id}
|
||||
[grid/cell {} id]
|
||||
[grid/cell {} status]
|
||||
[grid/cell {} detailed-status]
|
||||
[grid/cell {} (date->str last-updated)]
|
||||
[grid/cell {}
|
||||
[:ul
|
||||
(for [a accounts]
|
||||
^{:key (:id a)}
|
||||
[:li (:name a) " - " (:number a) [:div.tag (->$ (:available-balance a))]])]]
|
||||
[grid/cell {}
|
||||
[:div.buttons
|
||||
[buttons/fa-icon {:event [::form/editing c]
|
||||
:icon "fa-pencil"}]
|
||||
[buttons/fa-icon {:event [::request-refresh (:id c) (:id (:client c))]
|
||||
:class (status/class-for (get statuses (:id c)))
|
||||
:icon "fa-refresh"}]
|
||||
[buttons/fa-icon {:event [::delete-requested (:id c)]
|
||||
:icon "fa-times"}]]]]))]]]))
|
||||
^{:key (str name "-" id )}
|
||||
[grid/row {:class (:class c) :id id}
|
||||
[grid/cell {} id]
|
||||
[grid/cell {} status]
|
||||
[grid/cell {} detailed-status]
|
||||
[grid/cell {} (date->str last-updated)]
|
||||
[grid/cell {}
|
||||
[:ul
|
||||
(for [a accounts]
|
||||
^{:key (:id a)}
|
||||
[:li (:name a) " - " (:number a) [:div.tag (->$ (:available-balance a))]])]]
|
||||
[grid/cell {}
|
||||
[:div.buttons
|
||||
[buttons/fa-icon {:event [::form/editing c]
|
||||
:icon "fa-pencil"}]
|
||||
[buttons/fa-icon {:event [::request-refresh (:id c) (:id (:client c))]
|
||||
:class (status/class-for (get statuses (:id c)))
|
||||
:icon "fa-refresh"}]
|
||||
[buttons/fa-icon {:event [::delete-requested (:id c)]
|
||||
:icon "fa-times"}]]]])]]]))
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
(ns auto-ap.views.pages.transactions.form
|
||||
(:require [auto-ap.forms :as forms]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.layouts :as layouts]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead typeahead-entity]]
|
||||
[auto-ap.views.components.button-radio :refer [button-radio]]
|
||||
[auto-ap.views.components.expense-accounts-field :refer [expense-accounts-field] :as expense-accounts-field]
|
||||
[auto-ap.views.components.expense-accounts-field
|
||||
:as
|
||||
expense-accounts-field
|
||||
:refer
|
||||
[expense-accounts-field]]
|
||||
[auto-ap.views.components.layouts :as layouts]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead-entity]]
|
||||
[auto-ap.views.pages.transactions.common :refer [transaction-read]]
|
||||
[auto-ap.views.utils :refer [bind-field dispatch-event with-user]]
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.views.utils :refer [->$ date->str dispatch-event with-user]]
|
||||
[clojure.string :as str]
|
||||
[clojure.set :as set]))
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.status :as status]
|
||||
[reagent.core :as r]
|
||||
[react :as react]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; SUBS
|
||||
(re-frame/reg-sub
|
||||
@@ -45,7 +52,7 @@
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::editing
|
||||
(fn [db [_ which potential-payment-matches potential-transaction-rule-matches]]
|
||||
(fn [db [_ which potential-payment-matches potential-autopay-invoices-matches potential-transaction-rule-matches]]
|
||||
(let [locations @(re-frame/subscribe [::subs/locations-for-client (:id (:client which))])
|
||||
accounts-by-id @(re-frame/subscribe [::subs/accounts-by-id (:client which)])]
|
||||
(forms/start-form db ::form
|
||||
@@ -62,6 +69,9 @@
|
||||
(assoc :potential-transaction-rule-matches (if (:matched-rule which)
|
||||
nil
|
||||
potential-transaction-rule-matches))
|
||||
(assoc :potential-autopay-invoices-matches (if (:matched-rule which)
|
||||
nil
|
||||
potential-autopay-invoices-matches))
|
||||
(update :accounts expense-accounts-field/from-graphql accounts-by-id (:amount which) locations))))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
@@ -91,7 +101,7 @@
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::matching
|
||||
::matching-payment
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
|
||||
(fn [{{{:keys [id]} :data} :db user :user} [_ payment-id]]
|
||||
{:graphql
|
||||
@@ -106,6 +116,23 @@
|
||||
[::edited (:match-transaction result)])
|
||||
:on-error [::forms/save-error ::form]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::matching-autopay-invoices
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
|
||||
(fn [{{{:keys [id]} :data} :db user :user} [_ invoice-ids]]
|
||||
{:graphql
|
||||
{:token user
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "MatchTransactionAutopayInvoices"}
|
||||
:venia/queries [{:query/data [:match-transaction-autopay-invoices
|
||||
{:transaction_id id
|
||||
:autopay-invoice-ids invoice-ids}
|
||||
transaction-read]}]}
|
||||
:owns-state {:multi ::matching
|
||||
:which [:autopay-invoices invoice-ids]}
|
||||
:on-success (fn [result]
|
||||
[::edited (:match-transaction-autopay-invoices result)])}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::matching-rule
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form)]
|
||||
@@ -164,40 +191,99 @@
|
||||
:id ::form}))
|
||||
|
||||
(defn potential-transaction-rule-matches-box [{:keys [potential-transaction-rule-matches] :as params}]
|
||||
[:div.box
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-5 "Matching Rules:"]]
|
||||
[:div.column.is-narrow
|
||||
[:a.delete {:on-click (dispatch-event [::transaction-rule-closed])} ]]]
|
||||
|
||||
[:table.table.compact.is-borderless
|
||||
(for [{:keys [note id]} potential-transaction-rule-matches]
|
||||
^{:key id}
|
||||
[:tr
|
||||
[:td.no-border note]
|
||||
[:td.no-border
|
||||
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-rule id])}
|
||||
"Use this rule"]]])]])
|
||||
(let [states @(re-frame/subscribe [::status/multi ::matching])]
|
||||
[:div.box
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-5 "Matching Rules:"]]]
|
||||
|
||||
[:table.table.compact.is-borderless
|
||||
(for [{:keys [note id]} potential-transaction-rule-matches]
|
||||
^{:key id}
|
||||
[:tr
|
||||
[:td.no-border note]
|
||||
[:td.no-border
|
||||
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-rule id])
|
||||
:class (status/class-for (get states [:transaction-rule id]))
|
||||
:disabled (status/disabled-if-any states)}
|
||||
"Use this rule"]]])]]))
|
||||
|
||||
|
||||
|
||||
(defn potential-payment-matches-box [{:keys [potential-payment-matches] :as params}]
|
||||
[:div.box
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:h1.subtitle.is-5 "Potentially matching payments:"]]
|
||||
[:div.column.is-narrow
|
||||
[:a.delete {:on-click (dispatch-event [::manual-match])} ]]]
|
||||
|
||||
[:table.table.compact.is-borderless
|
||||
(list
|
||||
(for [{:keys [memo check-number vendor id]} potential-payment-matches]
|
||||
[:tr
|
||||
[:td.no-border (:name vendor)]
|
||||
[:td.no-border (when check-number (str "Check " check-number " ")) memo]
|
||||
[:td.no-border
|
||||
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching id])}
|
||||
"Match"]]]))]])
|
||||
(let [states @(re-frame/subscribe [::status/multi ::matching])]
|
||||
[:div
|
||||
[:h1.subtitle.is-5 "Potentially matching payments:"]
|
||||
|
||||
[:table.table.compact.is-borderless
|
||||
(list
|
||||
(for [{:keys [memo check-number vendor id]} potential-payment-matches]
|
||||
[:tr
|
||||
[:td.no-border (:name vendor)]
|
||||
[:td.no-border (when check-number (str "Check " check-number " ")) memo]
|
||||
[:td.no-border
|
||||
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-payment id])
|
||||
:class (status/class-for (get states [:payment id]))
|
||||
:disabled (status/disabled-if-any states)}
|
||||
"Match"]]]))]]))
|
||||
|
||||
(defn potential-autopay-invoices-matches-box [{:keys [potential-autopay-invoices-matches] :as params}]
|
||||
(let [states @(re-frame/subscribe [::status/multi ::matching])]
|
||||
[:div
|
||||
[:div.notification.is-light.is-info "This transaction may match the following autopay invoice(s)."]
|
||||
[:table.table.grid.is-fullwidth
|
||||
(list
|
||||
(for [invoices potential-autopay-invoices-matches]
|
||||
^{:key (str invoices)}
|
||||
[:tr
|
||||
[:td {:style {:width "30%"}} (:name (:vendor (first invoices)))]
|
||||
[:td {:style {:overflow "visible" :width "60%"}} [:span.has-tooltip-arrow.has-tooltip-bottom {:data-tooltip (str/join "\n"
|
||||
(for [i invoices]
|
||||
(str (:invoice-number i) " (" (->$ (:total i)) ")"))
|
||||
)}
|
||||
(count invoices) " invoices" (if (> (count invoices) 1)
|
||||
(str " from " (date->str (:date (first invoices))) " - " (date->str (:date (last invoices))))
|
||||
(str " on " (date->str (:date (first invoices)))))]]
|
||||
[:td {:style {:width "6em"}}
|
||||
[:a.button.is-primary.is-small {:on-click (dispatch-event [::matching-autopay-invoices (map :id invoices)])
|
||||
:class (status/class-for (get states [:autopay-invoices (map :id invoices)]))
|
||||
:disabled (status/disabled-if-any states)}
|
||||
"Match"]]]))]]))
|
||||
|
||||
|
||||
(defonce ^js/React.Context current-tab-context ( react/createContext "default"))
|
||||
(def ^js/React.Provider CurrentTabProvider (. current-tab-context -Provider))
|
||||
#_(println "Provider is" Provider)
|
||||
(def ^js/React.Consumer CurrentTabConsumer (. current-tab-context -Consumer))
|
||||
|
||||
(defn tabs [props & children]
|
||||
(let [current-tab (r/atom (:default-tab props))]
|
||||
(fn [props & children]
|
||||
(let [current-tab-v @current-tab]
|
||||
(r/create-element CurrentTabProvider #js {:value #js {:current-tab current-tab-v
|
||||
:on-tab-clicked (fn [new]
|
||||
(reset! current-tab new))}}
|
||||
(r/as-element
|
||||
[:<>
|
||||
[:div.tabs
|
||||
(into [:ul]
|
||||
(r/children (r/current-component)))]
|
||||
(into [:div]
|
||||
(->> (r/children (r/current-component))
|
||||
(filter identity)
|
||||
(filter #(= (doto (:key (second %)) println) current-tab-v) )
|
||||
first
|
||||
(drop 2)))]))))))
|
||||
|
||||
(defn tab [props & children]
|
||||
[:> CurrentTabConsumer {}
|
||||
(fn [consume]
|
||||
(let [{:strs [current-tab on-tab-clicked]} (js->clj consume)]
|
||||
(r/as-element
|
||||
[:li (if (= (:key props)
|
||||
current-tab)
|
||||
{:class "is-active"})
|
||||
[:a {:on-click (fn [] (on-tab-clicked (:key props)))} (:title props)]])))])
|
||||
|
||||
|
||||
(defn form [_]
|
||||
@@ -208,7 +294,9 @@
|
||||
{:keys [form-inline form field raw-field error-notification submit-button ]} transaction-form
|
||||
is-admin? @(re-frame/subscribe [::subs/is-admin?])
|
||||
should-disable-for-client? (and (not is-admin?)
|
||||
(not= :requires-feedback (:original-status data)))]
|
||||
(not= :requires-feedback (:original-status data)))
|
||||
is-already-matched? (or (:matched-rule data)
|
||||
(:payment data))]
|
||||
(form-inline {:title "Transaction"}
|
||||
[:<>
|
||||
|
||||
@@ -235,27 +323,37 @@
|
||||
[:input.input {:type "text"
|
||||
:field [:description-original]
|
||||
:disabled "disabled"}])
|
||||
|
||||
|
||||
(when (and (:payment data)
|
||||
is-admin?)
|
||||
[:p.notification.is-info.is-light>div.level>div.level-left
|
||||
[:div.level-item "This transaction is linked to a payment "]
|
||||
[:div.level-item [:button.button.is-warning {:on-click (dispatch-event [::unlink])} "Unlink"]]])
|
||||
|
||||
(cond
|
||||
(and (seq (:potential-transaction-rule-matches data))
|
||||
(not (:matched-rule data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
[potential-transaction-rule-matches-box {:potential-transaction-rule-matches (:potential-transaction-rule-matches data)}]
|
||||
[tabs {:default-tab :details}
|
||||
(when
|
||||
(and (seq (:potential-transaction-rule-matches data))
|
||||
(not is-already-matched?)
|
||||
is-admin?)
|
||||
[tab {:title "Transaction Rule" :key :transaction-rule}
|
||||
[potential-transaction-rule-matches-box {:potential-transaction-rule-matches (:potential-transaction-rule-matches data)}]])
|
||||
|
||||
(when
|
||||
(and (seq (:potential-autopay-invoices-matches data))
|
||||
(not is-already-matched?)
|
||||
is-admin?)
|
||||
[tab {:title "Autopay invoices" :key :autopay-invoices}
|
||||
[potential-autopay-invoices-matches-box {:potential-autopay-invoices-matches (:potential-autopay-invoices-matches data)}]])
|
||||
|
||||
(when
|
||||
(and (seq (:potential-payment-matches data))
|
||||
(not is-already-matched?)
|
||||
|
||||
[tab {:title "Payment" :key :payment}
|
||||
[potential-payment-matches-box {:potential-payment-matches (:potential-payment-matches data)}]]))
|
||||
|
||||
(and (seq (:potential-payment-matches data))
|
||||
(not (:payment data))
|
||||
is-admin?)
|
||||
[potential-payment-matches-box {:potential-payment-matches (:potential-payment-matches data)}]
|
||||
|
||||
(and (not (seq (:potential-payment-matches data)))
|
||||
(not (seq (:potential-transaction-rule-matches data))))
|
||||
[tab {:title "Details" :key :details}
|
||||
[:div
|
||||
(field "Vendor"
|
||||
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
|
||||
@@ -293,33 +391,6 @@
|
||||
:match->text :identifier
|
||||
:type "typeahead-entity"
|
||||
:field [:forecast-match]}])
|
||||
|
||||
|
||||
|
||||
|
||||
(error-notification)
|
||||
(when-not should-disable-for-client?
|
||||
(submit-button "Save"))]
|
||||
|
||||
:else
|
||||
|
||||
[:div
|
||||
(field "Approval Status"
|
||||
[button-radio
|
||||
{:type "button-radio"
|
||||
:field [:approval-status]
|
||||
:options [[:unapproved "Unapproved"]
|
||||
[:requires-feedback "Client Review"]
|
||||
[:approved "Approved"]
|
||||
[:excluded "Excluded from Ledger"]]
|
||||
:disabled should-disable-for-client?}])
|
||||
|
||||
(field "Forecasted-transaction"
|
||||
[typeahead-entity {:matches (doto @(re-frame/subscribe [::subs/forecasted-transactions-for-client (:id (:client data))]) println)
|
||||
:match->text :identifier
|
||||
:type "typeahead-entity"
|
||||
:field [:forecast-match]}])
|
||||
|
||||
(error-notification)
|
||||
(when-not should-disable-for-client?
|
||||
(submit-button "Save"))])]))])
|
||||
(submit-button "Save"))]]]]))])
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
::editing-matches-found
|
||||
(fn [{:keys [db]} [_ which matches]]
|
||||
{:dispatch
|
||||
[::edit/editing which (:potential-payment-matches matches) (:potential-transaction-rule-matches matches)]}))
|
||||
[::edit/editing which (:potential-payment-matches matches) (:potential-autopay-invoices-matches matches) (:potential-transaction-rule-matches matches)]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::editing-matches-failed
|
||||
@@ -36,7 +36,10 @@
|
||||
:which (:id which)}
|
||||
:query-obj {:venia/queries (into [{:query/data [:potential-payment-matches
|
||||
{:transaction_id (:id which)}
|
||||
[:id :memo :check-number [:vendor [:name]]]]}]
|
||||
[:id :memo :check-number [:vendor [:name]]]]}
|
||||
{:query/data [:potential-autopay-invoices-matches
|
||||
{:transaction_id (:id which)}
|
||||
[:id :invoice-number :total :date :scheduled-payment [:vendor [:name]]]]}]
|
||||
(when @(re-frame/subscribe [::subs/is-admin?])
|
||||
[{:query/data [:potential-transaction-rule-matches
|
||||
{:transaction_id (:id which)}
|
||||
|
||||
Reference in New Issue
Block a user