Makes company 1099 page work better and faster

This commit is contained in:
2023-05-12 12:27:48 -07:00
parent 0e814a8a4a
commit e78c73e093
15 changed files with 519 additions and 444 deletions

View File

@@ -12,6 +12,9 @@
.htmx-added .slide-up { .htmx-added .slide-up {
@apply translate-y-5 !important; @apply translate-y-5 !important;
} }
.hidden .slide-up {
@apply translate-y-5 !important;
}
.slide-up { .slide-up {
@apply translate-y-0; @apply translate-y-0;
} }

View 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;
}
}
})

View File

@@ -1149,10 +1149,6 @@ input:checked + .toggle-bg {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.ml-0 {
margin-left: 0px;
}
.ml-1 { .ml-1 {
margin-left: 0.25rem; margin-left: 0.25rem;
} }
@@ -1165,10 +1161,6 @@ input:checked + .toggle-bg {
margin-left: 0.75rem; margin-left: 0.75rem;
} }
.ml-8 {
margin-left: 2rem;
}
.mr-16 { .mr-16 {
margin-right: 4rem; margin-right: 4rem;
} }
@@ -1253,6 +1245,10 @@ input:checked + .toggle-bg {
height: 1rem; height: 1rem;
} }
.h-48 {
height: 12rem;
}
.h-5 { .h-5 {
height: 1.25rem; height: 1.25rem;
} }
@@ -1269,6 +1265,10 @@ input:checked + .toggle-bg {
height: 2rem; height: 2rem;
} }
.h-96 {
height: 24rem;
}
.h-\[calc\(100\%-1rem\)\] { .h-\[calc\(100\%-1rem\)\] {
height: calc(100% - 1rem); height: calc(100% - 1rem);
} }
@@ -1281,30 +1281,6 @@ input:checked + .toggle-bg {
height: 100vh; 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-h-full {
max-height: 100%; max-height: 100%;
} }
@@ -1345,23 +1321,10 @@ input:checked + .toggle-bg {
width: 2rem; width: 2rem;
} }
.w-auto {
width: auto;
}
.w-full { .w-full {
width: 100%; width: 100%;
} }
.w-max {
width: -moz-max-content;
width: max-content;
}
.w-2 {
width: 0.5rem;
}
.max-w-2xl { .max-w-2xl {
max-width: 42rem; max-width: 42rem;
} }
@@ -1510,16 +1473,12 @@ input:checked + .toggle-bg {
justify-content: space-between; justify-content: space-between;
} }
.gap-4 {
gap: 1rem;
}
.gap-2 { .gap-2 {
gap: 0.5rem; gap: 0.5rem;
} }
.gap-6 { .gap-4 {
gap: 1.5rem; gap: 1rem;
} }
.gap-8 { .gap-8 {
@@ -1568,18 +1527,6 @@ input:checked + .toggle-bg {
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); 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]) { .divide-y > :not([hidden]) ~ :not([hidden]) {
--tw-divide-y-reverse: 0; --tw-divide-y-reverse: 0;
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
@@ -1633,10 +1580,6 @@ input:checked + .toggle-bg {
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.rounded-xl {
border-radius: 0.75rem;
}
.rounded-l-lg { .rounded-l-lg {
border-top-left-radius: 0.5rem; border-top-left-radius: 0.5rem;
border-bottom-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)); 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 { .bg-green-500 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(121 181 46 / var(--tw-bg-opacity)); 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)); 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 { .bg-white {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity)); 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)); 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 { .bg-opacity-50 {
--tw-bg-opacity: 0.5; --tw-bg-opacity: 0.5;
} }
@@ -1823,14 +1746,6 @@ input:checked + .toggle-bg {
padding: 1.5rem; padding: 1.5rem;
} }
.p-8 {
padding: 2rem;
}
.p-5 {
padding: 1.25rem;
}
.px-2 { .px-2 {
padding-left: 0.5rem; padding-left: 0.5rem;
padding-right: 0.5rem; padding-right: 0.5rem;
@@ -1866,11 +1781,6 @@ input:checked + .toggle-bg {
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
} }
.py-1\.5 {
padding-top: 0.375rem;
padding-bottom: 0.375rem;
}
.py-2 { .py-2 {
padding-top: 0.5rem; padding-top: 0.5rem;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
@@ -1896,6 +1806,14 @@ input:checked + .toggle-bg {
padding-bottom: 1.25rem; padding-bottom: 1.25rem;
} }
.pb-2 {
padding-bottom: 0.5rem;
}
.pb-3 {
padding-bottom: 0.75rem;
}
.pl-10 { .pl-10 {
padding-left: 2.5rem; padding-left: 2.5rem;
} }
@@ -1904,6 +1822,10 @@ input:checked + .toggle-bg {
padding-left: 2.75rem; padding-left: 2.75rem;
} }
.pl-2 {
padding-left: 0.5rem;
}
.pl-3 { .pl-3 {
padding-left: 0.75rem; padding-left: 0.75rem;
} }
@@ -1912,6 +1834,14 @@ input:checked + .toggle-bg {
padding-left: 1rem; padding-left: 1rem;
} }
.pr-2 {
padding-right: 0.5rem;
}
.pr-2\.5 {
padding-right: 0.625rem;
}
.pt-16 { .pt-16 {
padding-top: 4rem; padding-top: 4rem;
} }
@@ -1924,18 +1854,6 @@ input:checked + .toggle-bg {
padding-top: 1.25rem; 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-left {
text-align: left; text-align: left;
} }
@@ -1978,10 +1896,6 @@ input:checked + .toggle-bg {
font-weight: 700; font-weight: 700;
} }
.font-light {
font-weight: 300;
}
.font-medium { .font-medium {
font-weight: 500; font-weight: 500;
} }
@@ -2054,6 +1968,11 @@ input:checked + .toggle-bg {
color: rgb(17 24 39 / var(--tw-text-opacity)); 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 { .text-primary-600 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(97 145 37 / var(--tw-text-opacity)); 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)); 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 { .text-yellow-800 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(114 59 19 / var(--tw-text-opacity)); 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 {
opacity: 0; opacity: 0;
} }
@@ -2169,6 +2073,10 @@ input:checked + .toggle-bg {
transition-duration: 300ms; transition-duration: 300ms;
} }
.duration-500 {
transition-duration: 500ms;
}
.duration-75 { .duration-75 {
transition-duration: 75ms; 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; 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 { .slide-up {
--tw-translate-y: 0px; --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)); 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)); 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 { .hover\:bg-green-600:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(97 145 37 / var(--tw-bg-opacity)); 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)); 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 { .hover\:text-blue-600:hover {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(0 125 187 / var(--tw-text-opacity)); 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)); 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 { .dark .dark\:border-gray-600 {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(75 85 99 / var(--tw-border-opacity)); 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)); 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 { .dark .dark\:bg-green-900 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(24 36 9 / var(--tw-bg-opacity)); 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 { .dark .dark\:bg-opacity-80 {
--tw-bg-opacity: 0.8; --tw-bg-opacity: 0.8;
} }
@@ -2538,6 +2456,11 @@ input:checked + .toggle-bg {
color: rgb(243 244 246 / var(--tw-text-opacity)); 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 { .dark .dark\:text-gray-300 {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity)); 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)); 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 { .dark .dark\:text-white {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity)); 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)); 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 { .dark .dark\:placeholder-gray-400::-moz-placeholder {
--tw-placeholder-opacity: 1; --tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity)); 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)); 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 { .dark .dark\:hover\:bg-green-700:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(73 109 28 / var(--tw-bg-opacity)); 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)); --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 { .dark .dark\:focus\:ring-gray-600:focus {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity)); --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
@@ -2677,10 +2610,6 @@ input:checked + .toggle-bg {
display: block; display: block;
} }
.sm\:flex {
display: flex;
}
.sm\:rounded-lg { .sm\:rounded-lg {
border-radius: 0.5rem; border-radius: 0.5rem;
} }
@@ -2742,10 +2671,6 @@ input:checked + .toggle-bg {
display: block; display: block;
} }
.lg\:inline {
display: inline;
}
.lg\:flex { .lg\:flex {
display: flex; display: flex;
} }
@@ -2804,10 +2729,6 @@ input:checked + .toggle-bg {
padding-left: 0.75rem; padding-left: 0.75rem;
} }
.lg\:pl-3\.5 {
padding-left: 0.875rem;
}
.lg\:pl-64 { .lg\:pl-64 {
padding-left: 16rem; padding-left: 16rem;
} }

