191 lines
7.3 KiB
Clojure
191 lines
7.3 KiB
Clojure
(ns auto-ap.views.pages.import-invoices
|
|
(:require [re-frame.core :as re-frame]
|
|
[reagent.core :as reagent]
|
|
[auto-ap.events :as events]
|
|
[auto-ap.subs :as subs]
|
|
[auto-ap.entities.clients :as client]
|
|
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
|
[auto-ap.views.components.invoices.side-bar :refer [invoices-side-bar]]
|
|
[auto-ap.views.utils :refer [dispatch-event]]
|
|
[auto-ap.utils :refer [by]]
|
|
[auto-ap.entities.vendors :as vendor]
|
|
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
|
|
[cljsjs.dropzone :as dropzone]
|
|
[cljs.reader :as edn]))
|
|
(def dropzone
|
|
(let [client (re-frame/subscribe [::subs/client])
|
|
token (re-frame/subscribe [::subs/token])]
|
|
(with-meta
|
|
(fn []
|
|
[:form.dz {:action "/api/invoices/upload"}
|
|
[:div.tile.notification
|
|
[:div.has-text-centered {:style {:padding "80px 0px" :width "100%"}}
|
|
[:span
|
|
[:span {:class "icon"}
|
|
[:i {:class "fa fa-cloud-download"}]]
|
|
"Drop any invoices you want to process here"]]]])
|
|
{:component-did-mount (fn [this]
|
|
(js/Dropzone. (reagent/dom-node this)
|
|
(clj->js {:init (fn []
|
|
(.on (js-this) "success" (fn [_ files]
|
|
(re-frame/dispatch [::invalidated]))))
|
|
:paramName "file"
|
|
:headers {"Authorization" (str "Token " @token)}
|
|
:url (str "/api/invoices/upload"
|
|
(when-let [client-name (-> @client :id)]
|
|
(str "?client=" client-name)))
|
|
:previewsContainer "#dz-hidden"
|
|
:previewTemplate "<div class='dz-hidden-preview'></div>"})))})))
|
|
|
|
(re-frame/reg-sub
|
|
::invoice-page
|
|
(fn [db]
|
|
(-> db ::invoice-page)))
|
|
|
|
(re-frame/reg-sub
|
|
::params
|
|
(fn [db]
|
|
(-> db (::params {}))))
|
|
|
|
(re-frame/reg-event-fx
|
|
::invalidated
|
|
(fn [cofx [_ params]]
|
|
{:dispatch [::params-change @(re-frame/subscribe [::params])]}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::params-change
|
|
(fn [cofx [_ params]]
|
|
|
|
{:db (-> (:db cofx)
|
|
(assoc-in [:status :loading] true)
|
|
(assoc-in [::params] params))
|
|
:graphql {:token (-> cofx :db :user)
|
|
:query-obj (invoice-table/query (assoc params :import-status "pending"))
|
|
:on-success [::received]}}))
|
|
|
|
(re-frame/reg-event-db
|
|
::received
|
|
(fn [db [_ data]]
|
|
(-> db
|
|
(assoc ::invoice-page (first (:invoice-page data)))
|
|
(update-in [::invoice-page] (fn [ip]
|
|
(assoc ip :checked (by :id (:invoices ip)))))
|
|
(assoc-in [:status :loading] false))))
|
|
|
|
(re-frame/reg-event-fx
|
|
::reject-invoices-clicked
|
|
(fn [{:keys [db]} [_ invoices on-success]]
|
|
{:graphql
|
|
{:token (-> db :user)
|
|
:query-obj {:venia/operation {:operation/type :mutation
|
|
:operation/name "RejectInvoices"}
|
|
|
|
:venia/queries [[:reject-invoices
|
|
{:invoices (keys invoices)}
|
|
[]]]}
|
|
:on-success [::invalidated]}
|
|
}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::approve-invoices-clicked
|
|
(fn [{:keys [db]} [_ invoices on-success]]
|
|
{:graphql
|
|
{:token (-> db :user)
|
|
:query-obj {:venia/operation {:operation/type :mutation
|
|
:operation/name "ApproveInvoices"}
|
|
|
|
:venia/queries [[:approve-invoices
|
|
{:invoices (keys invoices)}
|
|
[]]]}
|
|
:on-success [::invalidated]}
|
|
}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::approve-invoices
|
|
(fn [cofx [_ on-success]]
|
|
{:http {:method :post
|
|
:token (-> cofx :db :user)
|
|
:uri (str "/api/invoices/approve"
|
|
(when-let [client-id (:id @(re-frame/subscribe [::subs/client]))]
|
|
(str "?client=" client-id)))
|
|
:on-success on-success
|
|
}}))
|
|
|
|
(re-frame/reg-event-db
|
|
::toggle-check
|
|
(fn [db [_ id invoice]]
|
|
(-> db
|
|
(update-in [::invoice-page :checked] (fn [x]
|
|
(let [x (or x {})]
|
|
(if (x id)
|
|
(dissoc x id)
|
|
(assoc x id invoice))))))))
|
|
|
|
(defn approve-reject-button [checked]
|
|
[:div.is-pulled-right
|
|
|
|
[:button.button.is-success {:on-click (dispatch-event [::approve-invoices-clicked checked])
|
|
:disabled (if (seq checked)
|
|
""
|
|
"disabled")}
|
|
"Approve "
|
|
(when (> (count checked ))
|
|
(str
|
|
(count checked)
|
|
" invoices"))
|
|
|
|
|
|
[:span " "]]
|
|
[:button.button.is-danger {:on-click (dispatch-event [::reject-invoices-clicked checked])
|
|
:disabled (if (seq checked)
|
|
""
|
|
"disabled")}
|
|
"Reject "
|
|
(when (> (count checked ))
|
|
(str
|
|
(count checked)
|
|
" invoices"))
|
|
|
|
|
|
[:span " "]
|
|
]])
|
|
|
|
(def import-invoices-content
|
|
(with-meta
|
|
(fn []
|
|
(let [invoice-page (re-frame/subscribe [::invoice-page])
|
|
status (re-frame/subscribe [::subs/status])]
|
|
[:div
|
|
[:h1.title "Upload invoices"]
|
|
[dropzone]
|
|
|
|
[:div {:class "section"}]
|
|
[:div {:class "card found-invoices",}
|
|
[:div {:class "card-header"}
|
|
[:span {:class "card-header-title"} "Found Invoices"]]
|
|
[:div {:class "card-content"}
|
|
[approve-reject-button (:checked @invoice-page)]
|
|
(if (:loading @status)
|
|
[:h1.title
|
|
[:i.fa.fa-spin.fa-spinner]]
|
|
(if (seq (:invoices @invoice-page))
|
|
[invoice-table {:id :approved
|
|
:invoice-page invoice-page
|
|
:check-boxes true
|
|
:checked (:checked @invoice-page)
|
|
:on-check-changed (fn [which invoice]
|
|
(re-frame/dispatch [::toggle-check which invoice]))
|
|
:status (re-frame/subscribe [::subs/status])
|
|
:params (re-frame/subscribe [::params])
|
|
:on-params-change (fn [params]
|
|
(re-frame/dispatch [::params-change params])) }]
|
|
[:span "No pending invoices"]))]]]))
|
|
{:component-will-mount (fn []
|
|
(re-frame/dispatch-sync [::invalidated]))}))
|
|
|
|
(defn import-invoices-page []
|
|
[side-bar-layout {:side-bar [invoices-side-bar {}]
|
|
:main [import-invoices-content ]}])
|
|
|
|
|