diff --git a/src/clj/auto_ap/routes/invoices.clj b/src/clj/auto_ap/routes/invoices.clj index 20749e25..cbc682a5 100644 --- a/src/clj/auto_ap/routes/invoices.clj +++ b/src/clj/auto_ap/routes/invoices.clj @@ -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))}) diff --git a/src/clj/auto_ap/ssr/components/user_dropdown.clj b/src/clj/auto_ap/ssr/components/user_dropdown.clj index 485156c0..a30cdb71 100644 --- a/src/clj/auto_ap/ssr/components/user_dropdown.clj +++ b/src/clj/auto_ap/ssr/components/user_dropdown.clj @@ -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 ")} diff --git a/src/cljc/auto_ap/client_routes.cljc b/src/cljc/auto_ap/client_routes.cljc index fb9c4528..9eb04744 100644 --- a/src/cljc/auto_ap/client_routes.cljc +++ b/src/cljc/auto_ap/client_routes.cljc @@ -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 diff --git a/src/cljs/auto_ap/views/main.cljs b/src/cljs/auto_ap/views/main.cljs index cb2399ce..affe1917 100644 --- a/src/cljs/auto_ap/views/main.cljs +++ b/src/cljs/auto_ap/views/main.cljs @@ -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]) diff --git a/src/cljs/auto_ap/views/pages/admin/excel_import.cljs b/src/cljs/auto_ap/views/pages/admin/excel_import.cljs deleted file mode 100644 index 8158d955..00000000 --- a/src/cljs/auto_ap/views/pages/admin/excel_import.cljs +++ /dev/null @@ -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})) diff --git a/src/cljs/auto_ap/views/pages/admin/import_batches.cljs b/src/cljs/auto_ap/views/pages/admin/import_batches.cljs deleted file mode 100644 index 1c404508..00000000 --- a/src/cljs/auto_ap/views/pages/admin/import_batches.cljs +++ /dev/null @@ -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]}]) - diff --git a/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs b/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs deleted file mode 100644 index 6cd3416e..00000000 --- a/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs +++ /dev/null @@ -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])})) diff --git a/src/cljs/auto_ap/views/pages/admin/rules.cljs b/src/cljs/auto_ap/views/pages/admin/rules.cljs deleted file mode 100644 index f9b040b7..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules.cljs +++ /dev/null @@ -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}]]}])) diff --git a/src/cljs/auto_ap/views/pages/admin/rules/common.cljs b/src/cljs/auto_ap/views/pages/admin/rules/common.cljs deleted file mode 100644 index ef1105d6..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules/common.cljs +++ /dev/null @@ -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]]]) diff --git a/src/cljs/auto_ap/views/pages/admin/rules/form.cljs b/src/cljs/auto_ap/views/pages/admin/rules/form.cljs deleted file mode 100644 index e43ec1de..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules/form.cljs +++ /dev/null @@ -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])})) diff --git a/src/cljs/auto_ap/views/pages/admin/rules/results_modal.cljs b/src/cljs/auto_ap/views/pages/admin/rules/results_modal.cljs deleted file mode 100644 index bfc1651e..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules/results_modal.cljs +++ /dev/null @@ -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]}})) diff --git a/src/cljs/auto_ap/views/pages/admin/rules/side_bar.cljs b/src/cljs/auto_ap/views/pages/admin/rules/side_bar.cljs deleted file mode 100644 index 2c2d7187..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules/side_bar.cljs +++ /dev/null @@ -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])} ]]]]]) - diff --git a/src/cljs/auto_ap/views/pages/admin/rules/table.cljs b/src/cljs/auto_ap/views/pages/admin/rules/table.cljs deleted file mode 100644 index 47d69f49..00000000 --- a/src/cljs/auto_ap/views/pages/admin/rules/table.cljs +++ /dev/null @@ -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])})) diff --git a/src/cljs/auto_ap/views/pages/company/other.cljs b/src/cljs/auto_ap/views/pages/company/other.cljs deleted file mode 100644 index 46fcaa4e..00000000 --- a/src/cljs/auto_ap/views/pages/company/other.cljs +++ /dev/null @@ -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])})) - diff --git a/src/cljs/auto_ap/views/pages/company/side_bar.cljs b/src/cljs/auto_ap/views/pages/company/side_bar.cljs deleted file mode 100644 index d135bfe1..00000000 --- a/src/cljs/auto_ap/views/pages/company/side_bar.cljs +++ /dev/null @@ -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"]]]])) diff --git a/src/cljs/auto_ap/views/pages/company/yodlee2.cljs b/src/cljs/auto_ap/views/pages/company/yodlee2.cljs deleted file mode 100644 index eeae1e3a..00000000 --- a/src/cljs/auto_ap/views/pages/company/yodlee2.cljs +++ /dev/null @@ -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"]))}))) - diff --git a/src/cljs/auto_ap/views/pages/company/yodlee2/form.cljs b/src/cljs/auto_ap/views/pages/company/yodlee2/form.cljs deleted file mode 100644 index 89242e14..00000000 --- a/src/cljs/auto_ap/views/pages/company/yodlee2/form.cljs +++ /dev/null @@ -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}]})) - - diff --git a/src/cljs/auto_ap/views/pages/company/yodlee2/table.cljs b/src/cljs/auto_ap/views/pages/company/yodlee2/table.cljs deleted file mode 100644 index e9a8ddab..00000000 --- a/src/cljs/auto_ap/views/pages/company/yodlee2/table.cljs +++ /dev/null @@ -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"}]])]])]] - ]))