View File

@@ -30,7 +30,8 @@
[ring.util.response :as response] [ring.util.response :as response]
[unilog.context :as lc] [unilog.context :as lc]
[clj-time.coerce :as coerce] [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) (when (:aws-access-key-id env)
(defcredential (:aws-access-key-id env) (:aws-secret-access-key env) (:aws-region 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))] (let [end-time (time/plus (time/now) (time/days 14))]
(assoc response :session (assoc session ::idle-timeout (coerce/to-date end-time))))))))))) (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]} #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(def app (def app
(-> route-handler (-> route-handler
(wrap-hx-current-url-params)
(wrap-guess-route) (wrap-guess-route)
(wrap-authorization auth-backend (wrap-authorization auth-backend
) )

View File

@@ -121,12 +121,19 @@
(->> results (->> results
(filter (fn [[_ _ a]] (filter (fn [[_ _ a]]
(>= (or a 0.0) 600.0))) (>= (or a 0.0) 600.0)))
(take 200)
(sort-by (fn [[client _ amount]] (sort-by (fn [[client _ amount]]
[(:client/code client ) amount]))))) [(:client/code client ) amount]))
(into []))))
(defn table* [{:keys [identity session]} & {:keys [flash-id]}] (defn table* [{:keys [identity session query-params hx-query-params]} & {:keys [flash-id]}]
(let [companies (take 30 (get-1099-companies identity session))] (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 [:div#vendor-table {:hx-get (bidi/path-for ssr-routes/only-routes
:company-1099-vendor-table :company-1099-vendor-table
:request-method :get) :request-method :get)
@@ -210,10 +217,20 @@
(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes (com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
:company-1099-vendor-dialog :company-1099-vendor-dialog
:vendor-id (:db/id vendor)) :vendor-id (:db/id vendor))
:hx-target "#modal-content" :hx-target "#modal-holder"
:hx-swap "outerHTML"} :hx-swap "outerHTML"}
svg/pencil))))))] 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] (defn form-data->map [form-data]
(reduce-kv (reduce-kv
@@ -246,7 +263,7 @@
(update :vendor/legal-entity-tin-type #(some->> % not-empty (keyword "legal-entity-tin-type")))))])) (update :vendor/legal-entity-tin-type #(some->> % not-empty (keyword "legal-entity-tin-type")))))]))
(html-response (html-response
(table* request :flash-id (Long/parseLong (:vendor-id route-params))) (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] (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 :vendor/legal-entity-tin-type [:db/ident]}] (Long/parseLong (:vendor-id (:params request))))] ;; TODO perms
(html-response (html-response
[:form {:hx-post (bidi/path-for ssr-routes/only-routes (com/modal {}
:company-1099-vendor-save [:form {:hx-post (str (bidi/path-for ssr-routes/only-routes
:request-method :post :company-1099-vendor-save
:vendor-id (Long/parseLong (:vendor-id (:params request)))) :request-method :post
:hx-target "#vendor-table" :vendor-id (Long/parseLong (:vendor-id (:params request)))))
:hx-swap "outerHTML swap:300ms"} :hx-target "#vendor-table"
(com/dialog :hx-swap "outerHTML swap:300ms"}
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]] [:fieldset {:class "hx-disable"}
[:div.space-y-6 (com/modal-card {}
[:div.grid.grid-cols-6.gap-4 [:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
[:h4.text-xl.border-b.col-span-6 "Address"] [:div.space-y-6
[:div.col-span-6 [:div.grid.grid-cols-6.gap-4
(com/field {:label "Street 1"} [:h4.text-xl.border-b.col-span-6 "Address"]
(com/text-input {:name (path->name [:vendor/address :address/street1]) [:div.col-span-6
:value (-> vendor :vendor/address :address/street1) (com/field {:label "Street 1"}
:placeholder "1700 Pennsylvania Ave" (com/text-input {:name (path->name [:vendor/address :address/street1])
:autofocus true}))] :value (-> vendor :vendor/address :address/street1)
[:div.col-span-6 :placeholder "1700 Pennsylvania Ave"
(com/field {:label "Street 2"} :autofocus true}))]
(com/text-input {:name (path->name [:vendor/address :address/street2]) [:div.col-span-6
:value (-> vendor :vendor/address :address/street2) (com/field {:label "Street 2"}
:placeholder "Suite 200"}))] (com/text-input {:name (path->name [:vendor/address :address/street2])
[:div.col-span-3 :value (-> vendor :vendor/address :address/street2)
(com/field {:label "City"} :placeholder "Suite 200"}))]
(com/text-input {:name (path->name [:vendor/address :address/city]) [:div.col-span-3
:value (-> vendor :vendor/address :address/city) (com/field {:label "City"}
:placeholder "Cupertino"}))] (com/text-input {:name (path->name [:vendor/address :address/city])
[:div.col-span-1 :value (-> vendor :vendor/address :address/city)
(com/field {:label "State"} :placeholder "Cupertino"}))]
(com/text-input {:name (path->name [:vendor/address :address/state]) [:div.col-span-1
:value (-> vendor :vendor/address :address/state) (com/field {:label "State"}
:placeholder "CA"}))] (com/text-input {:name (path->name [:vendor/address :address/state])
[:div.col-span-2 :value (-> vendor :vendor/address :address/state)
(com/field {:label "Zip"} :placeholder "CA"}))]
(com/text-input {:name (path->name [:vendor/address :address/zip]) [:div.col-span-2
:value (-> vendor :vendor/address :address/zip) (com/field {:label "Zip"}
:placeholder "98102"}))] (com/text-input {:name (path->name [:vendor/address :address/zip])
[:h4.text-xl.border-b.col-span-6 "Legal Entity"] :value (-> vendor :vendor/address :address/zip)
[:div.col-span-6 :placeholder "98102"}))]
(com/field {:label "Legal Entity Name"} [:h4.text-xl.border-b.col-span-6 "Legal Entity"]
(com/text-input {:name (path->name [:vendor/legal-entity-name]) [:div.col-span-6
:value (-> vendor :vendor/legal-entity-name) (com/field {:label "Legal Entity Name"}
:placeholder "Good Restaurant LLC"}))] (com/text-input {:name (path->name [:vendor/legal-entity-name])
[:div.col-span-6.text-center " - OR -"] :value (-> vendor :vendor/legal-entity-name)
[:div.col-span-2 :placeholder "Good Restaurant LLC"}))]
(com/field {:label "First Name"} [:div.col-span-6.text-center " - OR -"]
(com/text-input {:name (path->name [:vendor/legal-entity-first-name]) [:div.col-span-2
:value (-> vendor :vendor/legal-entity-first-name) (com/field {:label "First Name"}
:placeholder "John"}))] (com/text-input {:name (path->name [:vendor/legal-entity-first-name])
[:div.col-span-2 :value (-> vendor :vendor/legal-entity-first-name)
(com/field {:label "Middle Name"} :placeholder "John"}))]
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name]) [:div.col-span-2
:value (-> vendor :vendor/legal-entity-middle-name) (com/field {:label "Middle Name"}
:placeholder "C."}))] (com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
[:div.col-span-2 :value (-> vendor :vendor/legal-entity-middle-name)
(com/field {:label "Last Name"} :placeholder "C."}))]
(com/text-input {:name (path->name [:vendor/legal-entity-last-name]) [:div.col-span-2
:value (-> vendor :vendor/legal-entity-last-name) (com/field {:label "Last Name"}
:placeholder "Riley"}))] (com/text-input {:name (path->name [:vendor/legal-entity-last-name])
[:div.col-span-2 :value (-> vendor :vendor/legal-entity-last-name)
(com/field {:label "TIN"} :placeholder "Riley"}))]
(com/text-input {:name (path->name [:vendor/legal-entity-tin]) [:div.col-span-2
:value (-> vendor :vendor/legal-entity-tin) (com/field {:label "TIN"}
:placeholder "John"}))] (com/text-input {:name (path->name [:vendor/legal-entity-tin])
[:div.col-span-2 :value (-> vendor :vendor/legal-entity-tin)
(com/field {:label "TIN Type"} :placeholder "John"}))]
(com/select {:name (path->name [:vendor/legal-entity-tin-type]) [:div.col-span-2
:allow-blank? true (com/field {:label "TIN Type"}
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name) (com/select {:name (path->name [:vendor/legal-entity-tin-type])
:options [["ein" "EIN"] :allow-blank? true
["ssn" "SSN"]]}))] :value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
[:div.col-span-2 :options [["ein" "EIN"]
(com/field {:label "1099 Type"} ["ssn" "SSN"]]}))]
(com/select {:name (path->name [:vendor/legal-entity-1099-type]) [:div.col-span-2
:allow-blank? true (com/field {:label "1099 Type"}
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name) (com/select {:name (path->name [:vendor/legal-entity-1099-type])
:options [["none" "None"] :allow-blank? true
["misc" "Misc"] :value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
["landlord" "Landlord"]]}))] :options [["none" "None"]
[:div.col-span-6 ["misc" "Misc"]
(com/button {:color :primary} ["landlord" "Landlord"]]}))]
"Save")]]] [:div.col-span-6
[:div])] (com/button {:color :primary}
:headers {"hx-trigger" "openDialog"}))) "Save")]]]
[:div])]]))))
(defn vendor-table [request] (defn vendor-table [request]
(html-response (com/page (html-response (table* request)
{:nav :headers {"hx-push-url" (str "?start=" (get (:query-params request) "start"))}))
(com/company-aside-nav)}
(com/breadcrumbs {}
[:a {:href "#"} "My Company"]
[:a {:href "#"} "1099 Vendor Info"])
(table* request))))
(defn page [{:keys [identity matched-route] :as request}] (defn page [{:keys [identity matched-route] :as request}]
(base-page (base-page
request 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 {} (com/breadcrumbs {}
[:a {:href "#"} "My Company"] [:a {:href "#"} "My Company"]
[:a {:href "#"} "1099 Vendor Info"]) [:a {:href "#"} "1099 Vendor Info"])

View File

@@ -2,103 +2,130 @@
(:require (:require
[auto-ap.datomic :refer [conn]] [auto-ap.datomic :refer [conn]]
[auto-ap.graphql.utils :refer [assert-can-see-client]] [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-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]] [auto-ap.ssr.utils :refer [html-response]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup2.core :as hiccup])) [hiccup2.core :as hiccup]
[iol-ion.query :refer [can-see-client?]]))
(defn dropdown-contents [{:keys [identity]}] (defn dropdown-search-results* [{:keys [options]}]
(let [options (->> (dc/q '[:find ?c ?n [:ul
:in $ ?user (for [option options]
:where [?c :client/name ?n] [:li
[(iol-ion.query/can-see-client? ?user ?c)]] [:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
(dc/db conn)
identity) [:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
(map (fn [[k v]] "_" (hiccup/raw "on click set value of <#company-search-value/> to @data-value then send selected to #company-dropdown")
{"key" k :data-value (get option "key")}
"value" v})))] (get option "value")]]])])
(html-response
[:div.navbar-dropdown {:style {:width "20em"}} (defn get-clients [identity query]
[:a.navbar-item {:hx-put (bidi/path-for ssr-routes/only-routes (dc/q '[:find ?c ?n
:active-client :in $ ?user ?q
:request-method :put) :where [?c :client/name ?n]
:hx-target "#company-dropdown" [(clojure.string/includes? ?n ?q)]
:hx-swap "outerHTML" [(iol-ion.query/can-see-client? ?user ?c)]]
:hx-trigger "click"} (dc/db conn)
"All"] identity
[:hr.navbar-divider] (or query "")))
[:input#company-search.input.navbar-item {:placeholder "Company name"
:name "search-text" (defn dropdown-search-results [{:keys [identity] :as request}]
:autoFocus true} ] (html-response
[:input#company-search-value {:type "hidden" (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" :autocomplete "off"
:name "search-client" :name "search-client"
:hx-put (bidi/path-for ssr-routes/only-routes :hx-put (bidi/path-for ssr-routes/only-routes
:active-client :active-client
:request-method :put) :request-method :put)
:hx-target "#company-dropdown" :hx-target "#company-dropdown"
:hx-swap "outerHTML" :hx-swap "outerHTML"
:hx-trigger "change"} ] :hx-trigger "change changed"} ]]
[:script [:div.divide-y.divide-gray-100
(hiccup/raw [:div#company-search-results {:class "h-48 px-3 pb-3 overflow-y-auto text-sm text-gray-700 dark:text-gray-200"}]
(str " [:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
var z = new autoComplete({
selector:\"#company-search\",
placeholder: \"Company Name....\",
data: {
keys: [\"value\"],
src: " (cheshire.core/encode
options)
" [: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
resultItem: { :active-client
highlight:true, :request-method :put)
class: \"autocomplete-suggestion\", :hx-target "#company-dropdown"
selected: \"highlighted\" :hx-swap "outerHTML"
:hx-trigger "click"}
"All"]]]
]]
[:script {:lang "text/javascript"}
(hiccup/raw
"
function initCompanyDropdown() {
var $dropdownTargetEl = document.getElementById('company-dropdown-list');
}, // set the element that trigger the dropdown menu on click
resultsList: { var $dropdownTriggerEl = document.getElementById('company-dropdown-button');
tabSelect: true
},
submit: true
}); var dropdownOptions = {
z.input.addEventListener(\"selection\", function (event) { placement: 'bottom',
z.input.blur(); triggerType: 'click',
z.input.value = event.detail.selection.value.value; offsetSkidding: 0,
document.getElementById(\"company-search-value\").value= event.detail.selection.value.key; offsetDistance: 10,
document.getElementById(\"company-search-value\").dispatchEvent(new Event('change')); delay: 300,
onHide: () => {
}); },
"))]]))) onShow: () => {
document.getElementById('company-search').focus()
(defn dropdown [request] },
onToggle: () => {
(let [client (get-in request [:session :client])] }
};
(navbar-dropdown var companyDrowdown = new Dropdown($dropdownTargetEl, $dropdownTriggerEl, dropdownOptions);
"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]])))
(defn active-client [{:keys [identity params] :as request}] (defn active-client [{:keys [identity params] :as request}]
(let [client-id (some-> (or (:search-client params) (get params "search-client")) not-empty Long/parseLong)] (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)))] (dc/pull (dc/db conn) [:db/id :client/name :client/code] client-id)))]
(assoc (assoc
(html-response (html-response
(dropdown (assoc request :session new-session))) (dropdown {:client (:client new-session)
:identity identity}))
:session :session
new-session new-session
:headers :headers

View File

@@ -15,7 +15,8 @@
(def button buttons/button-) (def button buttons/button-)
(def button-icon buttons/button-icon-) (def button-icon buttons/button-icon-)
(def icon-button buttons/icon-button-) (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 text-input inputs/text-input-)
(def select inputs/select-) (def select inputs/select-)
@@ -43,29 +44,62 @@
:class (str "font-medium text-blue-600 dark:text-blue-500 hover:underline " class)}] :class (str "font-medium text-blue-600 dark:text-blue-500 hover:underline " class)}]
children)) 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"} [: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 "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"} (str (inc start)) "-" (str end) " of " (str total)]]
[:span {:class "font-semibold text-gray-900 dark:text-white"} "1000"]] (paginator- params)])
[: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"}]]]]]])

View File

@@ -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] (defn modal- [params & children]
[:div#modal-content [: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 "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 "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600"} header]
[:div {:class "p-6 space-y-6"} [:div {:class "p-6 space-y-6"}
content] content]
[:div footer]]]) [:div footer]]
])

