progress on pay button.
This commit is contained in:
@@ -98,7 +98,8 @@
|
||||
(str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")))
|
||||
[:div.htmx-indicator.flex.items-center
|
||||
(svg/spinner {:class "inline w-4 h-4 text-white"})
|
||||
[:div.ml-3 "Loading..."]]
|
||||
(when (not (:minimal-loading? params))
|
||||
[:div.ml-3 "Loading..."])]
|
||||
(into [:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center] children)])
|
||||
|
||||
(defn a-button- [params & children]
|
||||
|
||||
@@ -215,13 +215,14 @@
|
||||
identity
|
||||
request)
|
||||
:headers {"hx-push-url" (str "?" (url/map->query
|
||||
(if (:query-schema grid-spec)
|
||||
(update (filter-vals #(not (nil? %))
|
||||
(m/encode (:query-schema grid-spec)
|
||||
(:query-params request)
|
||||
main-transformer))
|
||||
"sort" sort->query)
|
||||
(unparse-query-params (:parsed-query-params request)))))}
|
||||
(dissoc (if (:query-schema grid-spec)
|
||||
(update (filter-vals #(not (nil? %))
|
||||
(m/encode (:query-schema grid-spec)
|
||||
(:query-params request)
|
||||
main-transformer))
|
||||
"sort" sort->query)
|
||||
(unparse-query-params (:parsed-query-params request)))
|
||||
"selected" "all-selected")))} ;; TODO seems hacky to special case selected and all-selected here
|
||||
:oob (when-let [oob-render (:oob-render grid-spec)]
|
||||
(oob-render request)))))
|
||||
(wrap-trim-client-ids)
|
||||
@@ -242,7 +243,11 @@
|
||||
:client (:client request)
|
||||
:identity (:identity request)}
|
||||
(apply com/breadcrumbs {} (:breadcrumbs grid-spec))
|
||||
[:div {:x-data (hx/json {:selected [] :all_selected false})}
|
||||
[:div {:x-data (hx/json {:selected [] :all_selected false})
|
||||
"x-bind:hx-vals" "JSON.stringify({selected: $data.selected, 'all-selected': $data.all_selected})"
|
||||
:x-init "$watch('selected', s=> $dispatch('selectedChanged', {selected: s, all_selected: all_selected}) );
|
||||
$watch('all_selected', a=>$dispatch('selectedChanged', {selected: selected, all_selected: a}))"}
|
||||
|
||||
(table* grid-spec
|
||||
identity
|
||||
request)])
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
[:div {:id "exact-match-id-tag"}]))
|
||||
|
||||
(defn filters [request]
|
||||
[:form#payment-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||
[:form#invoice-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||
::route/table)
|
||||
"hx-target" "#entity-table"
|
||||
@@ -264,11 +264,10 @@
|
||||
[:start {:optional true :default 0} [:maybe :int]]
|
||||
[:amount-gte {:optional true} [:maybe :double]]
|
||||
[:amount-lte {:optional true} [:maybe :double]]
|
||||
[:payment-type {:optional true} [:maybe (ref->enum-schema "payment-type")]]
|
||||
[:vendor {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :vendor/name]}]]]
|
||||
[:check-number {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:invoice-number {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||
[:status {:optional true} [:maybe (ref->enum-schema "payment-status")]]
|
||||
[:status {:optional true} [:maybe (ref->enum-schema "invoice-status")]]
|
||||
[:exact-match-id {:optional true} [:maybe entity-id]]
|
||||
[:all-selected {:optional true :default nil} [:maybe :boolean]]
|
||||
[:selected {:optional true :default nil} [:maybe [:vector {:coerce? true}
|
||||
@@ -283,6 +282,75 @@
|
||||
{:start " "}
|
||||
main-transformer))
|
||||
|
||||
(defn selected->ids [request params]
|
||||
(let [all-selected (:all-selected params)
|
||||
selected (:selected params)
|
||||
ids (cond
|
||||
all-selected
|
||||
(:ids (fetch-ids (dc/db conn) (-> request
|
||||
(assoc :query-params params)
|
||||
(assoc-in [:query-params :start] 0)
|
||||
(assoc-in [:query-params :per-page] 250))))
|
||||
|
||||
|
||||
:else
|
||||
selected)]
|
||||
ids))
|
||||
|
||||
(defn pay-button* [params]
|
||||
(let [ids (:ids params)
|
||||
selected-client-count (if (seq ids)
|
||||
(ffirst
|
||||
(dc/q '[:find (count ?c)
|
||||
:in $ [?i ...]
|
||||
:where [?i :invoice/client ?c]]
|
||||
(dc/db conn)
|
||||
ids))
|
||||
|
||||
0)]
|
||||
|
||||
[:div {:hx-target "this"
|
||||
:x-data (hx/json {:popper nil
|
||||
:hovering false})
|
||||
"x-init" "popper = Popper.createPopper($refs.button, $refs.tooltip, {placement: 'bottom', strategy: 'fixed', modifiers: [{name: 'preventOverflow'}, {name: 'offset', options: {offset: [0, 10]}}]});"}
|
||||
(com/button {:color :primary
|
||||
:disabled (or (= (count (:ids params)) 0)
|
||||
(not= 1 selected-client-count))
|
||||
"x-bind:hx-vals" "JSON.stringify({selected: $data.selected, 'all-selected': $data.all_selected})"
|
||||
"hx-include" "#invoice-filters"
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes ::route/pay-button)
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "selectedChanged from:body, htmx:afterSwap from:#entity-table"
|
||||
"@mouseover" "hovering=true; $nextTick(() => popper.update())"
|
||||
"@mouseout" "hovering=false;"
|
||||
:x-ref "button"
|
||||
:minimal-loading? true
|
||||
:class "relative"}
|
||||
(if (> (count (:ids params)) 0)
|
||||
|
||||
(str "Pay " (count (:ids params)) " invoices")
|
||||
"Pay")
|
||||
(when (or (= 0 (count ids))
|
||||
(> selected-client-count 1))
|
||||
(com/badge {} "!")))
|
||||
[:div (hx/alpine-appear {:x-ref "tooltip"
|
||||
|
||||
:x-show "hovering"
|
||||
:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4"})
|
||||
(cond
|
||||
(= 0 (count ids))
|
||||
[:div "Please select some invoices to pay"]
|
||||
(> selected-client-count 1)
|
||||
[:div "Can only pay for one client at a time"]
|
||||
:else
|
||||
[:div "Click to choose a bank account"])]]))
|
||||
|
||||
|
||||
(defn pay-button [request]
|
||||
(html-response
|
||||
(pay-button* {:ids (selected->ids request
|
||||
(:query-params request))})))
|
||||
|
||||
;; TODO fix parsing of query params
|
||||
(def grid-page
|
||||
(helper/build {:id "entity-table"
|
||||
@@ -298,12 +366,15 @@
|
||||
:parse-query-params (fn [p]
|
||||
(mc/decode query-schema p main-transformer))
|
||||
:action-buttons (fn [request]
|
||||
[(when (can? (:identity request) {:subject :payment :activity :bulk-delete})
|
||||
[(when (can? (:identity request) {:subject :invoice :activity :bulk-delete})
|
||||
(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes ::route/bulk-delete))
|
||||
"x-bind:hx-vals" "JSON.stringify({selected: $data.selected, 'all-selected': $data.all_selected})"
|
||||
"hx-include" "#payment-filters"
|
||||
"hx-include" "#invoice-filters"
|
||||
:color :red}
|
||||
"Void selected"))])
|
||||
"Void selected"))
|
||||
(when (can? (:identity request) {:subject :invoice :activity :pay})
|
||||
(pay-button* {:ids (selected->ids request
|
||||
(:query-params request))}))])
|
||||
:row-buttons (fn [_ entity]
|
||||
[(when (= :invoice-status/unpaid (:invoice/status entity))
|
||||
(com/icon-button {:hx-delete (bidi/path-for ssr-routes/only-routes
|
||||
@@ -470,7 +541,7 @@
|
||||
(assoc "hx-retarget" ".modal-stack")
|
||||
(assoc "hx-reswap" "beforeend")))))
|
||||
|
||||
(defn void-payments-internal [all-ids id]
|
||||
(defn void-invoices-internal [all-ids id]
|
||||
(let [all-ids (->> all-ids
|
||||
(dc/q '[:find (pull ?i [:db/id :invoice/date {:invoice/expense-accounts [:db/id]}])
|
||||
:in $ [?i ...]
|
||||
@@ -512,21 +583,12 @@
|
||||
id)
|
||||
(count all-ids)))
|
||||
|
||||
|
||||
|
||||
(defn bulk-delete-dialog-confirm [request]
|
||||
(alog/peek (:form-params request))
|
||||
(let [all-selected (:all-selected (:form-params request))
|
||||
selected (:selected (:form-params request))
|
||||
ids (cond
|
||||
all-selected
|
||||
(:ids (fetch-ids (dc/db conn) (-> request
|
||||
(assoc :query-params (:form-params request))
|
||||
(assoc-in [:query-params :start] 0)
|
||||
(assoc-in [:query-params :per-page] 250))))
|
||||
|
||||
|
||||
:else
|
||||
selected)
|
||||
updated-count (void-payments-internal ids (:identity request))]
|
||||
(let [ids (selected->ids request (:form-params request))
|
||||
updated-count (void-invoices-internal ids (:identity request))]
|
||||
|
||||
(html-response [:div]
|
||||
:headers {"hx-trigger" (hx/json {:modalclose ""
|
||||
@@ -539,6 +601,8 @@
|
||||
(def key->handler
|
||||
(apply-middleware-to-all-handlers
|
||||
{::route/page (helper/page-route grid-page)
|
||||
::route/pay-button (-> pay-button
|
||||
(wrap-schema-enforce :query-schema query-schema))
|
||||
::route/delete (-> delete
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-enforce :route-params [:map [:db/id entity-id]]))
|
||||
|
||||
@@ -259,12 +259,15 @@
|
||||
(mt2/transformer {:decoders {:vector {:compile (fn [schema _]
|
||||
(when (:coerce? (m/properties schema))
|
||||
(fn [data]
|
||||
(cond (sequential? data)
|
||||
data
|
||||
(nil? data)
|
||||
nil
|
||||
:else
|
||||
[data]))))}}}))
|
||||
(cond
|
||||
(vector? data)
|
||||
data
|
||||
(sequential? data)
|
||||
data
|
||||
(nil? data)
|
||||
nil
|
||||
:else
|
||||
[data]))))}}}))
|
||||
|
||||
(defn wrap-merge-prior-hx [handler]
|
||||
;; TODO this should just be automatic
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns auto-ap.routes.invoice)
|
||||
(def routes {"" {:get ::page}
|
||||
"/pay-button" ::pay-button
|
||||
"/bulk-delete" {:get ::bulk-delete
|
||||
:delete ::bulk-delete-confirm}
|
||||
["/" [#"\d+" :db/id]] {:delete ::delete}
|
||||
|
||||
Reference in New Issue
Block a user