removed the cruft.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
[amazonica.aws.s3 :as s3]
|
||||
[auto-ap.datomic :refer [audit-transact conn]]
|
||||
[auto-ap.datomic.clients :as d-clients]
|
||||
[com.brunobonacci.mulog :as mu]
|
||||
[auto-ap.datomic.invoices :as d-invoices]
|
||||
[auto-ap.datomic.vendors :as d-vendors]
|
||||
[auto-ap.graphql.utils :refer [assert-admin assert-can-see-client]]
|
||||
@@ -335,12 +336,10 @@
|
||||
|
||||
(def routes {"api/" {"transactions/" {:post {#"batch-upload/?" :batch-upload-transactions
|
||||
#"cleared-against/?" :cleared-against}}
|
||||
"invoices/" {:post {#"upload/?" :upload-invoices
|
||||
#"upload-integreat/?" :bulk-upload-invoices}}
|
||||
"invoices/" {:post {#"upload/?" :upload-invoices}}
|
||||
:post {#"account-overrides/?" :bulk-account-overrides}}})
|
||||
|
||||
(def match->handler {:batch-upload-transactions (wrap-secure batch-upload-transactions)
|
||||
:upload-invoices (wrap-secure upload-invoices)
|
||||
:bulk-upload-invoices (wrap-secure bulk-upload-invoices)
|
||||
:cleared-against (wrap-secure cleared-against)
|
||||
:bulk-account-overrides (wrap-secure (wrap-json-response bulk-account-overrides))})
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
[:li
|
||||
[:a {:href (bidi/path-for ssr-routes/only-routes :company), :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "My Company"]]
|
||||
(when (= "admin" (:user/role identity))
|
||||
[:a {:href (bidi/path-for client-routes2/routes :admin), :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "Admin"])
|
||||
[:a {:href (bidi/path-for ssr-routes/only-routes :auto-ap.routes.admin/page), :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "Admin"])
|
||||
[:li
|
||||
[:a {:href "#", :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"
|
||||
"_" (hiccup/raw "on click toggle .dark on <body />")}
|
||||
|
||||
@@ -9,25 +9,19 @@
|
||||
"admin/" {"clients/" {"" :admin-clients
|
||||
[:id] {"" :admin-specific-client
|
||||
"/bank-accounts/" {[:bank-account] :admin-specific-bank-account}}}
|
||||
"vendors" :admin-vendors
|
||||
"excel-import" :admin-excel-import
|
||||
}
|
||||
"vendors" :admin-vendors}
|
||||
"invoices/" {"" :invoices
|
||||
"import" :import-invoices
|
||||
"unpaid" :unpaid-invoices
|
||||
"paid" :paid-invoices
|
||||
"voided" :voided-invoices
|
||||
"new" :new-invoice}
|
||||
"pos/" {"sales-orders" :sales-orders
|
||||
"expected-deposits" :expected-deposits}
|
||||
"transactions/" {"" :transactions
|
||||
"unapproved" :unapproved-transactions
|
||||
"approved" :approved-transactions
|
||||
"requires-feedback" :requires-feedback-transactions
|
||||
"excluded" :excluded-transactions}
|
||||
"reports/" {"" :reports}
|
||||
"company/" {"other" :company-other
|
||||
"export-vendors" :company-export-vendors}
|
||||
"plaid" :plaid
|
||||
"yodlee2" :yodlee2
|
||||
"ledger/" {"" :ledger
|
||||
|
||||
@@ -18,16 +18,9 @@
|
||||
[auto-ap.views.pages.ledger.profit-and-loss-detail :refer [profit-and-loss-detail-page]]
|
||||
[auto-ap.views.pages.login :refer [login-page]]
|
||||
[auto-ap.views.pages.payments :refer [payments-page]]
|
||||
[auto-ap.views.pages.pos.sales-orders :refer [sales-orders-page]]
|
||||
[auto-ap.views.pages.pos.expected-deposits :refer [expected-deposits-page]]
|
||||
[auto-ap.views.pages.admin :refer [admin-page]]
|
||||
[auto-ap.views.pages.home :refer [home-page]]
|
||||
[auto-ap.views.pages.admin.clients :refer [admin-clients-page]]
|
||||
[auto-ap.views.pages.admin.rules :refer [admin-rules-page]]
|
||||
[auto-ap.views.pages.admin.vendors :refer [admin-vendors-page]]
|
||||
[auto-ap.views.pages.admin.excel-import :refer [admin-excel-import-page]]
|
||||
[auto-ap.views.pages.admin.import-batches :refer [import-batches-page]]
|
||||
[auto-ap.views.pages.company.other :as company-other]))
|
||||
[auto-ap.views.pages.admin.vendors :refer [admin-vendors-page]]))
|
||||
|
||||
(defmulti page (fn [active-page] active-page))
|
||||
(defmethod page :unpaid-invoices [_]
|
||||
@@ -55,12 +48,6 @@
|
||||
(defmethod page :payments [_]
|
||||
[payments-page])
|
||||
|
||||
(defmethod page :sales-orders [_]
|
||||
[sales-orders-page])
|
||||
|
||||
(defmethod page :expected-deposits [_]
|
||||
[expected-deposits-page])
|
||||
|
||||
(defmethod page :transactions [_]
|
||||
(transactions-page {}))
|
||||
|
||||
@@ -92,31 +79,17 @@
|
||||
(defmethod page :balance-sheet [_]
|
||||
(balance-sheet-page))
|
||||
|
||||
(defmethod page :admin [_]
|
||||
(admin-page))
|
||||
|
||||
(defmethod page :admin-clients [_]
|
||||
(admin-clients-page))
|
||||
|
||||
(defmethod page :admin-specific-client [_]
|
||||
(admin-clients-page))
|
||||
|
||||
|
||||
(defmethod page :admin-rules [_]
|
||||
(admin-rules-page))
|
||||
|
||||
(defmethod page :admin-vendors [_]
|
||||
(admin-vendors-page))
|
||||
|
||||
(defmethod page :admin-import-batches [_]
|
||||
[import-batches-page])
|
||||
|
||||
(defmethod page :company-other [_]
|
||||
(company-other/company-other-page))
|
||||
|
||||
(defmethod page :index [_]
|
||||
(home-page)
|
||||
)
|
||||
(home-page))
|
||||
|
||||
(defmethod page :login [_]
|
||||
[login-page])
|
||||
@@ -130,10 +103,6 @@
|
||||
(defmethod page :external-ledger [_]
|
||||
[external-ledger-page])
|
||||
|
||||
(defmethod page :admin-excel-import [_]
|
||||
[admin-excel-import-page])
|
||||
|
||||
|
||||
(defmethod page :initial-error [_]
|
||||
[error-page])
|
||||
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.excel-import
|
||||
(:require
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.forms.builder :as form-builder]
|
||||
[auto-ap.schema :as schema]
|
||||
[auto-ap.views.components :as com]
|
||||
[auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.utils :refer [with-user]]
|
||||
[malli.core :as m]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::save
|
||||
[ with-user (forms/in-form ::form)]
|
||||
(fn [{:keys [db user]}]
|
||||
{:http {:token user
|
||||
:method :post
|
||||
:body (pr-str {:excel-rows (:excel-rows (:data db))})
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/invoices/upload-integreat")
|
||||
:owns-state {:single ::form}
|
||||
:on-success [::save-complete]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::save-complete
|
||||
(fn [{:keys [db]} [_ rows]]
|
||||
(cond->
|
||||
{:db (assoc db ::result rows)}
|
||||
(seq (:vendors-not-found rows)) (assoc :dispatch [::forms/start-form ::create-vendors ]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::result
|
||||
(fn [db]
|
||||
(::result db)))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::create-vendors
|
||||
[with-user (forms/in-form ::create-vendors)]
|
||||
(fn [{:keys [user db]}]
|
||||
{:graphql {:token user
|
||||
:owns-state {:single ::create-vendors}
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "UpsertVendor"}
|
||||
|
||||
:venia/queries
|
||||
(for [[vendor-name {:keys [default-account]}] (:data db)]
|
||||
{:query/data [:upsert-vendor
|
||||
{:vendor {:name vendor-name :default-account-id (:id default-account)}}
|
||||
[:id :name]]})}
|
||||
:on-success [::create-vendor-complete]}}))
|
||||
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::create-vendor-complete
|
||||
(fn [db _]
|
||||
(dissoc db ::result )))
|
||||
|
||||
(def missing-vendor-schema
|
||||
(m/schema [:map-of :string
|
||||
[:map
|
||||
[:default-account schema/reference]]]))
|
||||
|
||||
(defn create-missing-vendors [{:keys [vendors]}]
|
||||
(let [{:keys [data]} @(re-frame/subscribe [::forms/form ::create-vendors])
|
||||
vendors-to-create (filter (fn [v] (:checked v))
|
||||
(vals data))]
|
||||
[form-builder/builder {:id ::create-vendors
|
||||
:submit-event [::create-vendors]
|
||||
:schema missing-vendor-schema}
|
||||
[:article.message.is-warning.is-paddingless
|
||||
[:div.message-header
|
||||
"Some vendors could not be found"]
|
||||
|
||||
[:div.message-body
|
||||
[:h2 "Check the vendors you want to create"]
|
||||
(for [v vendors]
|
||||
^{:key v}
|
||||
[:div.field.is-grouped
|
||||
[:div.control
|
||||
[form-builder/raw-field-v2 {:field [v :checked]}
|
||||
[com/checkbox {:label v}]]]
|
||||
|
||||
[:div.control
|
||||
[form-builder/raw-field-v2 {:field [v :default-account]}
|
||||
[com/search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_account
|
||||
{:query i}
|
||||
[:name :id :location]])}]]]])
|
||||
[form-builder/error-notification]
|
||||
[form-builder/submit-button {:disabled (when-not (seq vendors-to-create) "disabled")}
|
||||
(str "Create " (count vendors-to-create) " vendors")]
|
||||
[:div.is-clearfix]]]]))
|
||||
|
||||
(defn admin-excel-import-content []
|
||||
[:div
|
||||
(let [{:keys [vendors-not-found errors already-imported imported]} @(re-frame/subscribe [::result])]
|
||||
[:div
|
||||
[:h1.title "Import Invoices from Integreat Excel"]
|
||||
(when (seq vendors-not-found)
|
||||
[create-missing-vendors {:vendors vendors-not-found}]
|
||||
)
|
||||
[form-builder/builder {:id ::form
|
||||
:submit-event [::save]}
|
||||
[form-builder/raw-field-v2 {:field :excel-rows}
|
||||
[:textarea.textarea {:rows "20"
|
||||
:type "text"}]]
|
||||
[form-builder/error-notification]
|
||||
[form-builder/submit-button "Import"]]
|
||||
[:div.is-clearfix]
|
||||
[:div.is-clearfix
|
||||
[:p
|
||||
(when imported
|
||||
(str imported " rows imported."))]
|
||||
[:p
|
||||
(when already-imported
|
||||
(str already-imported " rows already imported."))]]
|
||||
(when errors
|
||||
[:div
|
||||
[:h3 (str "Import errors (" (min 100 (count errors)) " / " (count errors) " )")]
|
||||
[:table.table.is-fullwidth
|
||||
[:thead
|
||||
[:td "Date"]
|
||||
[:td "Invoice #"]
|
||||
[:td "Client"]
|
||||
[:td "Vendor"]
|
||||
[:td "Amount"]
|
||||
[:td "Errors"]]
|
||||
|
||||
[:tbody
|
||||
(for [{:keys [raw-date invoice-number client vendor-name amount] row-errors :errors} (take 100 errors)]
|
||||
^{:key (str raw-date invoice-number client vendor-name amount)}
|
||||
[:tr
|
||||
[:td raw-date]
|
||||
[:td invoice-number]
|
||||
[:td client]
|
||||
[:td vendor-name]
|
||||
[:td amount]
|
||||
[:td (map (fn [{:keys [info]}] ^{:key info} [:p info]) row-errors)]])]]])])])
|
||||
|
||||
|
||||
(defn admin-excel-import-page-internal []
|
||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
||||
:main [admin-excel-import-content]}])
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [_ _]
|
||||
{:dispatch [::forms/start-form ::form]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn [{:keys [db]} _]
|
||||
{:dispatch-n [[::forms/form-closing ::form]
|
||||
[::forms/form-closing ::create-vendors]]
|
||||
:db (dissoc db ::results)}))
|
||||
|
||||
(defn admin-excel-import-page []
|
||||
(r/create-class
|
||||
{:display-name "excel-import-page"
|
||||
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])
|
||||
:component-did-mount #(re-frame/dispatch [::mounted])
|
||||
:reagent-render admin-excel-import-page-internal}))
|
||||
@@ -1,69 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.import-batches
|
||||
(:require
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.pages.admin.import-batches.table :as table]
|
||||
[auto-ap.views.pages.data-page :as data-page]
|
||||
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||
[clojure.set :as set]
|
||||
[re-frame.core :as re-frame]
|
||||
[vimsical.re-frame.fx.track :as track]))
|
||||
|
||||
(def default-read [:user-name :date :source :status :id :imported :suppressed :extant])
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::params-change
|
||||
[with-user ]
|
||||
(fn [{:keys [user]} [_ params]]
|
||||
{:graphql {:token user
|
||||
:owns-state {:single [::data-page/page ::page]}
|
||||
:query-obj {:venia/queries [{:query/data [:import_batch_page
|
||||
{:filters {:sort (:sort params)
|
||||
:start (:start params 0)
|
||||
:per-page (:per-page params)}}
|
||||
[[:data default-read]
|
||||
:total
|
||||
:start
|
||||
:end]]
|
||||
:query/alias :result}]}
|
||||
:on-success (fn [result]
|
||||
[::data-page/received ::page
|
||||
(set/rename-keys (:result result)
|
||||
{:import-batches :data})])}}))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [_]
|
||||
{::track/register {:id ::params
|
||||
:subscription [::data-page/params ::page]
|
||||
:event-fn (fn [params]
|
||||
[::params-change params])}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn [{:keys [db]}]
|
||||
{:dispatch [::data-page/dispose ::page]
|
||||
::track/dispose {:id ::params}}))
|
||||
|
||||
;; VIEWS
|
||||
(def import-batch-content
|
||||
(with-meta
|
||||
(fn []
|
||||
(let [user @(re-frame/subscribe [::subs/user])]
|
||||
[:div
|
||||
[:h1.title "Import Batches"]
|
||||
(when (= "admin" (:user/role user))
|
||||
[:div
|
||||
[:div.is-pulled-right
|
||||
[:div.buttons]]
|
||||
[table/table {:id :import-batches
|
||||
:data-page ::page}]])]))
|
||||
{:component-did-mount (dispatch-event [::mounted ])
|
||||
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])}))
|
||||
|
||||
(defn import-batches-page []
|
||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
||||
:main [import-batch-content]}])
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.import-batches.table
|
||||
(:require [auto-ap.routes :as routes]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.buttons :as buttons]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.pages.data-page :as data-page]
|
||||
[auto-ap.views.utils
|
||||
:refer
|
||||
[action-cell-width date->str dispatch-event pretty-long]]
|
||||
[bidi.bidi :as bidi]
|
||||
[cemerick.url :as url]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::specific-table-params
|
||||
(fn [db]
|
||||
(::table-params db)))
|
||||
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::unmounted
|
||||
(fn [db]
|
||||
(status/reset-multi db ::run)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::table-params
|
||||
:<- [::specific-table-params]
|
||||
:<- [::subs/query-params]
|
||||
(fn [[specific-table-params query-params]]
|
||||
(merge (select-keys query-params #{:start :sort}) specific-table-params )))
|
||||
|
||||
(defn table* [{:keys [data-page]}]
|
||||
(let [{:keys [data]} @(re-frame/subscribe [::data-page/page data-page])]
|
||||
[grid/grid {:data-page data-page
|
||||
:column-count 6}
|
||||
[grid/controls data]
|
||||
[grid/table {:fullwidth true}
|
||||
[grid/header
|
||||
[grid/row {}
|
||||
[grid/sortable-header-cell {:sort-key "date"
|
||||
:sort-name "Date"}
|
||||
"Date"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "source"
|
||||
:sort-name "Source"}
|
||||
"Source"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "status"
|
||||
:sort-name "Status"}
|
||||
"Status"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "user"
|
||||
:sort-name "User"}
|
||||
"User"]
|
||||
[grid/header-cell {:style {:width "7em"}} "Imported"]
|
||||
[grid/header-cell {:style {:width "7em"}} "Preexisting"]
|
||||
[grid/header-cell {:style {:width "7em"}} "Suppressed"]
|
||||
[grid/header-cell {:style {:width (action-cell-width 3)}}]]]
|
||||
[grid/body
|
||||
(for [{:keys [date source status user-name id imported extant suppressed] :as r} (:data data)]
|
||||
^{:key id}
|
||||
[grid/row {:class (:class r) :id id}
|
||||
[grid/cell {} (date->str date pretty-long)]
|
||||
[grid/cell {} source]
|
||||
[grid/cell {} status]
|
||||
[grid/cell {} user-name]
|
||||
[grid/cell {} imported]
|
||||
[grid/cell {} extant]
|
||||
[grid/cell {} suppressed]
|
||||
[grid/button-cell {}
|
||||
[buttons/fa-icon {:href (str (bidi/path-for routes/routes :transactions)
|
||||
"?"
|
||||
(url/map->query {:import-batch-id id}))
|
||||
:icon "fa-external-link"}]]])]]
|
||||
[grid/bottom-paginator data]]))
|
||||
|
||||
(defn table []
|
||||
(r/create-class {:component-will-unmount (dispatch-event [::unmounted])
|
||||
:reagent-render (fn [params]
|
||||
[table* params])}))
|
||||
@@ -1,103 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules
|
||||
(:require
|
||||
[auto-ap.effects.forward :as forward]
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.buttons :as buttons]
|
||||
[auto-ap.views.components.layouts
|
||||
:refer [appearing-side-bar side-bar-layout]]
|
||||
[auto-ap.views.pages.admin.rules.common :refer [default-read]]
|
||||
[auto-ap.views.pages.admin.rules.form :as form]
|
||||
[auto-ap.views.pages.admin.rules.side-bar :as side-bar]
|
||||
[auto-ap.views.pages.admin.rules.table :as table]
|
||||
[auto-ap.views.pages.data-page :as data-page]
|
||||
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||
[clojure.set :as set]
|
||||
[re-frame.core :as re-frame]
|
||||
[vimsical.re-frame.fx.track :as track]))
|
||||
|
||||
;; EVENTS
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::params-change
|
||||
[with-user ]
|
||||
(fn [{:keys [user]} [_ params]]
|
||||
{:graphql {:token user
|
||||
:owns-state {:single [::data-page/page ::page]}
|
||||
:query-obj {:venia/queries [{:query/data [:transaction_rule_page
|
||||
{:sort (:sort params)
|
||||
:start (:start params 0)
|
||||
:per-page (:per-page params)
|
||||
:vendor-id (:id (:vendor params))
|
||||
:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||
:note (:note params)
|
||||
:description (:description params)}
|
||||
[[:transaction-rules default-read]
|
||||
:total
|
||||
:start
|
||||
:end]]
|
||||
:query/alias :result}]}
|
||||
:on-success (fn [result]
|
||||
[::data-page/received ::page
|
||||
(set/rename-keys (:result result)
|
||||
{:transaction-rules :data})])}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::new-rule-clicked
|
||||
(fn [_ _]
|
||||
{:dispatch [::form/adding {:client @(re-frame/subscribe [::subs/client])}]}))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [_]
|
||||
{:dispatch-n [[::events/yodlee-merchants-needed]]
|
||||
::forward/register [{:id ::page
|
||||
:events #{::form/updated}
|
||||
:event-fn (fn [[_ result]]
|
||||
[::data-page/updated-entity ::page result])}
|
||||
{:id ::deleted-transaction-rule
|
||||
:events #{::table/deleted-transaction-rule }
|
||||
:event-fn (fn [[_ result]]
|
||||
[::data-page/deleted-entity ::page result])}]
|
||||
::track/register {:id ::params
|
||||
:subscription [::data-page/params ::page]
|
||||
:event-fn (fn [params]
|
||||
[::params-change params])}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn [_]
|
||||
{:dispatch [::data-page/dispose ::page]
|
||||
::forward/dispose [{:id ::page}
|
||||
{:id ::deleted-transaction-rule}]
|
||||
::track/dispose {:id ::params}}))
|
||||
|
||||
;; VIEWS
|
||||
(def rules-content
|
||||
(with-meta
|
||||
(fn []
|
||||
(let [user @(re-frame/subscribe [::subs/user])]
|
||||
[:div
|
||||
[:h1.title "Transaction Rules"]
|
||||
(when (= "admin" (:user/role user))
|
||||
[:div.is-pulled-right
|
||||
[buttons/new-button {:event [::new-rule-clicked]
|
||||
:class "is-primary"
|
||||
:name "Transaction Rule"}]])
|
||||
[table/table {:id :transaction-rules
|
||||
:data-page ::page}]]))
|
||||
{:component-did-mount (dispatch-event [::mounted ])
|
||||
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])}))
|
||||
|
||||
(defn admin-rules-page []
|
||||
(let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::form/form])]
|
||||
[side-bar-layout {:side-bar [admin-side-bar {}
|
||||
[side-bar/rule-side-bar {:data-page ::page}]]
|
||||
:main [rules-content]
|
||||
:right-side-bar [appearing-side-bar {:visible? active?}
|
||||
[form/form {:data-page ::page}]]}]))
|
||||
@@ -1,18 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules.common)
|
||||
|
||||
(def default-read [:id
|
||||
:description
|
||||
:note
|
||||
:amount-gte
|
||||
:amount-lte
|
||||
:dom-gte
|
||||
:dom-lte
|
||||
:transaction-approval-status
|
||||
[:yodlee-merchant [:name :id :yodlee-id]]
|
||||
[:vendor [:name :id]]
|
||||
[:client [:name :id]]
|
||||
[:bank-account [:name :id]]
|
||||
[:accounts [[:account [:id :name :numeric-code :location]]
|
||||
:id
|
||||
:percentage
|
||||
:location]]])
|
||||
@@ -1,373 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules.form
|
||||
(:require
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.forms.builder :as form-builder]
|
||||
[auto-ap.schema :as schema]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components :as com]
|
||||
[auto-ap.views.components.expense-accounts-field
|
||||
:as expense-accounts-field
|
||||
:refer [expense-accounts-field-v2]]
|
||||
[auto-ap.views.components.layouts :as layouts]
|
||||
[auto-ap.views.components.level :refer [left-stack]]
|
||||
[auto-ap.views.pages.admin.rules.common :refer [default-read]]
|
||||
[auto-ap.views.pages.admin.rules.results-modal :as results-modal]
|
||||
[auto-ap.views.utils :refer [coerce-float dispatch-event with-user]]
|
||||
[clojure.string :as str]
|
||||
[malli.core :as m]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]
|
||||
[vimsical.re-frame.cofx.inject :as inject]
|
||||
[vimsical.re-frame.fx.track :as track]))
|
||||
|
||||
;; SUBS
|
||||
|
||||
(re-frame/reg-sub
|
||||
::default-note
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{{:keys [client description amount-lte amount-gte dom-lte dom-gte]} :data}]
|
||||
(str/join " - " (filter (complement str/blank?)
|
||||
[(:code client)
|
||||
description
|
||||
(when (or amount-lte amount-gte)
|
||||
(str (when amount-gte
|
||||
(str amount-gte "<"))
|
||||
"amt"
|
||||
(when amount-lte
|
||||
(str "<" amount-lte))))
|
||||
|
||||
(when (or dom-lte dom-gte)
|
||||
(str (when dom-gte
|
||||
(str dom-gte "<"))
|
||||
"dom"
|
||||
(when dom-lte
|
||||
(str "<" dom-lte))))]))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::query
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{:keys [data] }]
|
||||
{:venia/operation {:operation/type :mutation
|
||||
:operation/name "UpsertTransactionRule"}
|
||||
:venia/queries [{:query/data [:upsert-transaction-rule
|
||||
{:transaction-rule (-> data
|
||||
(select-keys [:id
|
||||
:description
|
||||
:transaction-approval-status
|
||||
:amount-lte
|
||||
:amount-gte
|
||||
:dom-lte
|
||||
:dom-gte
|
||||
:accounts
|
||||
:note])
|
||||
(update :note #(if (str/blank? %)
|
||||
@(re-frame/subscribe [::default-note])
|
||||
%))
|
||||
(assoc :vendor-id (:id (:vendor data)))
|
||||
(assoc :yodlee-merchant-id (:id (:yodlee-merchant data)))
|
||||
(update :description (fn [d] (when d (str/replace d #"\\" "\\\\"))))
|
||||
(update :accounts (fn [as]
|
||||
(map #(-> %
|
||||
(update :id (fn [i] (if (some-> i (str/starts-with? "new-"))
|
||||
nil
|
||||
i)))
|
||||
(assoc :percentage (/ (get-in % [:amount-percentage]) 100 ))
|
||||
(assoc :account-id (get-in % [:account :id]))
|
||||
(select-keys [:percentage :id :location :account-id]))
|
||||
as)))
|
||||
(assoc :client-id (:id (:client data)))
|
||||
(assoc :bank-account-id (:id (:bank-account data))))}
|
||||
default-read]}]}))
|
||||
|
||||
|
||||
(re-frame/reg-sub
|
||||
::test-query
|
||||
:<- [::forms/form ::form]
|
||||
(fn [{:keys [data] }]
|
||||
{:venia/operation {:operation/type :query
|
||||
:operation/name "TestTransactionRule"}
|
||||
:venia/queries [{:query/data [:test-transaction-rule
|
||||
{:transaction-rule (-> data
|
||||
(select-keys [:id
|
||||
:description
|
||||
:amount-lte
|
||||
:amount-gte
|
||||
:dom-lte
|
||||
:dom-gte
|
||||
:note])
|
||||
(update :description (fn [d] (when d (str/replace d #"\\" "\\\\"))))
|
||||
(assoc :yodlee-merchant-id (:id (:yodlee-merchant data)))
|
||||
(assoc :client-id (:id (:client data)))
|
||||
(assoc :bank-account-id (:id (:bank-account data))))}
|
||||
[:id
|
||||
:date
|
||||
:amount
|
||||
[:client [:name]]
|
||||
[:bank-account [:name]]
|
||||
:description-original]]}]}))
|
||||
|
||||
|
||||
|
||||
;; EVENTS
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::adding
|
||||
(fn [db [_ new]]
|
||||
(-> db (forms/start-form ::form (assoc new
|
||||
:description nil
|
||||
:client nil
|
||||
:bank-account nil
|
||||
:note nil
|
||||
:amount-lte nil
|
||||
:amount-gte nil
|
||||
:dom-lte nil
|
||||
:dom-gte nil
|
||||
:vendor nil
|
||||
:transaction-approval-status :unapproved
|
||||
:accounts [{:id (str "new-" (random-uuid))
|
||||
:amount-mode "%"
|
||||
:amount-percentage 100
|
||||
:location nil}])))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::editing
|
||||
(fn [db [_ which]]
|
||||
(-> db (forms/start-form ::form (-> which
|
||||
(select-keys [:description
|
||||
:id
|
||||
:client
|
||||
:bank-account
|
||||
:note
|
||||
:amount-lte
|
||||
:amount-gte
|
||||
:dom-lte
|
||||
:dom-gte
|
||||
:vendor
|
||||
:accounts
|
||||
:yodlee-merchant
|
||||
:transaction-approval-status])
|
||||
|
||||
(update :amount-lte coerce-float)
|
||||
(update :amount-gte coerce-float)
|
||||
(update :accounts (fn [xs]
|
||||
(mapv #(-> %
|
||||
(assoc :amount-percentage (* (:percentage %) 100.0)))
|
||||
xs))))))))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::changed-vendor
|
||||
[(forms/in-form ::form)]
|
||||
(fn [{{{:keys [client]} :data} :db} [_ vendor]]
|
||||
(when (and (:id client) (:id vendor))
|
||||
{:dispatch [::events/vendor-preferences-requested {:client-id (:id client)
|
||||
:vendor-id (:id vendor)
|
||||
:on-success [::changed [:vendor-preferences]]}]})))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::changed-client
|
||||
[(forms/in-form ::form)]
|
||||
(fn [{{{:keys [vendor]} :data} :db} [_ client]]
|
||||
(when (and (:id client) (:id vendor))
|
||||
{:dispatch [::events/vendor-preferences-requested {:client-id (:id client)
|
||||
:vendor-id (:id vendor)
|
||||
:on-success [::changed [:vendor-preferences]]}]})))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::changed
|
||||
(forms/change-handler ::form
|
||||
(fn [data field value]
|
||||
(cond (and (= [:vendor-preferences] field)
|
||||
value
|
||||
(expense-accounts-field/can-replace-with-default? (:accounts data)))
|
||||
[[:accounts] (expense-accounts-field/default-account (:accounts data)
|
||||
(:default-account value)
|
||||
(:total data)
|
||||
[])]
|
||||
|
||||
(= [:client] field)
|
||||
[[:bank-account] nil]
|
||||
:else
|
||||
[]))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::saving
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form) (re-frame/inject-cofx ::inject/sub [::query])]
|
||||
(fn [{:keys [user] ::keys [query]} _]
|
||||
{:graphql
|
||||
{:token user
|
||||
:query-obj query
|
||||
:owns-state {:single ::form}
|
||||
:on-success (fn [result]
|
||||
[::updated (:upsert-transaction-rule result)])}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::test-clicked
|
||||
[with-user (forms/triggers-loading ::form) (forms/in-form ::form) (re-frame/inject-cofx ::inject/sub [::test-query])]
|
||||
(fn [{:keys [user] ::keys [test-query]} _]
|
||||
{:graphql
|
||||
{:token user
|
||||
:owns-state {:single ::test}
|
||||
:query-obj test-query
|
||||
:on-success [::succeeded-test]
|
||||
:on-error [::forms/save-error ::form]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::updated
|
||||
[(forms/triggers-stop ::form)]
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (forms/start-form db ::form {:client @(re-frame/subscribe [::subs/client])})}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::succeeded-test
|
||||
[(forms/triggers-stop-loading ::form)]
|
||||
(fn [_ [_ result]]
|
||||
|
||||
{:dispatch [::results-modal/opening (:test-transaction-rule result) nil false]}))
|
||||
|
||||
|
||||
|
||||
;; VIEWS
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [_ _]
|
||||
{::track/register [{:id ::client
|
||||
:subscription [::forms/field ::form [:client]]
|
||||
:event-fn (fn [c]
|
||||
[::changed-client c])}
|
||||
{:id ::vendor-change
|
||||
:subscription [::forms/field ::form [:vendor]]
|
||||
:event-fn (fn [v]
|
||||
[::changed-vendor v])}]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn []
|
||||
{::track/dispose [{:id ::client}
|
||||
{:id ::vendor-change}]}))
|
||||
|
||||
(def rule-schema
|
||||
(m/schema [:map
|
||||
[:client {:optional true}
|
||||
[:maybe schema/reference]]
|
||||
[:bank-account {:optional true}
|
||||
[:maybe schema/reference]]
|
||||
[:description
|
||||
schema/not-empty-string]
|
||||
[:amount-gte {:optional true}
|
||||
[:maybe schema/money]]
|
||||
[:amount-lte {:optional true}
|
||||
[:maybe schema/money]]
|
||||
[:dom-gte {:optional true}
|
||||
[:maybe [:int {:min 1 :max 31}]]]
|
||||
[:dom-lte {:optional true}
|
||||
[:maybe [:int {:min 1 :max 31}]]]
|
||||
[:vendor {:optional true}
|
||||
[:maybe schema/reference]]
|
||||
[:transaction-approval-status {:optional true}
|
||||
[:maybe schema/approval-status]]
|
||||
[:note {:optional true}
|
||||
[:maybe :string]]]))
|
||||
|
||||
(defn form-contents []
|
||||
[layouts/side-bar {:on-close (dispatch-event [::forms/form-closing ::form ])}
|
||||
(let [{:keys [data]} @(re-frame/subscribe [::forms/form ::form])
|
||||
default-note @(re-frame/subscribe [::default-note])
|
||||
test-state @(re-frame/subscribe [::status/single ::test])]
|
||||
[form-builder/builder {:change-event [::changed]
|
||||
:submit-event [::saving ]
|
||||
:id ::form
|
||||
:schema rule-schema}
|
||||
[form-builder/section {:title "Transaction Rule"}
|
||||
[form-builder/field-v2 {:required? true
|
||||
:field :client}
|
||||
"Client"
|
||||
[com/entity-typeahead {:entities @(re-frame/subscribe [::subs/clients])
|
||||
:auto-focus true
|
||||
:entity->text :name}]]
|
||||
|
||||
|
||||
[form-builder/field-v2 {:field [:bank-account]}
|
||||
"Bank account"
|
||||
[com/entity-typeahead {:entities @(re-frame/subscribe [::subs/real-bank-accounts-for-client (:client data)])
|
||||
:entity->text :name}]]
|
||||
|
||||
[form-builder/field-v2 {:field :description
|
||||
:required? true}
|
||||
[:span "Description (" [:a {:href "https://regex101.com" :target "_new"} "regex tester"] ")" ]
|
||||
[:input.input {:type "text"}]]
|
||||
|
||||
[:div.field
|
||||
[:p.help "Amount"]
|
||||
[left-stack
|
||||
[form-builder/raw-field-v2 {:field :amount-gte}
|
||||
[com/money-input {:placeholder ">="}]]
|
||||
"-"
|
||||
[form-builder/raw-field-v2 {:field :amount-lte}
|
||||
[com/money-input {:placeholder "<="}]]]]
|
||||
|
||||
[:div.field
|
||||
[:p.help "Day of month"]
|
||||
[left-stack
|
||||
[form-builder/raw-field-v2 {:field :dom-gte}
|
||||
[com/number-input {:placeholder ">="
|
||||
:style {:width "7em"}}]]
|
||||
"-"
|
||||
[form-builder/raw-field-v2 {:field :dom-lte}
|
||||
[com/number-input {:placeholder "<="
|
||||
:style {:width "7em"}}]]]]
|
||||
|
||||
|
||||
[:h2.title.is-4 "Outcomes"]
|
||||
|
||||
[form-builder/field-v2 {:field :vendor}
|
||||
"Assign Vendor"
|
||||
[com/search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_vendor
|
||||
{:query i}
|
||||
[:name :id]])}]]
|
||||
|
||||
[form-builder/field-v2 {:field :accounts}
|
||||
"Accounts"
|
||||
[expense-accounts-field-v2 {:descriptor "account asssignment"
|
||||
:percentage-only? true
|
||||
:client (:client data)
|
||||
:locations (into ["Shared"] @(re-frame/subscribe [::subs/locations-for-client-or-bank-account (:id (:client data)) (:id (:bank-account data))]))
|
||||
:max 100}]]
|
||||
|
||||
[form-builder/field-v2 {:field :transaction-approval-status}
|
||||
"Approval Status"
|
||||
[com/button-radio-input
|
||||
{:options [[:unapproved "Unapproved"]
|
||||
[:requires-feedback "Client Review"]
|
||||
[:approved "Approved"]
|
||||
[:excluded "Excluded from Ledger"]]}]]
|
||||
|
||||
[form-builder/field-v2 {:field :note}
|
||||
"Note"
|
||||
[:input.input {:type "text"
|
||||
:placeholder default-note}]]
|
||||
|
||||
[:div.is-divider]
|
||||
[form-builder/error-notification]
|
||||
[:div.columns
|
||||
[:div.column
|
||||
[:a.button.is-medium.is-fullwidth.is-outlined {:on-click (dispatch-event [::test-clicked])
|
||||
:disabled (status/disabled-for test-state)
|
||||
:class (status/class-for test-state)}
|
||||
"Test Rule"]]
|
||||
[:div.column
|
||||
[form-builder/submit-button {:class ["is-fullwidth"]}
|
||||
"Save"]]]]])])
|
||||
|
||||
(defn form [_]
|
||||
(r/create-class
|
||||
{:display-name "rule-form"
|
||||
:component-did-mount #(re-frame/dispatch [::mounted])
|
||||
:component-will-unmount #(re-frame/dispatch [::unmounted])
|
||||
:reagent-render (fn [p]
|
||||
[form-contents p])}))
|
||||
@@ -1,136 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules.results-modal
|
||||
(:require [auto-ap.views.utils :refer [date->str dispatch-event with-user]]
|
||||
[auto-ap.views.pages.transactions.common :refer [transaction-read]]
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[auto-ap.status :as status]))
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-sub
|
||||
::test-results
|
||||
(fn [db]
|
||||
(::test-results db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::runnable?
|
||||
(fn [db]
|
||||
(::runnable? db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::checked
|
||||
(fn [db]
|
||||
(::checked db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::all-checked
|
||||
(fn [db]
|
||||
(::all-checked db nil)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::checked-count
|
||||
:<- [::checked]
|
||||
(fn [checked]
|
||||
(if (seq checked)
|
||||
(count checked)
|
||||
0)))
|
||||
|
||||
(defn results-body []
|
||||
(let [runnable? @(re-frame/subscribe [::runnable?])
|
||||
checked @(re-frame/subscribe [::checked])
|
||||
all-checked @(re-frame/subscribe [::all-checked])]
|
||||
[:table.table.is-fullwidth.compact
|
||||
[:tr
|
||||
(when runnable?
|
||||
[:th {:style {:width "2em"}}
|
||||
[:input.checkbox {:type "checkbox"
|
||||
:checked all-checked
|
||||
:on-change (dispatch-event [::toggle-all])}]])
|
||||
[:th "Client"]
|
||||
[:th "Bank Account"]
|
||||
[:th "Description"]
|
||||
[:th "Date"]
|
||||
[:th "Amount"]]
|
||||
(for [{:keys [id client bank-account description-original date amount]} @(re-frame/subscribe [::test-results])]
|
||||
|
||||
^{:key id}
|
||||
[:tr
|
||||
(when runnable?
|
||||
[:td
|
||||
[:input.checkbox {:type "checkbox"
|
||||
:checked (boolean (checked id))
|
||||
:on-change (dispatch-event [::toggle id])}]])
|
||||
[:td (:name client)]
|
||||
[:td (:name bank-account)]
|
||||
[:td description-original]
|
||||
[:td (when date (date->str date))]
|
||||
[:td amount]])]))
|
||||
|
||||
(defn foot [params]
|
||||
(let [runnable? @(re-frame/subscribe [::runnable?])
|
||||
all-checked @(re-frame/subscribe [::all-checked])
|
||||
checked-count @(re-frame/subscribe [::checked-count])
|
||||
status @(re-frame/subscribe [::status/single ::apply])]
|
||||
(when runnable?
|
||||
[:div
|
||||
[:button.button.is-primary {:disabled (or (boolean (= checked-count 0))
|
||||
(status/disabled-for status))
|
||||
:class (status/class-for status)
|
||||
:on-click (dispatch-event [::apply-rule params])}
|
||||
(str "Apply to " checked-count " transactions")]
|
||||
|
||||
[:button.button.is-warning {:disabled (or (boolean (not all-checked))
|
||||
(status/disabled-for status))
|
||||
:class (status/class-for status)
|
||||
:on-click (dispatch-event [::apply-rule (assoc params :all? true)])}
|
||||
(str "Apply to all transactions")]])))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::opening
|
||||
(fn [{:keys [db]} [_ results transaction-rule-id runnable?]]
|
||||
{:db (-> db
|
||||
(assoc ::all-checked false)
|
||||
(assoc ::test-results results)
|
||||
(assoc ::transaction-rule-id transaction-rule-id)
|
||||
(assoc ::checked #{})
|
||||
(assoc ::runnable? runnable?))
|
||||
:dispatch [::modal/modal-requested {:title "Rule results"
|
||||
:class "wide"
|
||||
:body [results-body]
|
||||
:status-from [::status/single ::apply]
|
||||
:foot [foot]}]}))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::toggle
|
||||
[(re-frame/path [::checked])]
|
||||
(fn [checked [_ which]]
|
||||
(let [checked (or checked #{})]
|
||||
(if (checked which)
|
||||
(disj checked which)
|
||||
(conj checked which)))))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::toggle-all
|
||||
(fn [db [_ _]]
|
||||
(let [{::keys [all-checked test-results]} db]
|
||||
(assoc db
|
||||
::all-checked (not all-checked)
|
||||
::checked (if all-checked
|
||||
#{}
|
||||
(into #{} (map :id test-results)))))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::apply-rule
|
||||
[with-user]
|
||||
(fn [{:keys [db user]} [_ params]]
|
||||
{:graphql
|
||||
{:token user
|
||||
:owns-state {:single ::apply}
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "MatchTransactionRules"}
|
||||
:venia/queries [{:query/data [:match-transaction-rules
|
||||
{:transaction-ids (seq @(re-frame/subscribe [::checked]))
|
||||
:all (boolean (:all? params))
|
||||
:transaction-rule-id (::transaction-rule-id db)}
|
||||
transaction-read]}]}
|
||||
:on-success [::modal/modal-closed]}}))
|
||||
@@ -1,33 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules.side-bar
|
||||
(:require
|
||||
[auto-ap.views.components.typeahead.vendor
|
||||
:refer [search-backed-typeahead]]
|
||||
[auto-ap.views.pages.data-page :as data-page]
|
||||
[auto-ap.views.utils :refer [dispatch-value-change]]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn rule-side-bar [{:keys [data-page]}]
|
||||
[:div
|
||||
[:p.menu-label "Vendor"]
|
||||
[:div
|
||||
[search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_vendor
|
||||
{:query i}
|
||||
[:name :id]])
|
||||
:type "typeahead-v3"
|
||||
:on-change #(re-frame/dispatch [::data-page/filter-changed data-page :vendor %])
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :vendor])}]]
|
||||
|
||||
[:p.menu-label "Note"]
|
||||
[:div
|
||||
[:div.field
|
||||
[:div.control [:input.input {:placeholder "HOME DEPOT"
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :note])
|
||||
:on-change (dispatch-value-change [::data-page/filter-changed data-page :note])} ]]]]
|
||||
[:p.menu-label "Description"]
|
||||
[:div
|
||||
[:div.field
|
||||
[:div.control [:input.input {:placeholder "HOME DEPOT"
|
||||
:value @(re-frame/subscribe [::data-page/filter data-page :description])
|
||||
:on-change (dispatch-value-change [::data-page/filter-changed data-page :description])} ]]]]])
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
(ns auto-ap.views.pages.admin.rules.table
|
||||
(:require
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.buttons :as buttons]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[auto-ap.views.pages.admin.rules.form :as form]
|
||||
[auto-ap.views.pages.admin.rules.results-modal :as results-modal]
|
||||
[auto-ap.views.pages.data-page :as data-page]
|
||||
[auto-ap.views.utils
|
||||
:refer [->$ action-cell-width dispatch-event with-user]]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::run-clicked
|
||||
[with-user]
|
||||
(fn [{:keys [user]} [_ which]]
|
||||
{:graphql
|
||||
{:token user
|
||||
:owns-state {:multi ::run
|
||||
:which (:id which)}
|
||||
:query-obj {:venia/operation {:operation/type :query
|
||||
:operation/name "RunTransactionRule"}
|
||||
:venia/queries [{:query/data [:run-transaction-rule
|
||||
{:transaction-rule-id (:id which)}
|
||||
[:id
|
||||
:date
|
||||
:amount
|
||||
[:client [:name]]
|
||||
[:bank-account [:name]]
|
||||
:description-original]]}]}
|
||||
:on-success [::succeeded-run (:id which)]}}))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::succeeded-run
|
||||
(fn [_ [_ transaction-rule-id result]]
|
||||
{:dispatch [::results-modal/opening (:run-transaction-rule result) transaction-rule-id true]}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::specific-table-params
|
||||
(fn [db]
|
||||
(::table-params db)))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::unmounted
|
||||
(fn [db]
|
||||
(status/reset-multi db ::run)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::table-params
|
||||
:<- [::specific-table-params]
|
||||
:<- [::subs/query-params]
|
||||
(fn [[specific-table-params query-params]]
|
||||
(merge (select-keys query-params #{:start :sort}) specific-table-params )))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::deleted-transaction-rule
|
||||
(fn []
|
||||
{:dispatch [::modal/modal-closed]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::delete-transaction-rule
|
||||
[with-user]
|
||||
(fn [{:keys [user]} [_ id]]
|
||||
{:graphql
|
||||
{:token user
|
||||
:owns-state {:single ::delete-transaction-rule}
|
||||
:query-obj {:venia/operation {:operation/type :mutation
|
||||
:operation/name "DeleteTransactionRule"}
|
||||
:venia/queries [{:query/data [:delete-transaction-rule
|
||||
{:transaction-rule-id id}]}]}
|
||||
:on-success [::deleted-transaction-rule]}}))
|
||||
|
||||
|
||||
;; TODO count how many transactions
|
||||
(re-frame/reg-event-fx
|
||||
::request-delete
|
||||
(fn [_ [_ which]]
|
||||
{:dispatch [::modal/modal-requested {:title "Confirmation"
|
||||
:body [:div "Are you sure you want to delete transaction rule '" (:description which) "'? Any previously transactions will remain updated, but the rule association will be lost."]
|
||||
:cancel? true
|
||||
:confirm {:value "Delete Transaction Rule"
|
||||
:class "is-danger"
|
||||
:status-from [::status/single ::delete-transaction-rule]
|
||||
:on-click (dispatch-event [::delete-transaction-rule (:id which)] )}
|
||||
:close-event [::status/completed ::delete-transaction-rule]}]}))
|
||||
|
||||
|
||||
|
||||
(defn table* [{:keys [data-page]}]
|
||||
(let [{:keys [data]} @(re-frame/subscribe [::data-page/page data-page])
|
||||
_ @(re-frame/subscribe [::subs/client])
|
||||
states @(re-frame/subscribe [::status/multi ::run])]
|
||||
[grid/grid {:data-page data-page
|
||||
:column-count 6}
|
||||
[grid/controls data]
|
||||
[grid/table {:fullwidth true}
|
||||
[grid/header
|
||||
[grid/row {}
|
||||
[grid/sortable-header-cell {:sort-key "client"
|
||||
:sort-name "Client"}
|
||||
"Client"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "bank-account"
|
||||
:sort-name "Bank Account"}
|
||||
"Bank Account"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "description"
|
||||
:sort-name "Description"}
|
||||
"Description"]
|
||||
|
||||
[grid/header-cell {:style {:width "12em"}} "Amount"]
|
||||
|
||||
[grid/sortable-header-cell {:sort-key "note"
|
||||
:sort-name "Note"}
|
||||
"Note"]
|
||||
|
||||
[grid/header-cell {:style {:width (action-cell-width 3)}}]]]
|
||||
[grid/body
|
||||
(for [{:keys [client bank-account description amount-lte amount-gte note id] :as r} (:data data)]
|
||||
^{:key id}
|
||||
[grid/row {:class (:class r) :id id}
|
||||
[grid/cell {} (:name client)]
|
||||
[grid/cell {} (:name bank-account)]
|
||||
[grid/cell {} description]
|
||||
[grid/cell {:class "has-text-right"}
|
||||
(cond (and amount-gte amount-lte)
|
||||
(str (->$ amount-gte) " - " (->$ amount-lte))
|
||||
|
||||
amount-gte
|
||||
(str ">=" (->$ amount-gte))
|
||||
|
||||
amount-lte
|
||||
(str "<=" (->$ amount-lte))
|
||||
|
||||
:else
|
||||
"")]
|
||||
[grid/cell {} note]
|
||||
[grid/cell {}
|
||||
[:div.buttons
|
||||
[buttons/fa-icon {:event [::run-clicked r] :icon :fa-play :class (status/class-for (get states (:id r)))}]
|
||||
[buttons/sl-icon {:event [::request-delete r] :icon :icon-bin-2}]
|
||||
[buttons/fa-icon {:event [::form/editing r] :icon :fa-pencil}]]]])]]
|
||||
[grid/bottom-paginator data]]))
|
||||
|
||||
(defn table []
|
||||
(r/create-class {:component-will-unmount (dispatch-event [::unmounted])
|
||||
:reagent-render (fn [params]
|
||||
[table* params])}))
|
||||
@@ -1,78 +0,0 @@
|
||||
(ns auto-ap.views.pages.company.other
|
||||
(:require
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||
[auto-ap.views.components.buttons :refer [fa-icon]]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.shared-views.company.sidebar :refer [company-side-bar]]
|
||||
[goog.crypt.base64 :as b64]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[vimsical.re-frame.cofx.inject :as inject]
|
||||
[auto-ap.status :as status]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::ready
|
||||
(fn [{:keys [db] } [_ result]]
|
||||
{:db (assoc db ::export-result result)}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::export-result
|
||||
(fn [db]
|
||||
(::export-result db)))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::export-vendors
|
||||
[(re-frame/inject-cofx ::inject/sub [::subs/client]) with-user]
|
||||
(fn [{:keys [db user] ::subs/keys [client]}]
|
||||
{:http {:token user
|
||||
:method :get
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/vendors/company/export?client=" (:code client))
|
||||
:owns-state {:single ::export-vendors}
|
||||
:on-success [::ready]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn [{:keys [db]} _]
|
||||
{:db (dissoc db ::export-result)}))
|
||||
|
||||
(defn company-other-content []
|
||||
(let [client @(re-frame/subscribe [::subs/client])
|
||||
state @(re-frame/subscribe [::status/single ::export-vendors])
|
||||
export-result @(re-frame/subscribe [::export-result])]
|
||||
(if client
|
||||
[:div
|
||||
[:h1.title "Other"]
|
||||
[status/status-notification [::status/single ::export-vendors]]
|
||||
|
||||
|
||||
[fa-icon {:icon "fa-external-link"
|
||||
:class (into (status/class-for state) ["is-primary" ])
|
||||
:disabled (status/disabled-for state)
|
||||
:event [::export-vendors]
|
||||
}
|
||||
[:div
|
||||
(str " Export " (:name client) " Vendors")
|
||||
]]
|
||||
(when export-result
|
||||
[:<>
|
||||
[:div
|
||||
"Ready! Click "
|
||||
[:a {:href (str "data:attachment/csv;base64," (b64/encodeString export-result))
|
||||
:target "_blank"
|
||||
:download (str "vendors-" (:code client) ".csv")}
|
||||
"here"]
|
||||
" to download"]])
|
||||
]
|
||||
[:div "Please select a company."])))
|
||||
|
||||
|
||||
(defn company-other-page []
|
||||
(reagent/create-class
|
||||
{:reagent-render (fn []
|
||||
[side-bar-layout {:side-bar [company-side-bar {}]
|
||||
:main [company-other-content]}])
|
||||
:component-will-unmount #(re-frame/dispatch [::unmounted])}))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
(ns auto-ap.views.pages.company.side-bar
|
||||
(:require
|
||||
[auto-ap.routes :as routes]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.utils :refer [active-when]]
|
||||
[bidi.bidi :as bidi]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn company-side-bar []
|
||||
(let [ap @(re-frame/subscribe [::subs/active-page])]
|
||||
[:div
|
||||
[:ul.menu-list
|
||||
[:li.menu-item
|
||||
[:a.item {:href (bidi/path-for routes/routes :reports)
|
||||
:class [(active-when ap = :reports)]}
|
||||
[:span {:class "icon icon-receipt" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Reports"]]]]
|
||||
[:li.menu-item
|
||||
[:a {:href (bidi/path-for routes/routes :plaid), :class (str "item" (active-when ap = :plaid))}
|
||||
[:span {:class "icon icon-saving-bank-1" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Plaid Link"]]]
|
||||
[:li.menu-item
|
||||
[:a {:href (bidi/path-for routes/routes :yodlee2), :class (str "item" (active-when ap = :yodlee2))}
|
||||
[:span {:class "icon icon-saving-bank-1" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Yodlee Link"]]]
|
||||
[:li.menu-item
|
||||
[:a {:href (bidi/path-for routes/routes :company-other), :class (str "item" (active-when ap = :company-other))}
|
||||
[:span {:class "icon icon-cog-play-1" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Other"]]]]))
|
||||
@@ -1,141 +0,0 @@
|
||||
(ns auto-ap.views.pages.company.yodlee2
|
||||
(:require
|
||||
[auto-ap.effects.forward :as forward]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.shared-views.company.sidebar :refer [company-side-bar]]
|
||||
[auto-ap.views.pages.company.yodlee2.table :as table]
|
||||
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[vimsical.re-frame.cofx.inject :as inject]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::authentication
|
||||
(fn [db]
|
||||
(-> db ::authentication)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::params
|
||||
:<- [::table/params]
|
||||
(fn [table-params]
|
||||
table-params))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::yodlee-provider-accounts
|
||||
(fn [db]
|
||||
(::yodlee-provider-accounts db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::page
|
||||
:<- [::params]
|
||||
:<- [::yodlee-provider-accounts]
|
||||
(fn [[params all-yodlee-provider-accounts]]
|
||||
(assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) (:yodlee-provider-accounts all-yodlee-provider-accounts) )
|
||||
:data (grid/virtual-paginate (:start params) (:per-page params) (:yodlee-provider-accounts all-yodlee-provider-accounts)))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::data-requested
|
||||
[with-user (re-frame/inject-cofx ::inject/sub [::subs/client])]
|
||||
(fn [{:keys [user] ::subs/keys [client]} _]
|
||||
{:graphql {:token user
|
||||
:owns-state {:single ::page}
|
||||
:query-obj {:venia/queries [[:yodlee-provider-account-page {:client-id (:id client)}
|
||||
[[:yodlee-provider-accounts [:id :last-updated :status :detailed-status
|
||||
[:client [:id]]
|
||||
[:accounts [:id :name :number :available-balance]]]]
|
||||
:count]]]}
|
||||
:on-success [::received]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::mounted
|
||||
(fn [{:keys [db]} _]
|
||||
{:dispatch [::data-requested]
|
||||
::forward/register {:id ::yodlee-account-refreshed
|
||||
:events #{::table/refreshed ::table/provider-account-deleted}
|
||||
:event-fn (fn [[_ _]]
|
||||
[::data-requested])}
|
||||
:db (dissoc db ::authentication)}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::unmounted
|
||||
(fn [_ _]
|
||||
{::forward/dispose {:id ::yodlee-account-refreshed}}))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::authenticate-with-yodlee
|
||||
[with-user]
|
||||
(fn [{:keys [user]} [_ client]]
|
||||
{:http {:token user
|
||||
:method :get
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/yodlee2/fastlink?client=" client)
|
||||
:owns-state {:single ::authenticating}
|
||||
:on-success [::authenticated]
|
||||
:on-error [::save-error]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::authenticated
|
||||
(fn [{:keys [db]} [_ authentication]]
|
||||
{:db (-> db
|
||||
(assoc-in [::authentication] authentication))}))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::received
|
||||
(fn [db [_ d]]
|
||||
(assoc-in db [::yodlee-provider-accounts] (:yodlee-provider-account-page d))))
|
||||
|
||||
|
||||
(defn yodlee-provider-accounts-table []
|
||||
[table/table {:page @(re-frame/subscribe [::page])
|
||||
:status @(re-frame/subscribe [::status/single ::page])}])
|
||||
|
||||
|
||||
(defn yodlee-link-button []
|
||||
[:div
|
||||
(let [authentication @(re-frame/subscribe [::authentication])
|
||||
status @(re-frame/subscribe [::status/single ::authenticating])
|
||||
client-code (:code @(re-frame/subscribe [::subs/client]))]
|
||||
(cond (and authentication client-code)
|
||||
[:div
|
||||
"Authentication successful!"
|
||||
[:div#fa-spot]
|
||||
[:button.button.is-primary {:on-click (fn []
|
||||
(.open (.-fastlink js/window)
|
||||
#js {"fastLinkURL" (:url authentication)
|
||||
"accessToken" (:token authentication)
|
||||
"params" #js { "configName" "Aggregation"}}
|
||||
"fa-spot")
|
||||
)}
|
||||
[:span [:span.icon [:i.fa.fa-external-link]] " Go to yodlee"]]]
|
||||
|
||||
client-code
|
||||
[:button.button.is-primary {:disabled (status/disabled-for status)
|
||||
:class (status/class-for status)
|
||||
:on-click (dispatch-event [::authenticate-with-yodlee client-code])}
|
||||
"Authenticate with Yodlee (" client-code ")"]
|
||||
|
||||
:else
|
||||
nil))])
|
||||
|
||||
(defn admin-yodlee-provider-accounts-content []
|
||||
[:div
|
||||
[:h1.title "Yodlee Provider Accounts"]
|
||||
[yodlee-provider-accounts-table]
|
||||
[yodlee-link-button]])
|
||||
|
||||
|
||||
(defn admin-yodlee-provider-accounts-page []
|
||||
(let [user (re-frame/subscribe [::subs/user])]
|
||||
(reagent/create-class
|
||||
{:component-will-unmount #(re-frame/dispatch [::unmounted])
|
||||
:component-did-mount #(re-frame/dispatch [::mounted])
|
||||
:reagent-render (fn []
|
||||
(if (not= "manager" (:user/role @user))
|
||||
[side-bar-layout {:side-bar [company-side-bar {}]
|
||||
:main [admin-yodlee-provider-accounts-content]}]
|
||||
[:div "Not authorized"]))})))
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
(ns auto-ap.views.pages.company.yodlee2.form
|
||||
(:require
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(def form
|
||||
(r/create-class {
|
||||
:component-did-mount (fn [this]
|
||||
(let [{:keys [authentication provider-account-id]} (r/props this)]
|
||||
(try
|
||||
(println (js/parseInt provider-account-id) (:url authentication) (:token authentication))
|
||||
(.open (.-fastlink js/window)
|
||||
#js {"fastLinkURL" (:url authentication)
|
||||
"accessToken" (:token authentication)
|
||||
"params" #js {"configName" "Aggregation"
|
||||
"providerAccountId" (js/parseInt provider-account-id)
|
||||
"flow" "edit"}}
|
||||
"fa-modal-spot")
|
||||
(catch js/Error e
|
||||
(println e)))))
|
||||
|
||||
:reagent-render (fn [_]
|
||||
[:div#fa-modal-spot])}))
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::reauthenticate-start
|
||||
(fn [_ [_ provider-account-id authentication]]
|
||||
{:dispatch [::modal/modal-requested {:title (str "Reauthenticate " provider-account-id)
|
||||
:body [form {:provider-account-id provider-account-id
|
||||
:authentication authentication}]
|
||||
:cancel? false}]}))
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
(ns auto-ap.views.pages.company.yodlee2.table
|
||||
(:require [auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.buttons :as buttons]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[auto-ap.views.pages.company.yodlee2.form :as form]
|
||||
[auto-ap.views.utils :refer [->$ action-cell-width date->str with-user dispatch-event]]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::refreshed
|
||||
[with-user ]
|
||||
(fn [_ _]
|
||||
;; this is tracked in yodlee main, for refreshing
|
||||
{}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::request-refresh
|
||||
[with-user ]
|
||||
(fn [{:keys [user]} [_ provider-account client-id ]]
|
||||
{:http {:token user
|
||||
:method :post
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/yodlee2/provider-accounts/refresh/")
|
||||
:owns-state {:multi ::refresh
|
||||
:which provider-account}
|
||||
:body {:client-id client-id
|
||||
:provider-account-id provider-account}
|
||||
:on-success [::refreshed provider-account]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::provider-account-deleted
|
||||
(fn [_ _]
|
||||
{:dispatch [::modal/modal-closed ]}))
|
||||
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::request-login-form
|
||||
[with-user ]
|
||||
(fn [{:keys [user]} [_ provider-account client-id]]
|
||||
{:http {:token user
|
||||
:method :get
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/yodlee2/fastlink?client-id=" client-id)
|
||||
:owns-state {:multi ::request-login-form
|
||||
:which (:id provider-account)}
|
||||
:on-success [::form/reauthenticate-start provider-account]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::delete-provider-account
|
||||
[with-user ]
|
||||
(fn [{:keys [user]} [_ provider-account-id ]]
|
||||
{:http {:token user
|
||||
:method :post
|
||||
:owns-state {:single ::delete-provider-account}
|
||||
:headers {"Content-Type" "application/edn"}
|
||||
:uri (str "/api/yodlee2/provider-accounts/delete/" )
|
||||
:body {:client-id (:id @(re-frame/subscribe [::subs/client]))
|
||||
:provider-account-id provider-account-id}
|
||||
:on-success [::provider-account-deleted provider-account-id]
|
||||
}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::delete-requested
|
||||
[with-user]
|
||||
(fn [_ [_ account-id]]
|
||||
{:dispatch
|
||||
[::modal/modal-requested {:title "Delete Provider account "
|
||||
:body [:div "Are you sure you want to delete provider account " account-id "?"]
|
||||
:confirm {:value "Delete provider account"
|
||||
:status-from [::status/single ::delete-provider-account]
|
||||
:class "is-danger"
|
||||
:on-click (dispatch-event [::delete-provider-account account-id])
|
||||
:close-event [::status/completed ::delete-provider-account]}
|
||||
:cancel? true}]}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::params-changed
|
||||
(fn [{:keys [db]} [_ p]]
|
||||
{:db (assoc db ::params p)}))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::params
|
||||
(fn [db]
|
||||
(-> db ::params)))
|
||||
|
||||
(defn table [{:keys [status page]}]
|
||||
(let [params @(re-frame/subscribe [::params])
|
||||
statuses @(re-frame/subscribe [::status/multi ::refresh])
|
||||
login-statuses @(re-frame/subscribe [::status/multi ::request-login-form])
|
||||
is-admin? @(re-frame/subscribe [::subs/is-admin?])]
|
||||
[grid/grid {:status status
|
||||
:on-params-change (fn [p]
|
||||
(re-frame/dispatch [::params-changed p]))
|
||||
:params params
|
||||
:column-count 4}
|
||||
[grid/controls page]
|
||||
[grid/table {:fullwidth true}
|
||||
[grid/header
|
||||
[grid/row {}
|
||||
[grid/header-cell {:style {:width "18em"}} "Provider Account"]
|
||||
[grid/header-cell {:style {:width "20em"}} "Status"]
|
||||
[grid/header-cell {:style {:width "20em"}} "Detailed Status"]
|
||||
[grid/header-cell {:style {:width "12em"}} "Last Updated"]
|
||||
[grid/header-cell {} "Accounts"]
|
||||
[grid/header-cell {:style {:width (action-cell-width 3)}}]]]
|
||||
[grid/body
|
||||
(for [{:keys [id name accounts status detailed-status last-updated] :as c} (:data page)]
|
||||
^{: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 {}
|
||||
(when is-admin?
|
||||
[:div.buttons
|
||||
[buttons/fa-icon {:event
|
||||
[::request-login-form (:id c) (:id (:client c))]
|
||||
:class (status/class-for (get login-statuses (:id 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"}]])]])]]
|
||||
]))
|
||||
Reference in New Issue
Block a user