View File

@@ -3,9 +3,10 @@
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[hiccup2.core :as hiccup] [hiccup2.core :as hiccup]
[bidi.bidi :as bidi] [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"} [: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 "px-3 py-3 lg:px-5 lg:pl-3"}
[:div {:class "flex items-center justify-between"} [: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"} [: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"}] [: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) [:div {:class "flex items-center gap-4"}
:hx-target "#modal-content" [: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-swap "innerHTML"} :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 {: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] [:div.w-4.h-4 svg/search]
[:span.ml-2 "Search"]]]] [:span.ml-2 "Search"]]]
[:div {:class "flex items-center gap-4"}
[:div {:class "hidden mr-3 -mb-1 sm:block"} [:div {:class "hidden mr-3 -mb-1 sm:block"}
[:span]] [:span]]
(icon-button- (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" {: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 :hx-get (bidi/path-for ssr-routes/only-routes
:search) :search)
:hx-target "#modal-content" :hx-target "#modal-holder"
:hx-swap "innerHTML"} :hx-swap "outerHTML"}
svg/search) svg/search)
#_[:button #_[:button
[:div.w-4.h-4 svg/search]] [: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 "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 "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"} [:div {:class "grid grid-cols-3 gap-4 p-4"}

View File

@@ -3,9 +3,10 @@
[auto-ap.ssr.components.aside :refer [left-aside-]] [auto-ap.ssr.components.aside :refer [left-aside-]]
[hiccup2.core :as hiccup])) [hiccup2.core :as hiccup]))
(defn page- [{:keys [nav page-specific]} & children] (defn page- [{:keys [nav page-specific active-client identity]} & children]
[:div#app [:div#app
(navbar-) (navbar- {:client active-client
:identity identity})
[:div.flex.pt-16.overflow-hidden [:div.flex.pt-16.overflow-hidden
(left-aside- {:nav nav (left-aside- {:nav nav
:page-specific page-specific}) :page-specific page-specific})
@@ -14,11 +15,13 @@
(into (into
[:div.p-4] [:div.p-4]
children)]] children)]]
[:div#modal-holder.hidden
#_[:div#modal-holder.hidden
{"_" (hiccup/raw "on click trigger closeDialog")} {"_" (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 {:class "bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40"
}]]]) }]]
[:div#modal-holder]])

View File

@@ -18,7 +18,8 @@
:admin-history-search (wrap-client-redirect-unauthenticated (wrap-secure (wrap-admin admin/history-search))) :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))) :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))) :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 (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-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)) :company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))

