229 lines
10 KiB
Clojure
229 lines
10 KiB
Clojure
(ns auto-ap.views.pages.import-invoices
|
|
(:require [re-frame.core :as re-frame]
|
|
[reagent.core :as reagent]
|
|
[reagent.dom :as rdom]
|
|
[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 bind-field with-user]]
|
|
[auto-ap.utils :refer [by]]
|
|
[auto-ap.entities.vendors :as vendor]
|
|
[auto-ap.views.components.typeahead :refer [typeahead-entity]]
|
|
[auto-ap.views.components.invoice-table :refer [invoice-table] :as invoice-table]
|
|
[cljs.reader :as edn]
|
|
[clojure.string :as str]
|
|
[vimsical.re-frame.cofx.inject :as inject]
|
|
[auto-ap.status :as status]
|
|
[vimsical.re-frame.fx.track :as track]
|
|
[dropzone :as dz]
|
|
[auto-ap.views.pages.data-page :as data-page]
|
|
[clojure.set :as set]
|
|
[auto-ap.effects.forward :as forward]))
|
|
|
|
|
|
(defn dropzone []
|
|
(let [client (re-frame/subscribe [::subs/client])
|
|
token (re-frame/subscribe [::subs/token])
|
|
vendor (reagent/atom nil)]
|
|
(reagent/create-class
|
|
{:display-name "dropzone"
|
|
:component-did-mount (fn [this]
|
|
(dz. (rdom/dom-node this)
|
|
(clj->js {:init (fn []
|
|
(let [^js/Dropzone t (js-this)]
|
|
(.on t "addedfiles"
|
|
(fn []
|
|
(re-frame/dispatch [::status/completed ::import])))
|
|
|
|
(.on t "success" (fn [_ files]
|
|
(re-frame/dispatch [::invalidated])))
|
|
(.on t "error" (fn [_ error]
|
|
(re-frame/dispatch [::status/error ::import [(edn/read-string error)]])))))
|
|
: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>"})))
|
|
:reagent-render (fn []
|
|
{:key batch}
|
|
[:form.dz {:action "/api/invoices/upload"}
|
|
[:div.field.has-addons
|
|
[:p.control
|
|
[:a.button.is-static "Force Location"]]
|
|
[:p.control
|
|
[:input.input {:name "location" :placeholder "SG" :size "4" :maxlength "2" :style {:display "inline"}}]]]
|
|
[:div.field.has-addons
|
|
[:p.control
|
|
[:a.button.is-static "Force vendor"]]
|
|
[:div.control {:style {:width "400px"}}
|
|
[typeahead-entity {:matches @(re-frame/subscribe [::subs/vendors])
|
|
:match->text :name
|
|
:name "vendor"
|
|
:type "typeahead"
|
|
:on-change (fn [v]
|
|
(reset! vendor v))
|
|
:value @vendor}]]
|
|
]
|
|
[: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"]]]])})
|
|
))
|
|
|
|
|
|
|
|
|
|
(re-frame/reg-sub
|
|
::batch
|
|
(fn [db]
|
|
(-> db (::batch 0))))
|
|
|
|
(re-frame/reg-event-fx
|
|
::invalidated
|
|
(fn [{:keys [db]} [_ params]]
|
|
{:dispatch-n [[::params-change @(re-frame/subscribe [::data-page/params :import-invoices])]
|
|
[::data-page/reset-checked :import-invoices]]
|
|
:db (update db ::batch inc)}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::mounted
|
|
(fn [cofx [_ params]]
|
|
{::track/register [{:id ::params
|
|
:subscription [::data-page/params :import-invoices]
|
|
:event-fn (fn [params]
|
|
[::params-change params])}
|
|
]
|
|
::forward/register [{:id ::received
|
|
:events #{::data-page/received}
|
|
:event-fn (fn [[_ _ {:keys [data]}]]
|
|
[::received data])}]}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::unmounted
|
|
(fn [cofx [_ params]]
|
|
{::track/dispose {:id ::params}
|
|
:dispatch [::data-page/dispose :import-invoices]}))
|
|
|
|
|
|
(re-frame/reg-event-fx
|
|
::params-change
|
|
[with-user]
|
|
(fn [{:keys [user] } [_ params]]
|
|
{:graphql {:token user
|
|
:owns-state {:single [::data-page/page :import-invoices]}
|
|
:query-obj (invoice-table/query (assoc params :import-status "pending"))
|
|
:on-success (fn [result]
|
|
(let [result (set/rename-keys (first (:invoice-page result))
|
|
{:invoices :data})]
|
|
|
|
[::data-page/received :import-invoices result]))}}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::received
|
|
(fn [_ [_ data]]
|
|
{:dispatch [::data-page/toggle-check :import-invoices (by :id data)]}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::reject-invoices-clicked
|
|
(fn [{:keys [db]} [_ invoices on-success]]
|
|
{:graphql
|
|
{:token (-> db :user)
|
|
:owns-state {:single ::reject}
|
|
:query-obj {:venia/operation {:operation/type :mutation
|
|
:operation/name "RejectInvoices"}
|
|
:venia/queries [[:reject-invoices
|
|
{:invoices (vec invoices)}
|
|
[]]]}
|
|
:on-success [::invalidated]}}))
|
|
|
|
(re-frame/reg-event-fx
|
|
::approve-invoices-clicked
|
|
(fn [{:keys [db]} [_ invoices on-success]]
|
|
{:graphql
|
|
{:token (-> db :user)
|
|
:owns-state {:single ::approve}
|
|
:query-obj {:venia/operation {:operation/type :mutation
|
|
:operation/name "ApproveInvoices"}
|
|
:venia/queries [[:approve-invoices
|
|
{:invoices (vec 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}}))
|
|
|
|
(defn approve-reject-button [checked]
|
|
[:div.buttons
|
|
[:button.button.is-primary {:on-click (dispatch-event [::approve-invoices-clicked checked])
|
|
:class (status/class-for @(re-frame/subscribe [::status/single ::approve]))
|
|
:disabled (or (not (boolean (seq checked)))
|
|
(status/disabled-for @(re-frame/subscribe [::status/single ::approve])))}
|
|
"Approve "
|
|
(when (> (count checked ))
|
|
(str
|
|
(count checked)
|
|
" invoices"))
|
|
[:span " "]]
|
|
[:button.button.is-warning {:on-click (dispatch-event [::reject-invoices-clicked checked])
|
|
:class (status/class-for @(re-frame/subscribe [::status/single ::reject]))
|
|
:disabled (or (not (boolean (seq checked)))
|
|
(status/disabled-for @(re-frame/subscribe [::status/single ::reject])))}
|
|
"Reject "
|
|
(when (> (count checked ))
|
|
(str
|
|
(count checked)
|
|
" invoices"))
|
|
[:span " "]]])
|
|
|
|
(def import-invoices-content
|
|
(with-meta
|
|
(fn []
|
|
(let [page @(re-frame/subscribe [::data-page/page :import-invoices])
|
|
batch @(re-frame/subscribe [::batch])
|
|
client (:id @(re-frame/subscribe [::subs/client]))]
|
|
^{:key (str client "-" batch)}
|
|
[:div
|
|
[:h1.title "Upload invoices"]
|
|
[status/status-notification {:statuses [[::status/single ::approve]
|
|
[::status/single ::reject]
|
|
[::status/single ::import]]}]
|
|
^{:key (str batch)}
|
|
[dropzone]
|
|
[:div.mb-4]
|
|
[:div {:class "card found-invoices",}
|
|
[:div {:class "card-header"}
|
|
[:span {:class "card-header-title"} "Found Invoices"]]
|
|
[:div {:class "card-content"}
|
|
[approve-reject-button (:checked-set page)]
|
|
(if (seq (:data (:data page)))
|
|
[invoice-table {:id :approved
|
|
:data-page :import-invoices
|
|
:overrides {:client (fn [row]
|
|
[:p (:name (:client row))
|
|
[:p [:i.is-size-7 (:client-identifier row)]]])}
|
|
:check-boxes true}]
|
|
[:span "No pending invoices"])]]]))
|
|
{:component-did-mount (fn []
|
|
(re-frame/dispatch-sync [::mounted]))
|
|
:component-will-unmount (fn []
|
|
(re-frame/dispatch-sync [::unmounted]))}))
|
|
|
|
(defn import-invoices-page []
|
|
[side-bar-layout {:side-bar [invoices-side-bar {}]
|
|
:main [import-invoices-content ]}])
|
|
|
|
|