Adds float visibility
This commit is contained in:
1
resources/.~lock.sample-ledger.csv#
Normal file
1
resources/.~lock.sample-ledger.csv#
Normal file
@@ -0,0 +1 @@
|
|||||||
|
,noti,pop-os,24.08.2024 23:11,file:///home/noti/.config/libreoffice/4;
|
||||||
@@ -42,4 +42,27 @@ Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effec
|
|||||||
cleanup(onDestroy);
|
cleanup(onDestroy);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Alpine.directive('popper', (el, { value, expression }, { evaluateLater, effect, cleanup, evaluate, Alpine}) => {
|
||||||
|
let dependent_properties = evaluate(expression)
|
||||||
|
let tooltip = evaluate(dependent_properties['tooltip'])
|
||||||
|
let source = evaluate(dependent_properties['source'])
|
||||||
|
|
||||||
|
let popper = Popper.createPopper(source, tooltip, {placement: 'bottom', strategy: 'fixed', modifiers: [{name: 'preventOverflow'}, {name: 'offset', options: {offset: [0, 10]}}]});;
|
||||||
|
let d=Alpine.reactive({show: false});
|
||||||
|
tooltip.classList.add('opacity-0', 'transition-opacity')
|
||||||
|
|
||||||
|
let show = () => d.show = true;
|
||||||
|
let hide = () => d.show = false;
|
||||||
|
source.addEventListener('mouseover', show)
|
||||||
|
source.addEventListener('mouseout', hide)
|
||||||
|
effect(() => {
|
||||||
|
if (d.show) {
|
||||||
|
tooltip.classList.remove('opacity-0')
|
||||||
|
} else {
|
||||||
|
tooltip.classList.add('opacity-0')
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
cleanup(() => {popper.destroy(); source.removeEventListener('mouseover', show); source.removeEventListener('mouseout', hide) })
|
||||||
|
})
|
||||||
})
|
})
|
||||||
File diff suppressed because one or more lines are too long
@@ -30,6 +30,7 @@
|
|||||||
(def modal-header-attachment dialog/modal-header-attachment-)
|
(def modal-header-attachment dialog/modal-header-attachment-)
|
||||||
(def modal-body dialog/modal-body-)
|
(def modal-body dialog/modal-body-)
|
||||||
(def modal-footer dialog/modal-footer-)
|
(def modal-footer dialog/modal-footer-)
|
||||||
|
(def tooltip buttons/tooltip-)
|
||||||
|
|
||||||
(def text-input inputs/text-input-)
|
(def text-input inputs/text-input-)
|
||||||
(def text-area inputs/text-area-)
|
(def text-area inputs/text-area-)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
"sales"
|
"sales"
|
||||||
(#{::payment-routes/all-page ::payment-routes/pending-page ::payment-routes/cleared-page ::payment-routes/voided-page} (:matched-route request))
|
(#{::payment-routes/all-page ::payment-routes/pending-page ::payment-routes/cleared-page ::payment-routes/voided-page} (:matched-route request))
|
||||||
"payments"
|
"payments"
|
||||||
(#{::ledger-routes/all-page ::ledger-routes/external-page} (:matched-route request))
|
(#{::ledger-routes/all-page ::ledger-routes/external-page ::ledger-routes/external-import-page} (:matched-route request))
|
||||||
"ledger"
|
"ledger"
|
||||||
:else
|
:else
|
||||||
nil)]
|
nil)]
|
||||||
|
|||||||
@@ -232,3 +232,8 @@
|
|||||||
(if (seq children)
|
(if (seq children)
|
||||||
children
|
children
|
||||||
"Save")))
|
"Save")))
|
||||||
|
|
||||||
|
(defn tooltip- [{:as params} & children]
|
||||||
|
[:div (assoc params
|
||||||
|
:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4 opacity-0")
|
||||||
|
[:span children]])
|
||||||
|
|||||||
@@ -382,9 +382,7 @@
|
|||||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
::route/pay-wizard)
|
::route/pay-wizard)
|
||||||
:hx-trigger "click from:#pay-button"
|
:hx-trigger "click from:#pay-button"
|
||||||
:x-data (hx/json {:popper nil
|
:x-popper (hx/json {:source "$refs.button", :tooltip "$refs.tooltip"}) }
|
||||||
: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
|
(com/button {:color :primary
|
||||||
:id "pay-button"
|
:id "pay-button"
|
||||||
:disabled (or (= (count (:ids params)) 0)
|
:disabled (or (= (count (:ids params)) 0)
|
||||||
@@ -395,8 +393,6 @@
|
|||||||
:hx-get (bidi/path-for ssr-routes/only-routes ::route/pay-button)
|
:hx-get (bidi/path-for ssr-routes/only-routes ::route/pay-button)
|
||||||
:hx-swap "outerHTML"
|
:hx-swap "outerHTML"
|
||||||
:hx-trigger "selectedChanged from:body, htmx:afterSwap from:#entity-table"
|
:hx-trigger "selectedChanged from:body, htmx:afterSwap from:#entity-table"
|
||||||
"@mouseover" "hovering=true; $nextTick(() => popper.update())"
|
|
||||||
"@mouseout" "hovering=false;"
|
|
||||||
:x-ref "button"
|
:x-ref "button"
|
||||||
:minimal-loading? true
|
:minimal-loading? true
|
||||||
:class "relative"}
|
:class "relative"}
|
||||||
@@ -409,24 +405,21 @@
|
|||||||
(when (or (= 0 (count ids))
|
(when (or (= 0 (count ids))
|
||||||
(> selected-client-count 1))
|
(> selected-client-count 1))
|
||||||
(com/badge {} "!")))
|
(com/badge {} "!")))
|
||||||
[:div (hx/alpine-appear {:x-ref "tooltip"
|
(com/tooltip {:x-ref "tooltip" }
|
||||||
|
(cond
|
||||||
|
(not all-credits-or-debits)
|
||||||
|
[:div "All vendor totals must be either positive or negative."]
|
||||||
|
(and (= 0 (count ids))
|
||||||
|
(not= (count (:ids params))
|
||||||
|
0))
|
||||||
|
[:div "No " [:span.font-bold "payable"] " invoices selected."]
|
||||||
|
|
||||||
:x-show "hovering"
|
(= 0 (count ids))
|
||||||
:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4"})
|
[:div "Please select some invoices to pay"]
|
||||||
(cond
|
(> selected-client-count 1)
|
||||||
(not all-credits-or-debits)
|
[:div "Can only pay for one client at a time"]
|
||||||
[:div "All vendor totals must be either positive or negative."]
|
:else
|
||||||
(and (= 0 (count ids))
|
[:div "Click to choose a bank account"]))]))
|
||||||
(not= (count (:ids params))
|
|
||||||
0))
|
|
||||||
[:div "No " [:span.font-bold "payable"] " invoices selected."]
|
|
||||||
|
|
||||||
(= 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]
|
(defn pay-button [request]
|
||||||
|
|||||||
@@ -680,20 +680,19 @@
|
|||||||
:name (fc/field-name)
|
:name (fc/field-name)
|
||||||
:class "w-24"}))))
|
:class "w-24"}))))
|
||||||
(com/data-grid-cell {:class "align-top"}
|
(com/data-grid-cell {:class "align-top"}
|
||||||
[:div.p-2 {:x-data (hx/json {:popper nil
|
[:div.p-2
|
||||||
:hover false})
|
|
||||||
:x-init "popper = Popper.createPopper($refs.button, $refs.tooltip, {placement: 'bottom', strategy: 'fixed', modifiers: [{name: 'preventOverflow'}, {name: 'offset', options: {offset: [0, 10]}}]});"}
|
|
||||||
(cond (seq (fc/field-errors))
|
(cond (seq (fc/field-errors))
|
||||||
[:div.w-8.h-8.bg-red-50.rounded-full.p-2.text-red-300.flex.items-start
|
[:div
|
||||||
{"@mouseover" "hover=true; $nextTick(() => popper.update()); console.log('hi')"
|
{ :x-popper (hx/json {:source "$refs.button"
|
||||||
"@mouseout" "hover=false"
|
:tooltip "$refs.tooltip"})}
|
||||||
:x-ref "button"}
|
[:div.w-8.h-8.bg-red-50.rounded-full.p-2.text-red-300.flex.items-start
|
||||||
svg/alert]
|
{ :x-ref "button"}
|
||||||
|
svg/alert]
|
||||||
|
(com/tooltip {:x-ref "tooltip"}
|
||||||
|
[:span (pr-str (fc/field-errors))])]
|
||||||
:else
|
:else
|
||||||
nil)
|
nil)
|
||||||
[:div (hx/alpine-appear {:x-ref "tooltip" :x-show "hover"
|
]))))}
|
||||||
:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4"})
|
|
||||||
[:span (pr-str (fc/field-errors))]]]))))}
|
|
||||||
|
|
||||||
[:div.flex.m-4.flex-row-reverse
|
[:div.flex.m-4.flex-row-reverse
|
||||||
(com/button {:color :primary} "Import")])])))])
|
(com/button {:color :primary} "Import")])])))])
|
||||||
|
|||||||
@@ -243,12 +243,51 @@
|
|||||||
(map first))]
|
(map first))]
|
||||||
refunds))
|
refunds))
|
||||||
|
|
||||||
|
(defn sum-visible-pending [ids]
|
||||||
|
(->>
|
||||||
|
(dc/q {:find ['?id '?o]
|
||||||
|
:in ['$ '[?id ...]]
|
||||||
|
:where ['[?id :payment/amount ?o]
|
||||||
|
'[?id :payment/status :payment-status/pending]]}
|
||||||
|
(dc/db conn)
|
||||||
|
ids)
|
||||||
|
(map last)
|
||||||
|
(reduce
|
||||||
|
+
|
||||||
|
0.0)))
|
||||||
|
|
||||||
|
(defn sum-client-pending [clients]
|
||||||
|
(->>
|
||||||
|
(dc/q {:find '[?e ?a]
|
||||||
|
:in '[$ [?clients ?start ?end]]
|
||||||
|
:where '[[(iol-ion.query/scan-payments $ ?clients ?start ?end) [[?e _ ?sort-default] ...]]
|
||||||
|
[?e :payment/status :payment-status/pending]
|
||||||
|
[?e :payment/amount ?a]]}
|
||||||
|
(dc/db conn)
|
||||||
|
[clients
|
||||||
|
nil
|
||||||
|
nil])
|
||||||
|
|
||||||
|
(map last)
|
||||||
|
(reduce
|
||||||
|
+
|
||||||
|
0.0)))
|
||||||
|
|
||||||
(defn fetch-page [request]
|
(defn fetch-page [request]
|
||||||
(let [db (dc/db conn)
|
(let [db (dc/db conn)
|
||||||
{ids-to-retrieve :ids matching-count :count} (fetch-ids db request)]
|
{ids-to-retrieve :ids matching-count :count
|
||||||
|
all-ids :all-ids} (fetch-ids db request)]
|
||||||
|
|
||||||
|
|
||||||
[(->> (hydrate-results ids-to-retrieve db request))
|
[(->> (hydrate-results ids-to-retrieve db request))
|
||||||
matching-count]))
|
matching-count
|
||||||
|
(sum-visible-pending all-ids)
|
||||||
|
(sum-client-pending (extract-client-ids (:clients request)
|
||||||
|
(:client request)
|
||||||
|
(:client-id (:query-params request))
|
||||||
|
(when (:client-code (:query-params request))
|
||||||
|
[:client/code (:client-code (:query-params request))])))
|
||||||
|
]))
|
||||||
|
|
||||||
(def query-schema (mc/schema
|
(def query-schema (mc/schema
|
||||||
[:maybe [:map {:date-range [:date-range :start-date :end-date]}
|
[:maybe [:map {:date-range [:date-range :start-date :end-date]}
|
||||||
@@ -291,12 +330,17 @@
|
|||||||
:parse-query-params (fn [p]
|
:parse-query-params (fn [p]
|
||||||
(mc/decode query-schema p main-transformer))
|
(mc/decode query-schema p main-transformer))
|
||||||
:action-buttons (fn [request]
|
:action-buttons (fn [request]
|
||||||
[(when (can? (:identity request) {:subject :payment :activity :bulk-delete})
|
(let [[_ _ visible-in-float total-in-float ] (:page-results request)]
|
||||||
(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes ::route/bulk-delete))
|
[(com/pill {:color :primary} " Visible in float "
|
||||||
"x-bind:hx-vals" "JSON.stringify({selected: $data.selected, 'all-selected': $data.all_selected})"
|
(format "$%,.2f" visible-in-float))
|
||||||
"hx-include" "#payment-filters"
|
(com/pill {:color :secondary} " Total in float "
|
||||||
:color :red}
|
(format "$%,.2f" total-in-float))
|
||||||
"Void selected"))])
|
(when (can? (:identity request) {:subject :payment :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"
|
||||||
|
:color :red}
|
||||||
|
"Void selected"))]))
|
||||||
:row-buttons (fn [_ entity]
|
:row-buttons (fn [_ entity]
|
||||||
[(when (not= :payment-status/voided (:payment/status entity))
|
[(when (not= :payment-status/voided (:payment/status entity))
|
||||||
(com/icon-button {:hx-delete (bidi/path-for ssr-routes/only-routes
|
(com/icon-button {:hx-delete (bidi/path-for ssr-routes/only-routes
|
||||||
@@ -306,6 +350,13 @@
|
|||||||
svg/trash))])
|
svg/trash))])
|
||||||
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes ::route/page)}
|
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes ::route/page)}
|
||||||
"Payments"]]
|
"Payments"]]
|
||||||
|
:break-table (fn [request entity]
|
||||||
|
(cond
|
||||||
|
(= (-> request :query-params :sort first :name) "Vendor")
|
||||||
|
(-> entity :payment/vendor :vendor/name)
|
||||||
|
|
||||||
|
|
||||||
|
:else nil))
|
||||||
:title (fn [r]
|
:title (fn [r]
|
||||||
(str
|
(str
|
||||||
(some-> r :rout-params :status name str/capitalize (str " "))
|
(some-> r :rout-params :status name str/capitalize (str " "))
|
||||||
@@ -344,7 +395,7 @@
|
|||||||
(condp = status
|
(condp = status
|
||||||
:payment-status/cleared
|
:payment-status/cleared
|
||||||
(com/pill {:color :primary} "cleared")
|
(com/pill {:color :primary} "cleared")
|
||||||
|
|
||||||
:payment-status/pending
|
:payment-status/pending
|
||||||
(com/pill {:color :secondary} "pending")
|
(com/pill {:color :secondary} "pending")
|
||||||
:payment-status/voided
|
:payment-status/voided
|
||||||
@@ -368,10 +419,10 @@
|
|||||||
(map :invoice-payment/invoice)
|
(map :invoice-payment/invoice)
|
||||||
(filter identity)
|
(filter identity)
|
||||||
(map (fn [invoice]
|
(map (fn [invoice]
|
||||||
{:link (hu/url (bidi/path-for ssr-routes/only-routes
|
{:link (hu/url (bidi/path-for ssr-routes/only-routes
|
||||||
::invoice-route/all-page)
|
::invoice-route/all-page)
|
||||||
{:exact-match-id (:db/id invoice)})
|
{:exact-match-id (:db/id invoice)})
|
||||||
:content (str "Inv. " (:invoice/invoice-number invoice))})))
|
:content (str "Inv. " (:invoice/invoice-number invoice))})))
|
||||||
(some-> p :transaction/_payment ((fn [t]
|
(some-> p :transaction/_payment ((fn [t]
|
||||||
[{:link (hu/url (bidi/path-for client-routes/routes
|
[{:link (hu/url (bidi/path-for client-routes/routes
|
||||||
:transactions)
|
:transactions)
|
||||||
|
|||||||
Reference in New Issue
Block a user