(cloud) big performance improvements for page load.

This commit is contained in:
2023-04-06 14:38:22 -07:00
parent 2a0f736af7
commit 5561861d3d
10 changed files with 349 additions and 272 deletions

View File

@@ -1,10 +1,46 @@
(ns auto-ap.datomic.clients
(:require
[auto-ap.datomic :refer [conn]]
[auto-ap.datomic :refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many]]
[auto-ap.graphql.utils :refer [can-see-client? limited-clients]]
[auto-ap.search :as search]
[clj-time.coerce :as coerce]
[clojure.string :as str]
[datomic.client.api :as dc]))
[datomic.client.api :as dc]
[com.brunobonacci.mulog :as mu]))
(def full-read '[*
{:client/square-integration-status [:integration-status/message
:integration-status/last-attempt
:integration-status/last-updated
:db/id
{:integration-status/state [:db/ident]}]}
{:client/address [*]}
{:client/square-locations [:square-location/square-id
:square-location/name
:square-location/client-location
:db/id]}
{:client/ezcater-locations [{:ezcater-location/caterer [:ezcater-caterer/name :db/id]}
:ezcater-location/location
:db/id]}
{:client/bank-accounts [* {:bank-account/type [*]
:bank-account/yodlee-account [:yodlee-account/name :yodlee-account/id :yodlee-account/number]
:bank-account/plaid-account [:plaid-account/name :db/id :plaid-account/number :plaid-account/balance]
:bank-account/intuit-bank-account [:intuit-bank-account/name :intuit-bank-account/external-id :db/id]
:bank-account/integration-status [:integration-status/message
:db/id
:integration-status/last-attempt
:integration-status/last-updated
{:integration-status/state [:db/ident]}]}
]}
{:yodlee-provider-account/_client [*]}
{:plaid-item/_client [*]}
{:client/emails [:db/id :email-contact/email :email-contact/description]}])
(defn cleanse [e]
(-> e
@@ -29,52 +65,25 @@
(update :bank-account/sort-order (fn [so] (or so i)))))
(range) bas)))))
(defn get-all []
(->> (dc/q '[:find (pull ?e [*
{:client/square-integration-status [:integration-status/message
:integration-status/last-attempt
:integration-status/last-updated
:db/id
{:integration-status/state [:db/ident]}]}
{:client/address [*]}
{:client/square-locations [:square-location/square-id
:square-location/name
:square-location/client-location
:db/id]}
{:client/ezcater-locations [{:ezcater-location/caterer [:ezcater-caterer/name :db/id]}
:ezcater-location/location
:db/id]}
{:client/bank-accounts [* {:bank-account/type [*]
:bank-account/yodlee-account [:yodlee-account/name :yodlee-account/id :yodlee-account/number]
:bank-account/plaid-account [:plaid-account/name :db/id :plaid-account/number :plaid-account/balance]
:bank-account/intuit-bank-account [:intuit-bank-account/name :intuit-bank-account/external-id :db/id]
:bank-account/integration-status [:integration-status/message
:db/id
:integration-status/last-attempt
:integration-status/last-updated
{:integration-status/state [:db/ident]}]}
]}
{:yodlee-provider-account/_client [*]}
{:plaid-item/_client [*]}
{:client/emails [:db/id :email-contact/email :email-contact/description]}])
(->> (dc/q '[:find (pull ?e ?r)
:in $ ?r
:where [?e :client/name]]
(dc/db conn))
(dc/db conn)
full-read)
(map first)
(map cleanse)))
(defn get-minimal []
(->> (dc/q '[:find (pull ?e [:client/name :client/code :client/locations :db/id {:client/bank-accounts [{:bank-account/type [:db/ident]} :bank-account/name :bank-account/code :db/id]}])
:where [?e :client/name]]
(dc/db conn))
(map first)
(map cleanse)))
(defn get-by-id [id]
(->>
(dc/pull (dc/db conn )
'[* {:client/bank-accounts [* {:bank-account/type [*]
:bank-account/yodlee-account [:yodlee-account/name :yodlee-account/id :yodlee-account/number]
:bank-account/intuit-bank-account [:intuit-bank-account/name :intuit-bank-account/external-id :db/id]
:bank-account/plaid-account [:plaid-account/name :db/id :plaid-account/number :plaid-account/balance]}]
:client/emails [:db/id :email-contact/email :email-contact/description]}
{:client/ezcater-locations [{:ezcater-location/caterer [:ezcater-caterer/name :db/id]}
:ezcater-location/location
:db/id]}
{:yodlee-provider-account/_client [*]}
{:plaid-item/_client [*]}]
full-read
id)
(cleanse)))
@@ -105,3 +114,54 @@
:text match
:exact-match (str/upper-case match)})
"client"))
(defn raw-graphql-ids [db args]
(let [query (cond-> {:query {:find []
:in ['$ ]
:where []}
:args [db]}
(not (str/blank? (:code args)))
(merge-query {:query {:in ['?client-code]
:where ['[?e :client/code ?client-code]]}
:args [(:code args)]})
(not (str/blank? (:name-like args)))
(merge-query {:query {:in ['?name-like]
:where ['[?e :client/name ?name]
'[(clojure.string/includes? ?name ?name-like)]]}
:args [(:name-like args)]})
(limited-clients (:id args))
(merge-query {:query {:in ['[?e ...]]
:where []}
:args [(set (map :db/id (limited-clients (:id args))))]})
(:sort args) (add-sorter-fields {"name" ['[?e :client/name ?sort-name]]}
args)
true
(merge-query {:query {:find ['?sort-default '?e] :where ['[?e :client/name ?sort-default]]}}))]
(mu/log ::q
:query query)
(->> query
(dc/q)
(apply-sort-3 (update args :sort conj {:sort-key "default-2" :asc true}))
(apply-pagination args))))
(defn graphql-results [ids db args]
(let [results (->> (pull-many db full-read
ids)
(map cleanse))]
results))
(defn get-graphql-page [args]
(let [db (dc/db conn)
{ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)]
[(->> (graphql-results ids-to-retrieve db args))
matching-count]))

View File

@@ -9,11 +9,10 @@
pull-many
visible-clients
conn]]
[auto-ap.graphql.utils :refer [limited-clients]]
[iol-ion.query]
[clj-time.coerce :as c]
[clj-time.core :as time]
[clojure.set :as set]
[clojure.tools.logging :as log]
[datomic.client.api :as dc]
[com.brunobonacci.mulog :as mu]
))

View File

@@ -699,15 +699,14 @@
(- (+ total credit)
debit))
0.0
(dc/q {:query {:find '[?debit ?credit]
:in '[$ ?client]
:where ['[?j :journal-entry/client ?client]
'[?j :journal-entry/line-items ?je]
'[?je :journal-entry-line/account ?ba]
'[?ba :bank-account/type :bank-account-type/check]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]}
:args [(dc/db conn) client_id]}))
(dc/q {:query {:find '[?debit ?credit]
:in '[$ ?client]
:where ['[?client :client/bank-accounts ?ba]
'[?ba :bank-account/type :bank-account-type/check]
'[?je :journal-entry-line/account ?ba]
'[(get-else $ ?je :journal-entry-line/debit 0.0) ?debit]
'[(get-else $ ?je :journal-entry-line/credit 0.0) ?credit]]}
:args [(dc/db conn) client_id]}))
bills-due-soon (dc/q {:query {:find '[?due ?outstanding ?invoice-number ?vendor-id ?vendor-name]
:in '[$ ?client ?due-before]
:where ['[?i :invoice/client ?client]
@@ -734,8 +733,8 @@
recent-fulfillments (dc/q {:query {:find '[?f ?d]
:in '[$ ?client ?min-date]
:where ['[?t :transaction/forecast-match ?f]
'[?t :transaction/date ?d]
'[?t :transaction/client ?client]
'[?t :transaction/date ?d]
'[(>= ?d ?min-date)]]}
:args [(dc/db conn) client_id (coerce/to-date (t/plus (time/local-now) (t/months -2)))]})
forecasted-transactions (for [{:forecasted-transaction/keys [amount identifier day-of-month]

View File

@@ -3,12 +3,13 @@
[amazonica.aws.s3 :as s3]
[auto-ap.datomic :refer [audit-transact conn]]
[auto-ap.datomic.clients :as d-clients]
[iol-ion.tx :refer [upsert-entity]]
[auto-ap.graphql.utils
:refer [->graphql
assert-admin
attach-tracing-resolvers
can-see-client?
<-graphql
result->page
is-admin?]]
[auto-ap.routes.queries :as q]
[auto-ap.square.core :as square]
@@ -18,12 +19,12 @@
[clojure.set :as set]
[clojure.string :as str]
[clojure.tools.logging :as log]
[com.brunobonacci.mulog :as mu]
[datomic.client.api :as dc]
[unilog.context :as lc]
[iol-ion.tx :refer [random-tempid upsert-entity]]
[mount.core :as mount]
[yang.scheduler :as scheduler]
[iol-ion.tx :refer [random-tempid]]
[com.brunobonacci.mulog :as mu])
[unilog.context :as lc]
[yang.scheduler :as scheduler])
(:import
(java.util UUID)
(org.apache.commons.codec.binary Base64)))
@@ -200,23 +201,39 @@
(defn get-client [context _ _]
(->graphql
(->> (d-clients/get-all)
(filter #(can-see-client? (:id context) %))
(map (fn [c]
(update c :client/bank-accounts (fn [bas]
(map #(set/rename-keys % {:bank-account/use-date-instead-of-post-date? :use-date-instead-of-post-date}) bas)))))
(map (fn [c]
(if (is-admin? (:id context))
c
(-> c
(dissoc :client/yodlee-provider-accounts)
(dissoc :client/plaid-items)))))
(map (fn [c]
(update c :client/bank-accounts
(fn [bank-accounts]
(mapv (fn [ba]
(assoc ba :bank-account/yodlee-balance-old nil))
bank-accounts))))))))
(->> (d-clients/get-minimal)
(filter #(can-see-client? (:id context) %)))))
(defn get-admin-client [context {:keys [id]} _]
(assert-admin (:id context))
(->graphql
(-> (d-clients/get-by-id id)
(update :client/bank-accounts (fn [bas]
(map #(set/rename-keys % {:bank-account/use-date-instead-of-post-date? :use-date-instead-of-post-date}) bas))))))
(defn get-client-page [context args _]
(assert-admin (:id context))
(let [args (assoc args :id (:id context))
[clients clients-count] (d-clients/get-graphql-page (assoc (<-graphql (:filters args))
:id (:id context)))
clients (->> clients
(map (fn [c]
(update c :client/bank-accounts (fn [bas]
(map #(set/rename-keys % {:bank-account/use-date-instead-of-post-date? :use-date-instead-of-post-date}) bas)))))
(map (fn [c]
(if (is-admin? (:id context))
c
(-> c
(dissoc :client/yodlee-provider-accounts)
(dissoc :client/plaid-items)))))
(map (fn [c]
(update c :client/bank-accounts
(fn [bank-accounts]
(mapv (fn [ba]
(assoc ba :bank-account/yodlee-balance-old nil))
bank-accounts))))))]
(result->page clients clients-count :clients (:filters args))))
(def sales-summary-query
"[:find ?d4 (sum ?total) (sum ?tax) (sum ?tip) (sum ?service-charge) (sum ?discount) (sum ?returns)
@@ -437,6 +454,15 @@
:yodlee_provider_accounts {:type '(list :yodlee_provider_account)}
:plaid_items {:type '(list :plaid_item)}}}
:client_page
{:fields {:clients {:type '(list :client)}
:count {:type 'Int}
:total {:type 'Int}
:start {:type 'Int}
:end {:type 'Int}}}
:bank_account
{:fields {:id {:type :id}
:integration_status {:type :integration_status}
@@ -471,7 +497,14 @@
(def queries
{:client {:type '(list :client)
:resolve :get-client}})
:resolve :get-client}
:admin_client {:type :client
:args {:id {:type :id}}
:resolve :get-admin-client}
:client_page {:type :client_page
:args {:filters {:type :client_filters}}
:resolve :get-client-page}})
(def mutations
{:edit_client {:type :client
@@ -486,6 +519,13 @@
:match {:type 'String}
:id {:type :id}}}
:client_filters
{:fields {:code {:type 'String}
:name_like {:type 'String}
:start {:type 'Int}
:per_page {:type 'Int}
:sort {:type '(list :sort_item)}}}
:edit_square_location {:fields {:client_location {:type 'String}
:id {:type :id}}}
@@ -551,6 +591,8 @@
(def resolvers
{:get-client get-client
:get-admin-client get-admin-client
:get-client-page get-client-page
:mutation/edit-client edit-client
:mutation/setup-sales-queries setup-sales-queries})

View File

@@ -16,7 +16,13 @@
(js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." ))))))
(defn client-query [token]
(defn client-query []
(cond-> [:id :name :code :email :locations :feature-flags
[:emails [:id :email :description]]
[:bank-accounts [:id :code :bank-name :name :type :visible
:locations :include-in-reports :current-balance]]]))
(defn client-detail-query [token]
(cond-> [:id :name :signature-file :code :email :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits :locations :locked-until :square-auth-token :feature-flags
[:square-integration-status [:last-updated :last-attempt :message :state :id]]
[:square-locations [:square-id :id :name :client-location]]
@@ -68,7 +74,7 @@
:query-params (auto-ap.views.utils/query-params)
:user token)
:graphql {:token token
:query-obj {:venia/queries [[:client (client-query token)]]}
:query-obj {:venia/queries [[:client (client-query)]]}
:on-success [::received-initial]
:on-error [::failed-initial]}}))))
@@ -100,7 +106,7 @@
(fn [{:keys [db]}]
(let [token (-> db :user)]
{:graphql {:token token
:query-obj {:venia/queries [[:client (client-query token)]]}
:query-obj {:venia/queries [[:client (client-query)]]}
:on-success [::received-refreshed-clients]}})))
(re-frame/reg-event-fx

View File

@@ -4,6 +4,7 @@
[auto-ap.status :as status]
[auto-ap.subs :as subs]
[auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
[auto-ap.views.pages.data-page :as data-page]
[auto-ap.views.components.grid :as grid]
[auto-ap.views.components.layouts :refer [side-bar-layout]]
[auto-ap.views.pages.admin.clients.form :as form]
@@ -13,8 +14,12 @@
[auto-ap.views.utils :refer [with-user]]
[bidi.bidi :as bidi]
[clojure.string :as str]
[clojure.set :as set]
[re-frame.core :as re-frame]
[vimsical.re-frame.fx.track :as track]))
[vimsical.re-frame.fx.track :as track]
[auto-ap.events :as events]
[auto-ap.forms :as forms]
[auto-ap.db :as db]))
(re-frame/reg-event-db
::received-intuit-bank-accounts
@@ -24,10 +29,15 @@
(re-frame/reg-event-fx
::mounted
[with-user]
(fn [{:keys [user]} _]
{::track/register {:id ::params
:subscription [::params]
:event-fn (fn [params] [::params-change params])}
(fn [{:keys [user db]} _]
{::track/register [{:id ::params
:subscription [::data-page/params ::page]
:event-fn (fn [params] [::params-change params])}
{:id ::active-route
:subscription [::subs/active-route]
:event-fn (fn [params] [::params-change params])}]
:db (-> db
(forms/stop-form [::form/form]))
:graphql {:token user
:query-obj {:venia/queries [[:intuit_bank_accounts [:external_id :id :name]]]}
:owns-state {:single [::load-intuit-bank-accounts]}
@@ -37,34 +47,31 @@
::unmounted
(fn [{:keys [db]} _]
{:db (dissoc db ::table/params ::side-bar/filter-params)
::track/dispose {:id ::params}}))
::track/dispose [{:id ::params}
{:id ::active-route}]}))
(re-frame/reg-sub
::params
:<- [::table/params]
:<- [::side-bar/filter-params]
(fn [[table-params filter-params]]
(cond-> {}
(seq filter-params) (merge filter-params)
(seq table-params) (merge table-params))))
(defn data-params->query-params [params]
{:start (:start params 0)
:per-page (:per-page params)
:sort (:sort params)
:name-like (:name-like params)
:code (:code params)})
(re-frame/reg-event-fx
::params-change
(fn [_ [_ params]]
{:set-uri-params params}))
(re-frame/reg-sub
::page
:<- [::params]
:<- [::subs/clients]
(fn [[params all-clients]]
(let [matching-clients (cond->> all-clients
(not-empty (:name params)) (filter #(str/includes? (str/lower-case (or (:name %) ""))
(str/lower-case (:name params))))
(not-empty (:code params)) (filter #(= (str/lower-case (or (:code %) ""))
(str/lower-case (:code params)))))]
(assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) matching-clients)
:data (grid/virtual-paginate (:start params) (:per-page params) matching-clients)))))
[with-user]
(fn [{:keys [user]} [_ params]]
{:graphql {:token user
:owns-state {:single [::data-page/page ::page]}
:query-obj {:venia/queries [[:client-page
{:filters (data-params->query-params params)}
[[:clients (events/client-detail-query user)]
:total
:start
:end]]]}
:on-success (fn [result]
[::data-page/received ::page (set/rename-keys (:client-page result)
{:clients :data})])}}))
(def admin-clients-content
(with-meta
@@ -77,14 +84,14 @@
:content [:<>
[:div.is-pulled-right
[:a.button.is-primary.is-outlined {:href (bidi/path-for routes/routes :admin-specific-client :id "new")} "New client"]]
[table/clients-table {:page @(re-frame/subscribe [::page])
:status @(re-frame/subscribe [::status/single ::page])}]]}
[table/clients-table {:data-page ::page
:id :clients}]]}
{:key :admin-specific-client
:breadcrumb [:span [:a {:href (bidi/path-for routes/routes :admin-clients)}
"Clients"]
" / "
(or (:name @(re-frame/subscribe [::form/client]))
(or (:name (:data @(re-frame/subscribe [::forms/form ::form/form])))
[:i "New client"])]
:content [form/new-client-form]}
]}]])
@@ -94,6 +101,6 @@
(defn admin-clients-page []
[side-bar-layout {:side-bar [admin-side-bar {}
[side-bar/client-side-bar]]
[side-bar/client-side-bar {:data-page ::page}]]
:main [admin-clients-content]}])

View File

@@ -14,6 +14,7 @@
:refer [search-backed-typeahead]]
[auto-ap.views.utils
:refer [date-picker
with-user
dispatch-event]]
[bidi.bidi :as bidi]
[cljs-time.coerce :as coerce]
@@ -206,42 +207,46 @@
:bank-code bank-code})
(:bank-accounts new-client-data))})))
(re-frame/reg-sub
::client
:<- [::subs/route-params]
:<- [::subs/clients-by-id]
(fn [[rp clients-by-id]]
(or (get clients-by-id (:id rp))
{})))
(re-frame/reg-event-fx
::mounted
[(re-frame/inject-cofx ::inject/sub [::client])]
(fn [{:keys [db] ::keys [client]} _]
{:db (-> db
(forms/stop-form ::form)
(forms/start-form ::form (-> client
(assoc :selected-square-locations (->> (:square-locations client)
(filter :client-location )
(mapv (fn [sl]
{:id (:id sl)
:square-location sl
:client-location (:client-location sl)}))))
(update :locations #(mapv (fn [l] {:location l
:id (random-uuid)}) %))
[with-user (re-frame/inject-cofx ::inject/sub [::subs/route-params])]
(fn [{:keys [user db] ::subs/keys [route-params]} _]
{:graphql {:token user
:query-obj {:venia/queries [[:admin-client
{:id (js/parseInt (:id route-params))}
(events/client-detail-query user)]]}
:on-success (fn [result]
[::received (:admin-client result)])}
:db (-> db
(forms/stop-form ::form))}))
(update :feature-flags #(mapv (fn [l] {:feature-flag l
:id (random-uuid)}) %))
(update :matches #(mapv (fn [l] {:match l
:id (random-uuid)}) %))
(update :bank-accounts
(fn [bas]
(mapv (fn [ba]
(update ba :locations (fn [ls]
(map (fn [l] {:location l
:id (random-uuid)})
ls))))
bas))))))}))
(re-frame/reg-event-db
::received
(fn [db [_ client]]
(-> db
(forms/stop-form ::form)
(forms/start-form ::form (-> client
(assoc :selected-square-locations (->> (:square-locations client)
(filter :client-location )
(mapv (fn [sl]
{:id (:id sl)
:square-location sl
:client-location (:client-location sl)}))))
(update :locations #(mapv (fn [l] {:location l
:id (random-uuid)}) %))
(update :feature-flags #(mapv (fn [l] {:feature-flag l
:id (random-uuid)}) %))
(update :matches #(mapv (fn [l] {:match l
:id (random-uuid)}) %))
(update :bank-accounts
(fn [bas]
(mapv (fn [ba]
(update ba :locations (fn [ls]
(map (fn [l] {:location l
:id (random-uuid)})
ls))))
bas))))))))
(re-frame/reg-event-fx
::save-new-client
@@ -249,7 +254,7 @@
(fn [_ _]
(let [new-client-req @(re-frame/subscribe [::new-client-request])
user @(re-frame/subscribe [::subs/token])]
user @(re-frame/subscribe [::subs/token])]
{:graphql
{:token user
@@ -258,7 +263,7 @@
:operation/name "EditClient"}
:venia/queries [{:query/data [:edit-client
{:edit-client new-client-req}
(events/client-query user)]}]}
(events/client-detail-query user)]}]}
:on-success [::save-complete]
:on-error [::forms/save-error ::form]}})))
@@ -727,8 +732,7 @@
(defn form-content []
(let [_ @(re-frame/subscribe [::client])
{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
^{:key (or (:id new-client)
"new")}
@@ -750,5 +754,6 @@
(def new-client-form
(with-meta
(fn []
[form-content])
(let [_ @(re-frame/subscribe [::subs/route-params])]
[form-content]))
{:component-did-mount #(re-frame/dispatch [::mounted])}))

View File

@@ -2,78 +2,22 @@
(:require
[re-frame.core :as re-frame]
[auto-ap.views.utils :refer [dispatch-value-change]]
[auto-ap.subs :as subs]))
[auto-ap.views.pages.data-page :as data-page]))
(re-frame/reg-sub
::specific-filters
(fn [db ]
(::filters db nil)))
(re-frame/reg-sub
::filters
:<- [::specific-filters]
:<- [::subs/query-params]
(fn [[specific-filters _ query-params] ]
(let [url-filters (-> query-params
(select-keys #{:name
:code}))
url-filters {:name (str (:name url-filters))
:code (str (:code url-filters))}]
(merge url-filters specific-filters ))))
(re-frame/reg-sub
::filter
:<- [::filters]
(fn [filters [_ which]]
(get filters which)))
(re-frame/reg-sub
::filter-params
:<- [::settled-filters]
:<- [::filters]
:<- [::subs/active-page]
(fn [[settled-filters filters _ ]]
(let [filters (or settled-filters filters)]
{:name (:name filters)
:code (:code filters)})))
(re-frame/reg-sub
::settled-filters
(fn [db ]
(::settled-filters db)))
(re-frame/reg-event-fx
::filters-settled
(fn [{:keys [db]} _]
{:db (assoc db ::settled-filters @(re-frame/subscribe [::filters]))}))
(re-frame/reg-event-fx
::filter-changed
(fn [{:keys [db]} [_ & params]]
(let [[a b c] params
[which val] (if (= 3 (count params))
[(into [a] b) c]
[[a] b])]
{:db (assoc-in db (into [::filters] which) val)
:dispatch-debounce {:event [::filters-settled]
:time 800
:key ::filters}})))
(defn client-side-bar []
(defn client-side-bar [{:keys [data-page]}]
[:div
[:p.menu-label "Name"]
[:div.field
[:div.control [:input.input {:placeholder "Harry's Food Products"
:value @(re-frame/subscribe [::filter :name])
:on-change (dispatch-value-change [::filter-changed :name])} ]]]
:value @(re-frame/subscribe [::data-page/filter data-page :name-like])
:on-change (dispatch-value-change [::data-page/filter-changed data-page :name-like])} ]]]
[:p.menu-label "Code"]
[:div.field
[:div.control [:input.input {:placeholder "CBC"
:value @(re-frame/subscribe [::filter :code])
:on-change (dispatch-value-change [::filter-changed :code])} ]]]])
:value @(re-frame/subscribe [::data-page/filter data-page :code])
:on-change (dispatch-value-change [::data-page/filter-changed data-page :code])} ]]]])

View File

@@ -8,7 +8,8 @@
[auto-ap.views.components.buttons :as buttons]
[auto-ap.status :as status]
[bidi.bidi :as bidi]
[auto-ap.routes :as routes]))
[auto-ap.routes :as routes]
[auto-ap.views.pages.data-page :as data-page]))
(re-frame/reg-sub
::specific-params
@@ -76,14 +77,16 @@
nil
))
(defn clients-table [{:keys [page status]}]
(let [states @(re-frame/subscribe [::status/multi ::setup-sales-queries])]
(defn clients-table [{:keys [data-page status]}]
(let [states @(re-frame/subscribe [::status/multi ::setup-sales-queries])
{:keys [data]} @(re-frame/subscribe [::data-page/page data-page])]
[grid/grid {:on-params-change (fn [p]
(re-frame/dispatch [::params-changed p]))
:data-page data-page
:status status
:params @(re-frame/subscribe [::params])
:column-count 5}
[grid/controls page]
[grid/controls data]
[grid/table {:fullwidth true}
[grid/header
[grid/row {}
@@ -95,7 +98,7 @@
[grid/header-cell {:style {:width (action-cell-width 2)}}]]
]
[grid/body
(for [{:keys [id name email square-integration-status locked-until code locations bank-accounts]} (:data page)]
(for [{:keys [id name email square-integration-status locked-until code locations bank-accounts]} (:data data)]
^{:key (str name "-" id )}
[grid/row {:id id}
[grid/cell {} name]

View File

@@ -15,7 +15,9 @@
[re-frame.core :as re-frame]
[recharts]
[reagent.core :as r]
[react]))
[react]
[vimsical.re-frame.cofx.inject :as inject]
[auto-ap.status :as status]))
(def pie-chart (r/adapt-react-class recharts/PieChart))
(def pie (r/adapt-react-class recharts/Pie))
@@ -238,23 +240,28 @@
(re-frame/reg-event-fx
::mounted
(fn [{:keys [db]} _]
{:db (assoc db ::top-expense-categories nil)
:graphql {:token (-> db :user)
:query-obj {:venia/queries [[:expense_account_stats
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
[[:account [:id :name]] :total]]
[:invoice_stats
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
[:name :paid :unpaid]]
[:cash-flow
{:client-id (:id @(re-frame/subscribe [::subs/client]))}
[:beginning-balance
:outstanding-payments
[:invoices-due-soon [:due :outstanding-balance [:vendor [:id :name]] :invoice-number]]
[:upcoming-credits [:date :amount :identifier]]
[:upcoming-debits [:date :amount :identifier]]]]]}
:on-success [::received]}}))
[(re-frame/inject-cofx ::inject/sub [::subs/client])]
(fn [{:keys [db] ::subs/keys [client]} _]
(cond->
{:db (assoc db ::top-expense-categories nil
::cash-flow nil
::invoice-stats nil)}
client (assoc :graphql {:token (-> db :user)
:owns-state {:single ::page}
:query-obj {:venia/queries [[:expense_account_stats
{:client-id (:id client)}
[[:account [:id :name]] :total]]
[:invoice_stats
{:client-id (:id client)}
[:name :paid :unpaid]]
[:cash-flow
{:client-id (:id client)}
[:beginning-balance
:outstanding-payments
[:invoices-due-soon [:due :outstanding-balance [:vendor [:id :name]] :invoice-number]]
[:upcoming-credits [:date :amount :identifier]]
[:upcoming-debits [:date :amount :identifier]]]]]}
:on-success [::received]}))))
(defn cash-flow-range-button [{:keys [name value chart-options]}]
[:a.button {:class (when (= value (:cash-flow-range chart-options))
@@ -298,51 +305,56 @@
(defn home-content []
(let [client-id (-> @(re-frame/subscribe [::subs/client]) :id)
chart-options @(re-frame/subscribe [::chart-options])]
chart-options @(re-frame/subscribe [::chart-options])
state @(re-frame/subscribe [::status/single ::page])]
^{:key client-id}
[side-bar-layout {:side-bar [:div
]
:main [:div [:h1.title "Home"]
[:h1.title.is-4 "Top expense categories"]
(let [expense-categories @(re-frame/subscribe [::top-expense-categories])]
(make-pie-chart {:width 800 :height 500 :data (clj->js
(map (fn [x] {:name (:name (:account x)) :value (:total x)}) expense-categories))}))
[:h1.title.is-4 "Upcoming Bills"]
(make-bar-chart {:width 800 :height 500 :data (clj->js
@(re-frame/subscribe [::invoice-stats]))})
(if client-id
(if (= :loading (:state state))
[:div.loader.is-loading.big.is-centered]
[:h1.title.is-4 "Cash Flow"]
[:div.buttons.has-addons
[cash-flow-range-button {:name "7 days"
:value :seven-days
:chart-options chart-options}]
[cash-flow-range-button {:name "30 days"
:value :thirty-days
:chart-options chart-options}]
[:<>
[:h1.title.is-4 "Top expense categories"]
(let [expense-categories @(re-frame/subscribe [::top-expense-categories])]
(make-pie-chart {:width 800 :height 500 :data (clj->js
(map (fn [x] {:name (:name (:account x)) :value (:total x)}) expense-categories))}))
[:h1.title.is-4 "Upcoming Bills"]
(make-bar-chart {:width 800 :height 500 :data (clj->js
@(re-frame/subscribe [::invoice-stats]))})
[cash-flow-range-button {:name "60 days"
:value :sixty-days
:chart-options chart-options}]
[:h1.title.is-4 "Cash Flow"]
[:div.buttons.has-addons
[cash-flow-range-button {:name "7 days"
:value :seven-days
:chart-options chart-options}]
[cash-flow-range-button {:name "30 days"
:value :thirty-days
:chart-options chart-options}]
[cash-flow-range-button {:name "90 days"
:value :ninety-days
:chart-options chart-options}]
[cash-flow-range-button {:name "120 days"
:value :one-hundred-twenty-days
:chart-options chart-options}]
[cash-flow-range-button {:name "150 days"
:value :one-hundred-fifty-days
:chart-options chart-options}]
[cash-flow-range-button {:name "180 days"
:value :one-hundred-eighty-days
:chart-options chart-options}]]
(make-cash-flow-chart {:width 800 :height 500
:data (clj->js @(re-frame/subscribe [::cash-flow]))})
[cash-flow-range-button {:name "60 days"
:value :sixty-days
:chart-options chart-options}]
[cash-flow-grid]]}]))
[cash-flow-range-button {:name "90 days"
:value :ninety-days
:chart-options chart-options}]
[cash-flow-range-button {:name "120 days"
:value :one-hundred-twenty-days
:chart-options chart-options}]
[cash-flow-range-button {:name "150 days"
:value :one-hundred-fifty-days
:chart-options chart-options}]
[cash-flow-range-button {:name "180 days"
:value :one-hundred-eighty-days
:chart-options chart-options}]]
(make-cash-flow-chart {:width 800 :height 500
:data (clj->js @(re-frame/subscribe [::cash-flow]))})
[cash-flow-grid]])
[:h2.title.is-6 "Please select a customer to see reports."])]}]))
(defn home-page []