View File

@@ -130,26 +130,26 @@
(if-let [q (get (:form-params request) "q")] (if-let [q (get (:form-params request) "q")]
(html-response (search-results* q (:identity request))) (html-response (search-results* q (:identity request)))
(html-response (html-response
(com/dialog (com/modal {}
[:div.p-2 "Search"] (com/modal-card {}
[:div#search.overflow-auto.space-y-6.p-2.h-96 [:div.p-2 "Search"]
[:div#search.overflow-auto.space-y-6.p-2.h-96
(com/text-input {:id "search-input"
:type "search" (com/text-input {:id "search-input"
:placeholder "5/5/2034 Magheritas" :type "search"
:name "q" :placeholder "5/5/2034 Magheritas"
:hx-post "/search" :name "q"
:hx-trigger "keyup changed delay:300ms, search" :hx-post "/search"
:hx-target "#search-results" :hx-trigger "keyup changed delay:300ms, search"
:hx-indicator "#search" :hx-target "#search-results"
:value (:q (:params request)) :hx-indicator "#search"
:autofocus true}) :value (:q (:params request))
[: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'."] :autofocus true})
#_[:style [: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'."]
".htmx-request #search-results {display: none} .htmx-request .htmx-indicator { display: block !important; }"] #_[:style
[:div#search-results ".htmx-request #search-results {display: none} .htmx-request .htmx-indicator { display: block !important; }"]
] [:div#search-results
[:div.loader.is-loading.big.htmx-indicator ]] ]
nil) [:div.loader.is-loading.big.htmx-indicator ]]
:headers {"hx-trigger" "openDialog"}))) nil)))))

