diff --git a/src/clj/auto_ap/db/invoices.clj b/src/clj/auto_ap/db/invoices.clj index e6d5aae2..f7811390 100644 --- a/src/clj/auto_ap/db/invoices.clj +++ b/src/clj/auto_ap/db/invoices.clj @@ -71,12 +71,23 @@ q))) -(defn get-graphql [{:keys [imported company-id sort-by asc]}] + +(defn base-graphql [{:keys [imported company-id]}] + (cond-> base-query + (not (nil? imported)) (helpers/merge-where [:= :imported imported]) + (not (nil? company-id)) (helpers/merge-where [:= :company-id company-id]) + )) + +(defn get-graphql [{:keys [start sort-by asc] :as args}] (query - (cond-> base-query - (not (nil? imported)) (helpers/merge-where [:= :imported imported]) - (not (nil? company-id)) (helpers/merge-where [:= :company-id company-id]) - (not (nil? sort-by) ) (add-sort-by sort-by asc)))) + (cond-> (base-graphql args) + (not (nil? sort-by) ) (add-sort-by sort-by asc) + true (assoc :limit 20) + start (assoc :offset start)))) + +(defn count-graphql [args] + (:count (first (query + (assoc (base-graphql args) :select [:%count.*]))))) (defn import [parsed-invoices companies vendors] (insert-multi! diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index 31b1be83..7f90b2b7 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -36,15 +36,22 @@ :resolve :get-vendor-for-invoice} :company {:type :company - :resolve :get-company-for-invoice}}}} + :resolve :get-company-for-invoice}}} + + :invoice_page {:fields {:invoices {:type '(list :invoice)} + :count {:type 'Int} + :total {:type 'Int} + :start {:type 'Int} + :end {:type 'Int}}}} :queries - {:invoice {:type '(list :invoice) - :args {:imported {:type 'Boolean} - :company_id {:type 'Int} - :sort_by {:type 'String} - :asc {:type 'Boolean}} - - :resolve :get-invoice} + {:invoice_page {:type '(list :invoice_page) + :args {:imported {:type 'Boolean} + :company_id {:type 'Int} + :start {:type 'Int} + :sort_by {:type 'String} + :asc {:type 'Boolean}} + + :resolve :get-invoice-page} :company {:type '(list :company) :resolve :get-company} :vendor {:type '(list :vendor) @@ -93,17 +100,22 @@ node)) m)) -(defn get-invoice [context args value] - - (println (<-graphql args)) +(defn get-invoice-page [context args value] (let [extra-context (cond-> {} (executor/selects-field? context :invoice/vendor) (assoc :vendor-cache (by (vendors/get-all) :id )) - (executor/selects-field? context :invoice/company) (assoc :company-cache (by (companies/get-all) :id )))] + (executor/selects-field? context :invoice/company) (assoc :company-cache (by (companies/get-all) :id ))) + + invoices (map + ->graphql + (invoices/get-graphql (<-graphql args))) + invoice-count (invoices/count-graphql (<-graphql args))] (resolve/with-context - (map - ->graphql - (invoices/get-graphql (<-graphql args))) extra-context))) + [{:invoices invoices + :total invoice-count + :count (count invoices) + :start (:start args 0) + :end (+ (:start args 0) (count invoices))}] extra-context))) (defn get-vendor-for-invoice [context args value] (->graphql @@ -127,7 +139,7 @@ (def schema (-> integreat-schema - (attach-resolvers {:get-invoice get-invoice + (attach-resolvers {:get-invoice-page get-invoice-page :get-vendor-for-invoice get-vendor-for-invoice :get-company-for-invoice get-company-for-invoice :get-company get-company diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index 5693a3f1..ad36c7f5 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -3,6 +3,7 @@ [auto-ap.subs :as subs] [auto-ap.views.utils :refer [date->str]] [reagent.core :as reagent] + [clojure.string :as str] [cljs-time.format :as format])) (defn toggle-sort-by [params key] @@ -26,39 +27,90 @@ [:i.fa.fa-sort]])) (defn query [params] - {:venia/queries [[:invoice + {:venia/queries [[:invoice_page (assoc params :company-id (:id @(re-frame/subscribe [::subs/company]))) - [:id :total :invoice-number :date [:vendor [:name :id]] [:company [:name :id]]]]]}) + [[:invoices [:id :total :invoice-number :date [:vendor [:name :id]] [:company [:name :id]]]] + :total + :start + :end]]]}) -(defn invoice-table [{:keys [id invoices status on-params-change vendors params]}] +(defn bound [x y z] + (cond + (< z x) + x + (< y x) + x + (> y z) + z + :else + y)) + +(defn buttons-for [start end count total on-params-change state] + (let [per-page 20 + max-buttons 5 + buttons-before (Math/floor (/ max-buttons 2)) + total-pages (Math/ceil (/ total per-page)) + current-page (Math/floor (/ start per-page)) + first-page-button (bound 0 (- current-page buttons-before) (- total-pages max-buttons)) + all-buttons (into [] (for [x (range total-pages)] + ^{:key x} [:button.button {:class (str/join " " [(when (= current-page x) + "is-active")]) + :on-click (fn [e] (on-params-change (swap! state assoc :start (* x per-page))))} (inc x)])) + + + last-page-button (Math/min total-pages (+ max-buttons first-page-button)) + + extended-last-page-button (when (not= last-page-button total-pages) + [:span "..." [:button.button {:on-click (fn [e] (on-params-change (swap! state assoc :start (* (dec total-pages) per-page))))} total-pages]]) + + extended-first-page-button (when (not= first-page-button 0) + [:span [:button.button {:on-click (fn [e] (on-params-change (swap! state assoc :start 0)))} 1] "..."]) + + ] + + + [:div.is-pulled-right + [:div + extended-first-page-button + (apply list (subvec all-buttons first-page-button last-page-button)) + + extended-last-page-button]] + )) + +(defn invoice-table [{:keys [id invoice-page status on-params-change vendors params]}] (let [state (reagent/atom (or @params {}))] - (fn [{:keys [id invoices status on-params-change vendors]}] - (let [{:keys [sort-by asc]} @state] - [:table.table.is-fullwidth - [:thead - [:tr - [:th {:on-click (fn [e] - (on-params-change (swap! state toggle-sort-by "vendor"))) :style {:width "25%" :cursor "pointer"}} "Vendor" - (sort-icon "vendor" sort-by asc)] - [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "company"))) :style {:width "25%" :cursor "pointer"}} "Company" - (sort-icon "company" sort-by asc)] - [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "invoice-number"))) :style {:width "18%" :cursor "pointer"}} "Invoice #" - (sort-icon "invoice-number" sort-by asc)] - [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "date"))) :style {:width "16%" :cursor "pointer"}} "Date" - (sort-icon "date" sort-by asc)] - [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "total"))) :style {:width "16%" :cursor "pointer"}} "Amount" - (sort-icon "total" sort-by asc)]]] - [:tbody - (if (:loading @status) - [:tr - [:td {:col-span 5} - [:i.fa.fa-spin.fa-spinner]]] - (for [{:keys [company invoice-number date total id vendor] :as i} @invoices] - ^{:key id} - [:tr - [:td (:name vendor)] - [:td (:name company)] - [:td invoice-number] - [:td (date->str date) ] - [:td total]]))]])))) + (fn [{:keys [id invoice-page status on-params-change vendors]}] + (let [{:keys [sort-by asc]} @state + {:keys [invoices start end count total]} @invoice-page] + [:div + [buttons-for start end count total on-params-change state] + "Showing " (inc start) "-" end "/" total + + [:table.table.is-fullwidth + [:thead + [:tr + [:th {:on-click (fn [e] + (on-params-change (swap! state toggle-sort-by "vendor"))) :style {:width "25%" :cursor "pointer"}} "Vendor" + (sort-icon "vendor" sort-by asc)] + [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "company"))) :style {:width "25%" :cursor "pointer"}} "Company" + (sort-icon "company" sort-by asc)] + [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "invoice-number"))) :style {:width "18%" :cursor "pointer"}} "Invoice #" + (sort-icon "invoice-number" sort-by asc)] + [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "date"))) :style {:width "16%" :cursor "pointer"}} "Date" + (sort-icon "date" sort-by asc)] + [:th {:on-click (fn [e] (on-params-change (swap! state toggle-sort-by "total"))) :style {:width "16%" :cursor "pointer"}} "Amount" + (sort-icon "total" sort-by asc)]]] + [:tbody + (if (:loading @status) + [:tr + [:td {:col-span 5} + [:i.fa.fa-spin.fa-spinner]]] + (for [{:keys [company invoice-number date total id vendor] :as i} (:invoices @invoice-page)] + ^{:key id} + [:tr + [:td (:name vendor)] + [:td (:name company)] + [:td invoice-number] + [:td (date->str date) ] + [:td total]]))]]])))) diff --git a/src/cljs/auto_ap/views/pages/import_invoices.cljs b/src/cljs/auto_ap/views/pages/import_invoices.cljs index ab62635a..04e67e1a 100644 --- a/src/cljs/auto_ap/views/pages/import_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/import_invoices.cljs @@ -34,9 +34,9 @@ :previewTemplate "
"})))}))) (re-frame/reg-sub - ::invoices + ::invoice-page (fn [db] - (-> db ::invoices))) + (-> db ::invoice-page))) (re-frame/reg-sub ::params @@ -63,7 +63,7 @@ ::received (fn [db [_ data]] (-> db - (assoc ::invoices (:invoice data)) + (assoc ::invoice-page (first (:invoice-page data))) (assoc-in [:status :loading] false)))) (re-frame/reg-event-fx @@ -91,7 +91,7 @@ (def import-invoices-page (with-meta (fn [] - (let [invoices (re-frame/subscribe [::invoices]) + (let [invoice-page (re-frame/subscribe [::invoice-page]) status (re-frame/subscribe [::subs/status])] [:div {:class "inbox-messages"} [:h1.title "Upload invoices"] @@ -105,15 +105,15 @@ (if (:loading @status) [:h1.title [:i.fa.fa-spin.fa-spinner]] - (if (seq @invoices) + (if (seq (:invoices @invoice-page)) [invoice-table {:id :approved - :invoices invoices + :invoice-page invoice-page :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"]))] - (if (and (seq @invoices) (not (:loading @status))) + (if (and (seq (:invoices @invoice-page)) (not (:loading @status))) [:div.card-footer [:a.card-footer-item {:on-click (fn [e] diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 16a339cb..98fb4e8b 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -8,9 +8,9 @@ [auto-ap.events :as events])) (re-frame/reg-sub - ::invoices + ::invoice-page (fn [db] - (-> db ::invoices))) + (-> db ::invoice-page))) (re-frame/reg-sub ::params @@ -31,7 +31,7 @@ ::received (fn [db [_ data]] (-> db - (assoc ::invoices (:invoice data)) + (assoc ::invoice-page (first (:invoice-page data))) (assoc-in [:status :loading] false)))) (re-frame/reg-event-fx @@ -46,7 +46,7 @@ [:h1.title "Unpaid invoices"] [invoice-table {:id :unpaid :params (re-frame/subscribe [::params]) - :invoices (re-frame/subscribe [::invoices]) + :invoice-page (re-frame/subscribe [::invoice-page]) :status (re-frame/subscribe [::subs/status]) :on-params-change (fn [params] (re-frame/dispatch [::params-change params])) }]])