Makes company 1099 page work better and faster
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
.htmx-added .slide-up {
|
||||
@apply translate-y-5 !important;
|
||||
}
|
||||
.hidden .slide-up {
|
||||
@apply translate-y-5 !important;
|
||||
}
|
||||
.slide-up {
|
||||
@apply translate-y-0;
|
||||
}
|
||||
|
||||
16
resources/public/js/htmx-disable.js
Normal file
16
resources/public/js/htmx-disable.js
Normal file
@@ -0,0 +1,16 @@
|
||||
htmx.defineExtension('disable-submit', {
|
||||
onEvent: function (name, evt, data) {
|
||||
let elt = evt.detail.elt;
|
||||
let result = elt.querySelectorAll('.hx-disable');
|
||||
|
||||
if (name === 'htmx:beforeRequest') {
|
||||
result.forEach(element => element.disabled = true);
|
||||
if (elt.classList.contains('hx-disable')) {
|
||||
elt.disabled = true;}
|
||||
|
||||
} else if(name == 'htmx:afterRequest') {
|
||||
result.forEach(element => element.disabled = false);
|
||||
if (elt.classList.contains('hx-disable')) elt.disabled = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1149,10 +1149,6 @@ input:checked + .toggle-bg {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.ml-0 {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.ml-1 {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
@@ -1165,10 +1161,6 @@ input:checked + .toggle-bg {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.ml-8 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.mr-16 {
|
||||
margin-right: 4rem;
|
||||
}
|
||||
@@ -1253,6 +1245,10 @@ input:checked + .toggle-bg {
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.h-48 {
|
||||
height: 12rem;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
@@ -1269,6 +1265,10 @@ input:checked + .toggle-bg {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.h-96 {
|
||||
height: 24rem;
|
||||
}
|
||||
|
||||
.h-\[calc\(100\%-1rem\)\] {
|
||||
height: calc(100% - 1rem);
|
||||
}
|
||||
@@ -1281,30 +1281,6 @@ input:checked + .toggle-bg {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.h-2 {
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
.h-48 {
|
||||
height: 12rem;
|
||||
}
|
||||
|
||||
.h-64 {
|
||||
height: 16rem;
|
||||
}
|
||||
|
||||
.h-80 {
|
||||
height: 20rem;
|
||||
}
|
||||
|
||||
.h-1\/2 {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.h-96 {
|
||||
height: 24rem;
|
||||
}
|
||||
|
||||
.max-h-full {
|
||||
max-height: 100%;
|
||||
}
|
||||
@@ -1345,23 +1321,10 @@ input:checked + .toggle-bg {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.w-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-max {
|
||||
width: -moz-max-content;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.w-2 {
|
||||
width: 0.5rem;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
@@ -1510,16 +1473,12 @@ input:checked + .toggle-bg {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.gap-6 {
|
||||
gap: 1.5rem;
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.gap-8 {
|
||||
@@ -1568,18 +1527,6 @@ input:checked + .toggle-bg {
|
||||
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.space-y-8 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(2rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-y-reverse: 0;
|
||||
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
||||
@@ -1633,10 +1580,6 @@ input:checked + .toggle-bg {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.rounded-l-lg {
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
@@ -1746,6 +1689,11 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(228 240 213 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-500 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(121 181 46 / var(--tw-bg-opacity));
|
||||
@@ -1756,16 +1704,6 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(242 248 234 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-red-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(153 2 2 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-slate-300 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(203 213 225 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
@@ -1780,21 +1718,6 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-blue-200 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(153 215 247 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-blue-300 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(102 196 242 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-green-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(228 240 213 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-opacity-50 {
|
||||
--tw-bg-opacity: 0.5;
|
||||
}
|
||||
@@ -1823,14 +1746,6 @@ input:checked + .toggle-bg {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.p-8 {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.p-5 {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
@@ -1866,11 +1781,6 @@ input:checked + .toggle-bg {
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.py-1\.5 {
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
@@ -1896,6 +1806,14 @@ input:checked + .toggle-bg {
|
||||
padding-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.pb-2 {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.pb-3 {
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.pl-10 {
|
||||
padding-left: 2.5rem;
|
||||
}
|
||||
@@ -1904,6 +1822,10 @@ input:checked + .toggle-bg {
|
||||
padding-left: 2.75rem;
|
||||
}
|
||||
|
||||
.pl-2 {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.pl-3 {
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
@@ -1912,6 +1834,14 @@ input:checked + .toggle-bg {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.pr-2 {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.pr-2\.5 {
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
|
||||
.pt-16 {
|
||||
padding-top: 4rem;
|
||||
}
|
||||
@@ -1924,18 +1854,6 @@ input:checked + .toggle-bg {
|
||||
padding-top: 1.25rem;
|
||||
}
|
||||
|
||||
.pb-2 {
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.pr-2 {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.pr-2\.5 {
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
@@ -1978,10 +1896,6 @@ input:checked + .toggle-bg {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.font-light {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -2054,6 +1968,11 @@ input:checked + .toggle-bg {
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(48 72 18 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-primary-600 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(97 145 37 / var(--tw-text-opacity));
|
||||
@@ -2064,26 +1983,11 @@ input:checked + .toggle-bg {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-yellow-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(227 160 8 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-yellow-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(114 59 19 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-200 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(229 231 235 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-green-800 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(48 72 18 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.opacity-0 {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -2169,6 +2073,10 @@ input:checked + .toggle-bg {
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
|
||||
.duration-500 {
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
.duration-75 {
|
||||
transition-duration: 75ms;
|
||||
}
|
||||
@@ -2194,6 +2102,11 @@ input:checked + .toggle-bg {
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important;
|
||||
}
|
||||
|
||||
.hidden .slide-up {
|
||||
--tw-translate-y: 1.25rem !important;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important;
|
||||
}
|
||||
|
||||
.slide-up {
|
||||
--tw-translate-y: 0px;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
@@ -2296,6 +2209,16 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-green-100:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(228 240 213 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-green-600:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(97 145 37 / var(--tw-bg-opacity));
|
||||
@@ -2316,11 +2239,6 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-gray-200:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:text-blue-600:hover {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(0 125 187 / var(--tw-text-opacity));
|
||||
@@ -2446,6 +2364,11 @@ input:checked + .toggle-bg {
|
||||
border-color: rgb(0 156 234 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:border-gray-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(107 114 128 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:border-gray-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
@@ -2504,21 +2427,16 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(97 145 37 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-yellow-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(99 49 18 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-blue-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(0 94 140 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-green-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(24 36 9 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-yellow-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(99 49 18 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:bg-opacity-80 {
|
||||
--tw-bg-opacity: 0.8;
|
||||
}
|
||||
@@ -2538,6 +2456,11 @@ input:checked + .toggle-bg {
|
||||
color: rgb(243 244 246 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-200 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(229 231 235 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||
@@ -2548,6 +2471,16 @@ input:checked + .toggle-bg {
|
||||
color: rgb(156 163 175 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-50 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(249 250 251 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-green-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(175 211 130 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
@@ -2558,16 +2491,6 @@ input:checked + .toggle-bg {
|
||||
color: rgb(250 202 21 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-green-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(175 211 130 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:text-gray-50 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(249 250 251 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:placeholder-gray-400::-moz-placeholder {
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||
@@ -2602,6 +2525,11 @@ input:checked + .toggle-bg {
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:hover\:bg-green-600:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(97 145 37 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:hover\:bg-green-700:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(73 109 28 / var(--tw-bg-opacity));
|
||||
@@ -2642,6 +2570,11 @@ input:checked + .toggle-bg {
|
||||
--tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:focus\:ring-blue-800:focus {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(0 62 94 / var(--tw-ring-opacity));
|
||||
}
|
||||
|
||||
.dark .dark\:focus\:ring-gray-600:focus {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
|
||||
@@ -2677,10 +2610,6 @@ input:checked + .toggle-bg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sm\:flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sm\:rounded-lg {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
@@ -2742,10 +2671,6 @@ input:checked + .toggle-bg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lg\:inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.lg\:flex {
|
||||
display: flex;
|
||||
}
|
||||
@@ -2804,10 +2729,6 @@ input:checked + .toggle-bg {
|
||||
padding-left: 0.75rem;
|
||||
}
|
||||
|
||||
.lg\:pl-3\.5 {
|
||||
padding-left: 0.875rem;
|
||||
}
|
||||
|
||||
.lg\:pl-64 {
|
||||
padding-left: 16rem;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
[ring.util.response :as response]
|
||||
[unilog.context :as lc]
|
||||
[clj-time.coerce :as coerce]
|
||||
[clj-time.core :as time]))
|
||||
[clj-time.core :as time]
|
||||
[cemerick.url :as url]))
|
||||
|
||||
(when (:aws-access-key-id env)
|
||||
(defcredential (:aws-access-key-id env) (:aws-secret-access-key env) (:aws-region env)))
|
||||
@@ -161,9 +162,17 @@
|
||||
(let [end-time (time/plus (time/now) (time/days 14))]
|
||||
(assoc response :session (assoc session ::idle-timeout (coerce/to-date end-time)))))))))))
|
||||
|
||||
(defn wrap-hx-current-url-params
|
||||
[handler ]
|
||||
(fn [request]
|
||||
(let [query-params (some-> (get-in request [:headers "hx-current-url"]) (url/url ) :query)
|
||||
request (assoc request :hx-query-params query-params)]
|
||||
(handler request))))
|
||||
|
||||
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
||||
(def app
|
||||
(-> route-handler
|
||||
(wrap-hx-current-url-params)
|
||||
(wrap-guess-route)
|
||||
(wrap-authorization auth-backend
|
||||
)
|
||||
|
||||
@@ -121,12 +121,19 @@
|
||||
(->> results
|
||||
(filter (fn [[_ _ a]]
|
||||
(>= (or a 0.0) 600.0)))
|
||||
(take 200)
|
||||
(sort-by (fn [[client _ amount]]
|
||||
[(:client/code client ) amount])))))
|
||||
[(:client/code client ) amount]))
|
||||
(into []))))
|
||||
|
||||
(defn table* [{:keys [identity session]} & {:keys [flash-id]}]
|
||||
(let [companies (take 30 (get-1099-companies identity session))]
|
||||
(defn table* [{:keys [identity session query-params hx-query-params]} & {:keys [flash-id]}]
|
||||
(println hx-query-params)
|
||||
(let [start (or (some-> (or (get query-params "start") (get hx-query-params "start")) not-empty (Long/parseLong ))
|
||||
0)
|
||||
per-page (or (some-> (or (get query-params "per-page") (get hx-query-params "per-page")) not-empty (Long/parseLong ))
|
||||
30)
|
||||
companies (get-1099-companies identity session)
|
||||
total (count companies)
|
||||
companies (subvec companies (Math/min start total) (Math/min (+ start per-page) total))]
|
||||
[:div#vendor-table {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-table
|
||||
:request-method :get)
|
||||
@@ -210,10 +217,20 @@
|
||||
(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-dialog
|
||||
:vendor-id (:db/id vendor))
|
||||
:hx-target "#modal-content"
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
svg/pencil))))))]
|
||||
(com/paginator))]))
|
||||
(com/paginator {:start start
|
||||
:end (Math/min (+ start per-page) total)
|
||||
:per-page per-page
|
||||
:total total
|
||||
:a-params (fn [page]
|
||||
{:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-table
|
||||
:request-method :get)
|
||||
"?start=" (* page per-page))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML show:#app:top"})}))]))
|
||||
|
||||
(defn form-data->map [form-data]
|
||||
(reduce-kv
|
||||
@@ -246,7 +263,7 @@
|
||||
(update :vendor/legal-entity-tin-type #(some->> % not-empty (keyword "legal-entity-tin-type")))))]))
|
||||
(html-response
|
||||
(table* request :flash-id (Long/parseLong (:vendor-id route-params)))
|
||||
:headers {"hx-trigger" "closeDialog"}))
|
||||
:headers {"hx-trigger" "closeModal"}))
|
||||
|
||||
|
||||
|
||||
@@ -254,104 +271,102 @@
|
||||
(let [vendor (dc/pull (dc/db conn) '[* {:vendor/legal-entity-1099-type [:db/ident]
|
||||
:vendor/legal-entity-tin-type [:db/ident]}] (Long/parseLong (:vendor-id (:params request))))] ;; TODO perms
|
||||
(html-response
|
||||
[:form {:hx-post (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-save
|
||||
:request-method :post
|
||||
:vendor-id (Long/parseLong (:vendor-id (:params request))))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
(com/dialog
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
|
||||
[:div.space-y-6
|
||||
[:div.grid.grid-cols-6.gap-4
|
||||
[:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 1"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street1])
|
||||
:value (-> vendor :vendor/address :address/street1)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true}))]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 2"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street2])
|
||||
:value (-> vendor :vendor/address :address/street2)
|
||||
:placeholder "Suite 200"}))]
|
||||
[:div.col-span-3
|
||||
(com/field {:label "City"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/city])
|
||||
:value (-> vendor :vendor/address :address/city)
|
||||
:placeholder "Cupertino"}))]
|
||||
[:div.col-span-1
|
||||
(com/field {:label "State"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/state])
|
||||
:value (-> vendor :vendor/address :address/state)
|
||||
:placeholder "CA"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Zip"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/zip])
|
||||
:value (-> vendor :vendor/address :address/zip)
|
||||
:placeholder "98102"}))]
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Legal Entity Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-name])
|
||||
:value (-> vendor :vendor/legal-entity-name)
|
||||
:placeholder "Good Restaurant LLC"}))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "First Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-first-name])
|
||||
:value (-> vendor :vendor/legal-entity-first-name)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Middle Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
|
||||
:value (-> vendor :vendor/legal-entity-middle-name)
|
||||
:placeholder "C."}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Last Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-last-name])
|
||||
:value (-> vendor :vendor/legal-entity-last-name)
|
||||
:placeholder "Riley"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-tin])
|
||||
:value (-> vendor :vendor/legal-entity-tin)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-tin-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "1099 Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-1099-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
|
||||
:options [["none" "None"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]}))]
|
||||
[:div.col-span-6
|
||||
(com/button {:color :primary}
|
||||
"Save")]]]
|
||||
[:div])]
|
||||
:headers {"hx-trigger" "openDialog"})))
|
||||
(com/modal {}
|
||||
[:form {:hx-post (str (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-save
|
||||
:request-method :post
|
||||
:vendor-id (Long/parseLong (:vendor-id (:params request)))))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
[:fieldset {:class "hx-disable"}
|
||||
(com/modal-card {}
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
|
||||
[:div.space-y-6
|
||||
[:div.grid.grid-cols-6.gap-4
|
||||
[:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 1"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street1])
|
||||
:value (-> vendor :vendor/address :address/street1)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true}))]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 2"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street2])
|
||||
:value (-> vendor :vendor/address :address/street2)
|
||||
:placeholder "Suite 200"}))]
|
||||
[:div.col-span-3
|
||||
(com/field {:label "City"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/city])
|
||||
:value (-> vendor :vendor/address :address/city)
|
||||
:placeholder "Cupertino"}))]
|
||||
[:div.col-span-1
|
||||
(com/field {:label "State"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/state])
|
||||
:value (-> vendor :vendor/address :address/state)
|
||||
:placeholder "CA"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Zip"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/zip])
|
||||
:value (-> vendor :vendor/address :address/zip)
|
||||
:placeholder "98102"}))]
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Legal Entity Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-name])
|
||||
:value (-> vendor :vendor/legal-entity-name)
|
||||
:placeholder "Good Restaurant LLC"}))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "First Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-first-name])
|
||||
:value (-> vendor :vendor/legal-entity-first-name)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Middle Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
|
||||
:value (-> vendor :vendor/legal-entity-middle-name)
|
||||
:placeholder "C."}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Last Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-last-name])
|
||||
:value (-> vendor :vendor/legal-entity-last-name)
|
||||
:placeholder "Riley"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-tin])
|
||||
:value (-> vendor :vendor/legal-entity-tin)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-tin-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "1099 Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-1099-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
|
||||
:options [["none" "None"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]}))]
|
||||
[:div.col-span-6
|
||||
(com/button {:color :primary}
|
||||
"Save")]]]
|
||||
[:div])]]))))
|
||||
|
||||
(defn vendor-table [request]
|
||||
(html-response (com/page
|
||||
{:nav
|
||||
(com/company-aside-nav)}
|
||||
(com/breadcrumbs {}
|
||||
[:a {:href "#"} "My Company"]
|
||||
[:a {:href "#"} "1099 Vendor Info"])
|
||||
(table* request))))
|
||||
(html-response (table* request)
|
||||
:headers {"hx-push-url" (str "?start=" (get (:query-params request) "start"))}))
|
||||
|
||||
(defn page [{:keys [identity matched-route] :as request}]
|
||||
(base-page
|
||||
request
|
||||
(com/page {:nav (com/company-aside-nav)}
|
||||
(com/page {:nav (com/company-aside-nav)
|
||||
:active-client (:client (:session request))
|
||||
:identity (:identity request)}
|
||||
(com/breadcrumbs {}
|
||||
[:a {:href "#"} "My Company"]
|
||||
[:a {:href "#"} "1099 Vendor Info"])
|
||||
|
||||
@@ -2,103 +2,130 @@
|
||||
(:require
|
||||
[auto-ap.datomic :refer [conn]]
|
||||
[auto-ap.graphql.utils :refer [assert-can-see-client]]
|
||||
[iol-ion.query :refer [can-see-client?]]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.components.navbar-dropdown :refer [navbar-dropdown]]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.utils :refer [html-response]]
|
||||
[bidi.bidi :as bidi]
|
||||
[datomic.api :as dc]
|
||||
[hiccup2.core :as hiccup]))
|
||||
[hiccup2.core :as hiccup]
|
||||
[iol-ion.query :refer [can-see-client?]]))
|
||||
|
||||
(defn dropdown-contents [{:keys [identity]}]
|
||||
(let [options (->> (dc/q '[:find ?c ?n
|
||||
:in $ ?user
|
||||
:where [?c :client/name ?n]
|
||||
[(iol-ion.query/can-see-client? ?user ?c)]]
|
||||
(dc/db conn)
|
||||
identity)
|
||||
(map (fn [[k v]]
|
||||
{"key" k
|
||||
"value" v})))]
|
||||
(html-response
|
||||
[:div.navbar-dropdown {:style {:width "20em"}}
|
||||
[:a.navbar-item {:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
"All"]
|
||||
[:hr.navbar-divider]
|
||||
[:input#company-search.input.navbar-item {:placeholder "Company name"
|
||||
:name "search-text"
|
||||
:autoFocus true} ]
|
||||
[:input#company-search-value {:type "hidden"
|
||||
(defn dropdown-search-results* [{:keys [options]}]
|
||||
[:ul
|
||||
(for [option options]
|
||||
[:li
|
||||
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
|
||||
|
||||
[:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
|
||||
"_" (hiccup/raw "on click set value of <#company-search-value/> to @data-value then send selected to #company-dropdown")
|
||||
:data-value (get option "key")}
|
||||
(get option "value")]]])])
|
||||
|
||||
(defn get-clients [identity query]
|
||||
(dc/q '[:find ?c ?n
|
||||
:in $ ?user ?q
|
||||
:where [?c :client/name ?n]
|
||||
[(clojure.string/includes? ?n ?q)]
|
||||
[(iol-ion.query/can-see-client? ?user ?c)]]
|
||||
(dc/db conn)
|
||||
identity
|
||||
(or query "")))
|
||||
|
||||
(defn dropdown-search-results [{:keys [identity] :as request}]
|
||||
(html-response
|
||||
(dropdown-search-results* {:options (->> (get-clients identity (get (:query-params request) "search-text"))
|
||||
(map (fn [[k v]]
|
||||
{"key" k
|
||||
"value" v})))
|
||||
:client (:client (:session request))})))
|
||||
|
||||
(defn dropdown [{:keys [client]}]
|
||||
[:div#company-dropdown
|
||||
{:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-include "#company-search-value"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "selected"}
|
||||
[:script
|
||||
(hiccup/raw
|
||||
"localStorage.setItem(\"last-client-id\", \""(:db/id client)"\")")]
|
||||
[:div
|
||||
[:button#company-dropdown-button { :class "text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
|
||||
:type "button"}
|
||||
(if client
|
||||
(:client/name client)
|
||||
"All Companies")
|
||||
[:div.w-4.h-4.ml-2
|
||||
svg/drop-down]]
|
||||
[:div#company-dropdown-list.hidden {"_" (hiccup/raw "init call initCompanyDropdown()")
|
||||
}
|
||||
[:div {:class "z-10 bg-white rounded-lg shadow w-64 dark:bg-gray-700 slide-up duration-500 transition-all"}
|
||||
[:div {:class "p-3"}
|
||||
[:label {:for "input-group-search", :class "sr-only"} "Search"]
|
||||
[:div {:class "relative"}
|
||||
[:div {:class "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"}
|
||||
[:div.w-5.h-5.text-gray-500.dark:text-gray-400
|
||||
svg/search]]
|
||||
[:input#company-search {:placeholder "Company name"
|
||||
:name "search-text"
|
||||
:class "block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
:autoFocus true
|
||||
:tab-index -1
|
||||
:hx-trigger "keyup changed delay:500ms, search"
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-dropdown-search-results)
|
||||
:hx-target "#company-search-results"
|
||||
:hx-swap "innerHTML"} ]]
|
||||
[:input#company-search-value {:type "hidden"
|
||||
:autocomplete "off"
|
||||
:name "search-client"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "change"} ]
|
||||
[:script
|
||||
(hiccup/raw
|
||||
(str "
|
||||
var z = new autoComplete({
|
||||
selector:\"#company-search\",
|
||||
placeholder: \"Company Name....\",
|
||||
data: {
|
||||
keys: [\"value\"],
|
||||
src: " (cheshire.core/encode
|
||||
options)
|
||||
:name "search-client"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "change changed"} ]]
|
||||
[:div.divide-y.divide-gray-100
|
||||
[:div#company-search-results {:class "h-48 px-3 pb-3 overflow-y-auto text-sm text-gray-700 dark:text-gray-200"}]
|
||||
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
|
||||
|
||||
"
|
||||
},
|
||||
resultItem: {
|
||||
highlight:true,
|
||||
class: \"autocomplete-suggestion\",
|
||||
selected: \"highlighted\"
|
||||
[:button {:class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
"All"]]]
|
||||
]]
|
||||
[:script {:lang "text/javascript"}
|
||||
(hiccup/raw
|
||||
"
|
||||
function initCompanyDropdown() {
|
||||
var $dropdownTargetEl = document.getElementById('company-dropdown-list');
|
||||
|
||||
},
|
||||
resultsList: {
|
||||
tabSelect: true
|
||||
},
|
||||
submit: true
|
||||
// set the element that trigger the dropdown menu on click
|
||||
var $dropdownTriggerEl = document.getElementById('company-dropdown-button');
|
||||
|
||||
});
|
||||
z.input.addEventListener(\"selection\", function (event) {
|
||||
z.input.blur();
|
||||
z.input.value = event.detail.selection.value.value;
|
||||
document.getElementById(\"company-search-value\").value= event.detail.selection.value.key;
|
||||
document.getElementById(\"company-search-value\").dispatchEvent(new Event('change'));
|
||||
|
||||
});
|
||||
"))]])))
|
||||
|
||||
(defn dropdown [request]
|
||||
|
||||
(let [client (get-in request [:session :client])]
|
||||
|
||||
(navbar-dropdown
|
||||
"company-dropdown"
|
||||
[:span
|
||||
(if client
|
||||
(str "Company: " (:client/name client))
|
||||
"Company")
|
||||
[:script
|
||||
(hiccup/raw
|
||||
"localStorage.setItem(\"last-client-id\", \""(:db/id client)"\")")]]
|
||||
[:div {:hx-get
|
||||
(bidi/path-for ssr-routes/only-routes
|
||||
:company-dropdown-contents)
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "intersect delay:150ms"
|
||||
:hx-target "closest .navbar-dropdown"
|
||||
:style {:width "20em"
|
||||
:height "80px"}
|
||||
}
|
||||
[:div.loader.is-loading.is-active.is-centered]])))
|
||||
var dropdownOptions = {
|
||||
placement: 'bottom',
|
||||
triggerType: 'click',
|
||||
offsetSkidding: 0,
|
||||
offsetDistance: 10,
|
||||
delay: 300,
|
||||
onHide: () => {
|
||||
},
|
||||
onShow: () => {
|
||||
document.getElementById('company-search').focus()
|
||||
},
|
||||
onToggle: () => {
|
||||
}
|
||||
};
|
||||
var companyDrowdown = new Dropdown($dropdownTargetEl, $dropdownTriggerEl, dropdownOptions);
|
||||
}
|
||||
")]]])
|
||||
|
||||
(defn active-client [{:keys [identity params] :as request}]
|
||||
(let [client-id (some-> (or (:search-client params) (get params "search-client")) not-empty Long/parseLong)]
|
||||
@@ -109,7 +136,8 @@ document.getElementById(\"company-search-value\").dispatchEvent(new Event('chang
|
||||
(dc/pull (dc/db conn) [:db/id :client/name :client/code] client-id)))]
|
||||
(assoc
|
||||
(html-response
|
||||
(dropdown (assoc request :session new-session)))
|
||||
(dropdown {:client (:client new-session)
|
||||
:identity identity}))
|
||||
:session
|
||||
new-session
|
||||
:headers
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
(def button buttons/button-)
|
||||
(def button-icon buttons/button-icon-)
|
||||
(def icon-button buttons/icon-button-)
|
||||
(def dialog dialog/dialog-)
|
||||
(def modal dialog/modal-)
|
||||
(def modal-card dialog/modal-card-)
|
||||
|
||||
(def text-input inputs/text-input-)
|
||||
(def select inputs/select-)
|
||||
@@ -43,29 +44,62 @@
|
||||
:class (str "font-medium text-blue-600 dark:text-blue-500 hover:underline " class)}]
|
||||
children))
|
||||
|
||||
(defn paginator []
|
||||
(defn bound [x y z]
|
||||
(cond
|
||||
(< z x)
|
||||
x
|
||||
(< y x)
|
||||
x
|
||||
(> y z)
|
||||
z
|
||||
:else
|
||||
y))
|
||||
|
||||
(def elipsis-button
|
||||
[:p {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400"} "..."])
|
||||
|
||||
(defn paginator- [{:keys [start per-page end total a-params]}]
|
||||
(let [per-page (or per-page 20)
|
||||
max-buttons 5
|
||||
buttons-before (Math/floor (/ max-buttons 2))
|
||||
total-pages (long (Math/max (long 1) (long (Math/ceil (/ total per-page)))))
|
||||
current-page (long (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)]
|
||||
[:li
|
||||
[:a (-> (a-params x)
|
||||
(update
|
||||
:class #(cond-> %
|
||||
true (str " flex items-center justify-center px-3 py-2 text-sm leading-tight border ")
|
||||
|
||||
(= current-page x)
|
||||
(str " text-primary-600 bg-primary-50 border-primary-300 hover:bg-primary-100 hover:text-primary-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white")
|
||||
|
||||
(not= current-page x)
|
||||
(str " text-gray-500 bg-white border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white")))
|
||||
(assoc :href "#"))
|
||||
(inc x)]]))
|
||||
|
||||
|
||||
last-page-button (Math/min (long total-pages) (long (+ max-buttons first-page-button)))
|
||||
|
||||
extended-last-page-button (when (not= last-page-button total-pages)
|
||||
(list
|
||||
elipsis-button
|
||||
(last all-buttons)))
|
||||
|
||||
extended-first-page-button (when (not= first-page-button 0)
|
||||
(list
|
||||
(first all-buttons)
|
||||
elipsis-button))]
|
||||
[:nav
|
||||
[:ul {:class "inline-flex items-stretch -space-x-px"}
|
||||
extended-first-page-button
|
||||
(apply list (subvec all-buttons first-page-button last-page-button))
|
||||
extended-last-page-button]]))
|
||||
|
||||
(defn paginator [{:keys [start per-page end total a-params] :as params}]
|
||||
[:nav {:class "flex flex-col items-start justify-between p-4 space-y-3 md:flex-row md:items-center md:space-y-0", :aria-label "Table navigation"}
|
||||
[:span {:class "text-sm font-normal text-gray-500 dark:text-gray-400"}
|
||||
[:span {:class "font-semibold text-gray-900 dark:text-white"} "1-10"]
|
||||
[:span {:class "font-semibold text-gray-900 dark:text-white"} "1000"]]
|
||||
[:ul {:class "inline-flex items-stretch -space-x-px"}
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center h-full py-1.5 px-3 ml-0 text-gray-500 bg-white rounded-l-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"}
|
||||
[:span {:class "sr-only"} "Previous"]
|
||||
[:svg {:class "w-5 h-5", :aria-hidden "true", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
|
||||
[:path {:fill-rule "evenodd", :d "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z", :clip-rule "evenodd"}]]]]
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"} "1"]]
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"} "2"]]
|
||||
[:li
|
||||
[:a {:href "#", :aria-current "page", :class "z-10 flex items-center justify-center px-3 py-2 text-sm leading-tight border text-primary-600 bg-primary-50 border-primary-300 hover:bg-primary-100 hover:text-primary-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white"} "3"]]
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"} "..."]]
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"} "100"]]
|
||||
[:li
|
||||
[:a {:href "#", :class "flex items-center justify-center h-full py-1.5 px-3 leading-tight text-gray-500 bg-white rounded-r-lg border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"}
|
||||
[:span {:class "sr-only"} "Next"]
|
||||
[:svg {:class "w-5 h-5", :aria-hidden "true", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
|
||||
[:path {:fill-rule "evenodd", :d "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", :clip-rule "evenodd"}]]]]]])
|
||||
[:span {:class "font-semibold text-gray-900 dark:text-white"} (str (inc start)) "-" (str end) " of " (str total)]]
|
||||
(paginator- params)])
|
||||
|
||||
@@ -1,9 +1,44 @@
|
||||
(ns auto-ap.ssr.components.dialog)
|
||||
(ns auto-ap.ssr.components.dialog
|
||||
(:require [hiccup2.core :as hiccup]))
|
||||
|
||||
(defn dialog- [header content footer]
|
||||
[:div#modal-content
|
||||
(defn modal- [params & children]
|
||||
[:div
|
||||
[:div#modal-holder { :tabindex "-1", :class "fixed top-0 left-0 right-0 z-50 w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full flex justify-center hidden" :aria-hidden true
|
||||
"_" (hiccup/raw "on closeModal transition <#modal-holder .modal-content /> opacity to 0.0 over 300ms then call hideModal()")}
|
||||
[:div {:class "relative w-full max-w-2xl max-h-full"}
|
||||
(into [:div#modal-content]
|
||||
children)]
|
||||
]
|
||||
[:script {:lang "text/javascript"}
|
||||
(hiccup/raw "
|
||||
var modal_element = document.getElementById('modal-holder');
|
||||
var modal_options = {
|
||||
placement: 'center',
|
||||
backdrop: 'dynamic',
|
||||
backdropClasess: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40',
|
||||
closable: true,
|
||||
onOpen: function() {
|
||||
modal_element.dispatchEvent('openModal');
|
||||
|
||||
},
|
||||
onHide: function() {
|
||||
modal_element.outerHTML='<div id=\"modal-holder\"></div>';
|
||||
},
|
||||
};
|
||||
var curModal = new Modal(modal_element, modal_options);
|
||||
curModal.show();
|
||||
function hideModal() {
|
||||
curModal.hide();
|
||||
}
|
||||
")
|
||||
|
||||
]])
|
||||
|
||||
(defn modal-card- [params header content footer]
|
||||
[:div#modal-card
|
||||
[:div {:class "relative bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white fade-in slide-up duration-300 transition-all modal-content"}
|
||||
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600"} header]
|
||||
[:div {:class "p-6 space-y-6"}
|
||||
content]
|
||||
[:div footer]]])
|
||||
[:div footer]]
|
||||
])
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[hiccup2.core :as hiccup]
|
||||
[bidi.bidi :as bidi]
|
||||
[auto-ap.ssr-routes :as ssr-routes]))
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.company-dropdown :as cd]))
|
||||
|
||||
(defn navbar- []
|
||||
(defn navbar- [{:keys [client identity]}]
|
||||
[:nav {:class "fixed z-30 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700"}
|
||||
[:div {:class "px-3 py-3 lg:px-5 lg:pl-3"}
|
||||
[:div {:class "flex items-center justify-between"}
|
||||
@@ -17,36 +18,31 @@
|
||||
[:a {:href "https://flowbite-admin-dashboard.vercel.app/", :class "flex ml-2 md:mr-24"}
|
||||
[:img {:src "/img/logo-big2.png", :class "h-10 mr-16", :alt "Integreat logo"}]
|
||||
]
|
||||
[:button.mt-1.lg:w-96.relative.hidden.lg:block {:class "bg-gray-50 hover:bg-gray-200 dark:hover:bg-gray-700 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 w-full pl-10 py-4 pr-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 gap-4 "
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:search)
|
||||
:hx-target "#modal-content"
|
||||
:hx-swap "innerHTML"}
|
||||
]
|
||||
|
||||
[:div {:class "flex items-center gap-4"}
|
||||
[:button.mt-1.lg:w-96.relative.hidden.lg:block {:class "bg-gray-50 hover:bg-gray-200 dark:hover:bg-gray-700 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 w-full pl-10 py-4 pr-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 gap-4 "
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:search)
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
[:div {:class "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-gray-500"}
|
||||
[:div.w-4.h-4 svg/search]
|
||||
[:span.ml-2 "Search"]]]]
|
||||
|
||||
[:div {:class "flex items-center gap-4"}
|
||||
[:span.ml-2 "Search"]]]
|
||||
[:div {:class "hidden mr-3 -mb-1 sm:block"}
|
||||
[:span]]
|
||||
(icon-button-
|
||||
{:id "toggleSidebarMobileSearch", :type "button", :class "p-2 text-gray-500 rounded-lg lg:hidden hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:search)
|
||||
:hx-target "#modal-content"
|
||||
:hx-swap "innerHTML"}
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
svg/search)
|
||||
#_[:button
|
||||
[:div.w-4.h-4 svg/search]]
|
||||
(cd/dropdown {:client client :identity identity})
|
||||
|
||||
|
||||
|
||||
#_[:button {:type "button", :data-dropdown-toggle "apps-dropdown", :class "hidden p-2 text-gray-500 rounded-lg sm:flex hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-700"}
|
||||
[:span {:class "sr-only"} "View notifications"]
|
||||
[:svg {:class "w-6 h-6", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
|
||||
[:path {:d "M5 3a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2V5a2 2 0 00-2-2H5zM5 11a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2v-2a2 2 0 00-2-2H5zM11 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V5zM11 13a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"}]]]
|
||||
#_(com/icon-button {}
|
||||
[:div.w-4.h-4 svg/search])
|
||||
[:div {:class "z-20 z-50 max-w-sm my-4 overflow-hidden text-base list-none bg-white divide-y divide-gray-100 rounded shadow-lg dark:bg-gray-700 dark:divide-gray-600 hidden", :id "apps-dropdown", :style "position: absolute; inset: 0px auto auto 0px; margin: 0px; transform: translate(1545px, 65px);", :data-popper-placement "bottom"}
|
||||
[:div {:class "block px-4 py-2 text-base font-medium text-center text-gray-700 bg-gray-50 dark:bg-gray-700 dark:text-gray-400"} ]
|
||||
[:div {:class "grid grid-cols-3 gap-4 p-4"}
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
[auto-ap.ssr.components.aside :refer [left-aside-]]
|
||||
[hiccup2.core :as hiccup]))
|
||||
|
||||
(defn page- [{:keys [nav page-specific]} & children]
|
||||
(defn page- [{:keys [nav page-specific active-client identity]} & children]
|
||||
[:div#app
|
||||
(navbar-)
|
||||
(navbar- {:client active-client
|
||||
:identity identity})
|
||||
[:div.flex.pt-16.overflow-hidden
|
||||
(left-aside- {:nav nav
|
||||
:page-specific page-specific})
|
||||
@@ -14,11 +15,13 @@
|
||||
(into
|
||||
[:div.p-4]
|
||||
children)]]
|
||||
[:div#modal-holder.hidden
|
||||
|
||||
|
||||
|
||||
|
||||
#_[:div#modal-holder.hidden
|
||||
{"_" (hiccup/raw "on click trigger closeDialog")}
|
||||
[:div { :tabindex "-1", :class "fixed top-0 left-0 right-0 z-50 w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full flex justify-center "}
|
||||
[:div {:class "relative w-full max-w-2xl max-h-full"
|
||||
"_" (hiccup/raw "on click halt the event")}
|
||||
[:div#modal-content ]]]
|
||||
|
||||
[:div {:class "bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40"
|
||||
}]]])
|
||||
}]]
|
||||
[:div#modal-holder]])
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
:admin-history-search (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin admin/history-search)))
|
||||
:admin-history-inspect (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin admin/inspect)))
|
||||
:active-client (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin company-dropdown/active-client)))
|
||||
:company-dropdown-contents (wrap-client-redirect-unauthenticated (wrap-secure company-dropdown/dropdown-contents))
|
||||
:company-dropdown-search-results
|
||||
(wrap-client-redirect-unauthenticated (wrap-secure company-dropdown/dropdown-search-results))
|
||||
:company-1099 (wrap-client-redirect-unauthenticated (wrap-secure company-1099/page))
|
||||
:company-1099-vendor-table (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-table))
|
||||
:company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))
|
||||
|
||||
@@ -130,26 +130,26 @@
|
||||
(if-let [q (get (:form-params request) "q")]
|
||||
(html-response (search-results* q (:identity request)))
|
||||
(html-response
|
||||
(com/dialog
|
||||
[:div.p-2 "Search"]
|
||||
[:div#search.overflow-auto.space-y-6.p-2.h-96
|
||||
|
||||
(com/text-input {:id "search-input"
|
||||
:type "search"
|
||||
:placeholder "5/5/2034 Magheritas"
|
||||
:name "q"
|
||||
:hx-post "/search"
|
||||
:hx-trigger "keyup changed delay:300ms, search"
|
||||
:hx-target "#search-results"
|
||||
:hx-indicator "#search"
|
||||
:value (:q (:params request))
|
||||
:autofocus true})
|
||||
[:i.text-sm.text-gray-600.dark:text-gray-50 "Try dates, numbers, vendors. To filter to specific type, use 'invoice', 'transaction', 'journal-entry', 'payment'."]
|
||||
#_[:style
|
||||
".htmx-request #search-results {display: none} .htmx-request .htmx-indicator { display: block !important; }"]
|
||||
[:div#search-results
|
||||
]
|
||||
[:div.loader.is-loading.big.htmx-indicator ]]
|
||||
nil)
|
||||
:headers {"hx-trigger" "openDialog"})))
|
||||
(com/modal {}
|
||||
(com/modal-card {}
|
||||
[:div.p-2 "Search"]
|
||||
[:div#search.overflow-auto.space-y-6.p-2.h-96
|
||||
|
||||
(com/text-input {:id "search-input"
|
||||
:type "search"
|
||||
:placeholder "5/5/2034 Magheritas"
|
||||
:name "q"
|
||||
:hx-post "/search"
|
||||
:hx-trigger "keyup changed delay:300ms, search"
|
||||
:hx-target "#search-results"
|
||||
:hx-indicator "#search"
|
||||
:value (:q (:params request))
|
||||
:autofocus true})
|
||||
[:i.text-sm.text-gray-600.dark:text-gray-50 "Try dates, numbers, vendors. To filter to specific type, use 'invoice', 'transaction', 'journal-entry', 'payment'."]
|
||||
#_[:style
|
||||
".htmx-request #search-results {display: none} .htmx-request .htmx-indicator { display: block !important; }"]
|
||||
[:div#search-results
|
||||
]
|
||||
[:div.loader.is-loading.big.htmx-indicator ]]
|
||||
nil)))))
|
||||
|
||||
|
||||
@@ -193,3 +193,7 @@
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]])
|
||||
|
||||
(def drop-down
|
||||
[:svg {:class "w-4 h-4 ml-2", :aria-hidden "true", :fill "none", :stroke "currentColor", :viewbox "0 0 24 24", :xmlns "http://www.w3.org/2000/svg"}
|
||||
[:path {:stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "M19 9l-7 7-7-7"}]])
|
||||
|
||||
@@ -29,11 +29,12 @@
|
||||
:crossorigin= "anonymous"}]
|
||||
[:script {:src "https://unpkg.com/htmx.org@1.9.0/dist/htmx.js"
|
||||
:crossorigin= "anonymous"}]
|
||||
[:script {:src "/js/htmx-disable.js"}]
|
||||
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async" }]]
|
||||
[:script {:type "text/javascript", :src "https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/autoComplete.min.js"}]
|
||||
[:script {:src "https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"}]
|
||||
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
|
||||
[:body {"_" (hiccup/raw "on closeDialog transition <#modal-holder .modal-content /> opacity to 0.0 over 300ms then add .hidden to <#modal-holder /> on openDialog remove .hidden from #modal-holder")}
|
||||
[:body {:hx-ext "disable-submit"}
|
||||
contents
|
||||
[:script {:src "/js/flowbite.min.js"}]
|
||||
[:script {:lang "text/javascript"}
|
||||
@@ -53,4 +54,13 @@
|
||||
}
|
||||
};
|
||||
|
||||
const collapse = new Collapse($targetEl, $triggerEl, options); ")]]]))
|
||||
const collapse = new Collapse($targetEl, $triggerEl, options);
|
||||
|
||||
|
||||
;
|
||||
|
||||
"
|
||||
|
||||
|
||||
|
||||
)]]]))
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
["/approve/" [#"\d+" :transaction-id]] {:post :transaction-insight-approve}
|
||||
["/rows/" [#"\d+" :after]] {:get :transaction-insight-rows}
|
||||
["/explain/" [#"\d+" :transaction-id]] {:get :transaction-insight-explain}}}
|
||||
"company" {"/dropdown" :company-dropdown-contents
|
||||
"company" {"/dropdown" :company-dropdown-search-results
|
||||
"/active" {:put :active-client}
|
||||
"/1099" :company-1099
|
||||
"/1099/table" {:get :company-1099-vendor-table}
|
||||
|
||||
Reference in New Issue
Block a user