View File

@@ -193,3 +193,7 @@
:stroke "currentColor", :stroke "currentColor",
:stroke-linecap "round", :stroke-linecap "round",
:stroke-linejoin "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"}]])

View File

@@ -29,11 +29,12 @@
:crossorigin= "anonymous"}] :crossorigin= "anonymous"}]
[:script {:src "https://unpkg.com/htmx.org@1.9.0/dist/htmx.js" [:script {:src "https://unpkg.com/htmx.org@1.9.0/dist/htmx.js"
:crossorigin= "anonymous"}] :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.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 {: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"}] [: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"}] [: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 contents
[:script {:src "/js/flowbite.min.js"}] [:script {:src "/js/flowbite.min.js"}]
[:script {:lang "text/javascript"} [:script {:lang "text/javascript"}
@@ -53,4 +54,13 @@
} }
}; };
const collapse = new Collapse($targetEl, $triggerEl, options); ")]]])) const collapse = new Collapse($targetEl, $triggerEl, options);
;
"
)]]]))

View File

@@ -13,7 +13,7 @@
["/approve/" [#"\d+" :transaction-id]] {:post :transaction-insight-approve} ["/approve/" [#"\d+" :transaction-id]] {:post :transaction-insight-approve}
["/rows/" [#"\d+" :after]] {:get :transaction-insight-rows} ["/rows/" [#"\d+" :after]] {:get :transaction-insight-rows}
["/explain/" [#"\d+" :transaction-id]] {:get :transaction-insight-explain}}} ["/explain/" [#"\d+" :transaction-id]] {:get :transaction-insight-explain}}}
"company" {"/dropdown" :company-dropdown-contents "company" {"/dropdown" :company-dropdown-search-results
"/active" {:put :active-client} "/active" {:put :active-client}
"/1099" :company-1099 "/1099" :company-1099
"/1099/table" {:get :company-1099-vendor-table} "/1099/table" {:get :company-1099-vendor-table}