cleans stuff up.

This commit is contained in:
2024-11-23 21:13:15 -08:00
parent 39d8e6e71f
commit 98dcdb5a55
12 changed files with 79 additions and 92 deletions

View File

@@ -1,6 +1,6 @@
document.addEventListener('alpine:init', () => {
Alpine.directive('hx-val', (el, { value, expression }, { evaluateLater, effect, cleanup, evaluate }) => {
var config = function(evt) {
var config = function (evt) {
evt.detail.parameters[value] = evaluate(expression); // add a new parameter into the request
}
el.addEventListener('htmx:configRequest', config);
@@ -8,8 +8,8 @@ document.addEventListener('alpine:init', () => {
el.removeEventListener('htmx:configRequest', config);
})
})
Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effect, cleanup, evaluate }) => {
var config = function(evt) {
Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effect, cleanup, evaluate }) => {
var config = function (evt) {
evt.detail.headers[value] = evaluate(expression); // add a new parameter into the request
}
el.addEventListener('htmx:configRequest', config);
@@ -20,7 +20,7 @@ Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effec
Alpine.directive('dispatch', (el, { value, expression }, { evaluateLater, effect, cleanup, evaluate }) => {
let dependent_properties = evaluateLater(expression)
effect(() => {
dependent_properties(props => {
el.dispatchEvent(
@@ -38,16 +38,16 @@ Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effec
Alpine.directive(
"destroy",
(el, { expression }, { evaluateLater, cleanup }) => {
const onDestroy = evaluateLater(expression);
cleanup(onDestroy);
const onDestroy = evaluateLater(expression);
cleanup(onDestroy);
}
);
);
Alpine.data('popper', () => ({
show: false,
popper: null,
init() {
this.$nextTick(() => this.popper = Popper.createPopper(this.$refs.source, this.$refs.tooltip,
{ placement: 'bottom', strategy: 'fixed', modifiers: [{ name: 'preventOverflow' }, { name: 'offset', options: { offset: [0, 10] } }] }))
{ placement: 'bottom', strategy: 'fixed', modifiers: [{ name: 'preventOverflow' }, { name: 'offset', options: { offset: [0, 10] } }] }))
let reveal = () => {
if (!this.show) {
this.show = true;
@@ -62,10 +62,17 @@ Alpine.directive('hx-header', (el, { value, expression }, { evaluateLater, effec
},
tooltip: {
[':class']() { return {'opacity-0': !this.show, 'opacity-100': this.show, 'pointer-events-none': !this.show, 'transition': true } },
[':class']() { return { 'opacity-0': !this.show, 'opacity-100': this.show, 'pointer-events-none': !this.show, 'transition': true } },
["x-ref"]: 'tooltip',
['x-transition']: true
}
}))
}));
Alpine.store('darkMode', {
on: false,
toggle() {
this.on = ! this.on
}
})
})

File diff suppressed because one or more lines are too long

View File

@@ -154,7 +154,6 @@
:admin-history)
"hx-select" "#history-table"
"hx-swap" "innerHTML"
"hx-ext" "debug"
"hx-push-url" "true"}
(com/text-input {:name "entity-id" :placeholder "Entity Id" :value entity-id
:style {:width "300px"}})

View File

@@ -68,7 +68,7 @@
(dropdown-search-results* {:options (get-clients identity (get (:query-params request) "search-text"))})))
(defn dropdown [{:keys [client-selection client identity clients]}]
[:div#company-dropdown
[:div#company-dropdown {:x-data (hx/json {})}
[:script
(hiccup/raw
"localStorage.setItem(\"last-client-id\", \"" (:db/id client) "\")" "\n"
@@ -81,23 +81,25 @@
client-selection) ")")]
[: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"
"x-tooltip.on.click" "{content: ()=>$refs.tooltip.innerHTML, theme: 'light', onMount(i) { htmx.process(i.popper); }, allowHTML: true, interactive:true}"
:type "button"}
(cond
(= :mine client-selection)
"My Companies"
(= :all client-selection)
"All Companies"
(and client
(= 1 (count clients)))
(:client/name client)
:else
(str (count clients) " 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"}
[:template#company-dropdown-list {:x-ref "tooltip"}
[:div {:class "w-[300px]"
"x-init" "$refs.company.focus()"}
[:div {:class "p-3"}
[:label {:for "input-group-search", :class "sr-only"} "Search"]
[:div {:class "relative"}
@@ -105,6 +107,7 @@
[:div.w-5.h-5.text-gray-500.dark:text-gray-400
svg/search]]
[:input#company-search {:placeholder "Company name"
:x-ref "company"
: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

View File

@@ -33,7 +33,6 @@
(def modal-header-attachment dialog/modal-header-attachment-)
(def modal-body dialog/modal-body-)
(def modal-footer dialog/modal-footer-)
(def tooltip buttons/tooltip-)
(def tabs tabs/tabs-)
(def text-input inputs/text-input-)

View File

@@ -236,8 +236,3 @@
(if (seq children)
children
"Save")))
(defn tooltip- [{:as params} & children]
[:div (assoc params
:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 p-4 absolute")
[:span children]])

View File

@@ -1,20 +1,19 @@
(ns auto-ap.ssr.components.data-grid
(:require
[auto-ap.logging :as alog]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components.buttons :refer [a-button-]]
[auto-ap.ssr.components.card :refer [content-card-]]
[auto-ap.ssr.components.inputs :as inputs]
[auto-ap.ssr.components.paginator :refer [paginator-]]
[auto-ap.ssr.hiccup-helper :as hh]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.hx :as hx :refer [js-fn]]
[bidi.bidi :as bidi]
[hiccup.util :as hu]
[hiccup2.core :as hiccup]))
(defn header- [params & rest]
(into [:th.px-4.py-3 {:scope "col" :class (:class params)
"_" (hiccup/raw (when (:sort-key params ) (format "on click trigger sorted(key:\"%s\")", (:sort-key params))))
"@click" (format "$dispatch('sorted', {key: '%s'})" (:sort-key params))
:style (:style params)}]
(if (:sort-key params)
[(into [:a {:href "#"} ] rest)]
@@ -22,7 +21,7 @@
(defn sort-header- [params & rest]
[:th.px-4.py-3 {:scope "col" :class (:class params)
"_" (hiccup/raw (format "on click trigger sorted(key:\"%s\")", (:sort-key params)))}
"@click" (format "$dispatch('sorted', {key: '%s'})" (:sort-key params)) }
(into [:a {:href "#"} ] rest)])
(defn row- [params & rest]

View File

@@ -7,13 +7,13 @@
[hiccup2.core :as hiccup]))
(defn page- [{:keys [nav page-specific client clients client-selection identity app-params request] :or {app-params {}} } & children]
[:div#app {"_" (hiccup/raw "
on notification from body put event.detail.value into #notification-details then add .htmx-added to #notification-holder then remove .hidden from #notification-holder then wait 30ms then remove .htmx-added from #notification-holder "
)
[:div#app { "@notification.document" "notificationDetails=event.detail.value; showNotification=true"
:x-data (hx/json {:leftNavShow true
:showError false
:errorDetails ""})
:errorDetails ""
:showNotification false
:notificationDetails ""})
"@htmx:response-error.camel" "errorDetails = $event.detail.xhr.response; showError=true;"
}
(navbar- {:client-selection client-selection
@@ -31,18 +31,25 @@
":class" "leftNavShow ? 'lg:pl-64' : ''"
:x-effect "leftNavShow ? $el.classList.add('lg:pl-64') : $el.classList.remove('lg:pl-64')"
}
[:div#notification-holder.hidden
[:div.fixed.top-0.right-0.left-0.z-30.mx-auto.max-w-screen-lg.w-screen-lg.my-0.pt-8.rounded-lg
[:div#notification-holder
[:div.fixed.top-0.right-0.left-0.z-30.mx-auto.max-w-screen-lg.w-screen-lg.my-0.pt-8.rounded-lg {:x-show "showNotification" }
[:div.relative
[:button.absolute.right-2.top-2.w-6.h-6.z-50.text-blue-400
{"_" (hiccup/raw "on click add .hidden to #notification-holder")}
{ "@click" "showNotification=false"}
svg/filled-x]]
[:div.m-4.overflow-auto.z-30.flex.center-items.justify-center.text-blue-800.bg-blue-50.dark:bg-gray-800.dark:text-blue-400.border-blue-300.rounded-lg.border.transition-all.duration-500.fade-in.slide-up.max-h-96
[:div.m-4.overflow-auto.z-30.flex.center-items.justify-center.text-blue-800.bg-blue-50.dark:bg-gray-800.dark:text-blue-400.border-blue-300.rounded-lg.border.max-h-96
{:x-show "showNotification"
"x-transition:enter" "transition duration-300 transform ease-in-out"
"x-transition:enter-start" "opacity-0 translate-y-full"
"x-transition:enter-end" "opacity-100 translate-y-0"
"x-transition:leave" "transition duration-300 transform ease-in-out"
"x-transition:leave-start" "opacity-100 translate-y-0"
"x-transition:leave-end" "opacity-0 translate-y-full"}
[:div {:class "p-4 text-lg w-full" :role "alert"}
[:div.text-sm
[:pre#notification-details.text-xs]]]]]]
[:pre#notification-details.text-xs {:x-text "notificationDetails"}]]]]]]
[:div {:x-show "showError"
:x-init ""}
[:div.fixed.top-0.right-0.left-0.z-30.mx-auto.max-w-screen-lg.w-screen-lg.my-0.pt-8.rounded-lg

View File

@@ -11,18 +11,15 @@
[:div {:class "flex items-center ml-3 mr-10"}
[:div
[:button#user-menu-button {:type "button", :class "flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600", :aria-expanded "false"
"_" (hiccup/raw "init call initUserDropdown()")}
"@click" "$tooltip($refs.tooltip, {content: ()=>$refs.tooltip.innerHTML, theme: $store.darkMode.on ? 'dark' : 'light', allowHTML: true, interactive:true})"
}
[:span {:class "sr-only"} "Open user menu"]
[:img {:class "w-8 h-8 rounded-full", :src (pull-attr (dc/db conn) :user/profile-image-url (:db/id identity)) :alt "user photo" :referrerpolicy "no-referrer"}]]]
[:div#user-menu {:class "z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:bg-gray-700 dark:divide-gray-600 mr-10"}
[:template {:class ""
:x-ref "tooltip"}
[:div {:class "px-4 py-3", :role "none"}
[:p {:class "text-sm text-gray-900 dark:text-white", :role "none"} (:user/name identity)]
[:p {:class "text-sm font-medium text-gray-900 truncate dark:text-gray-300", :role "none"} (pull-attr (dc/db conn) :user/email (:db/id identity))]
#_(icon-button-
{"_" (hiccup/raw "on click toggle .dark on <body />")}
[:div.h-4.w-4
[:div.hidden.dark:block svg/sun]
[:div.dark:hidden svg/moon]])]
[:p {:class "text-sm font-medium text-gray-900 truncate dark:text-gray-300", :role "none"} (pull-attr (dc/db conn) :user/email (:db/id identity))] ]
[:ul {:class "py-1", :role "none"}
[:li
[:a {:href (bidi/path-for ssr-routes/only-routes :company), :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "My Company"]]
@@ -31,32 +28,7 @@
:class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "Admin"])
[:li
[:a {:href "#", :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"
"_" (hiccup/raw "on click toggle .dark on <body />")}
"@click.prevent" "$store.darkMode.toggle()" }
"Night Mode"]]
[:li
[:a {:href "/logout", :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "Sign out"]]]]
[:script {:lang "text/javascript"}
(hiccup/raw
"
function initUserDropdown() {
var $dropdownTargetEl = document.getElementById('user-menu');
// set the element that trigger the dropdown menu on click
var $dropdownTriggerEl = document.getElementById('user-menu-button');
var userDrowdown = new Dropdown($dropdownTargetEl, $dropdownTriggerEl, {
placement: 'bottom',
triggerType: 'click',
offsetSkidding: 0,
offsetDistance: 10,
delay: 5000,
onHide: () => {
},
onShow: () => {
},
onToggle: () => {
}
});
}
")]])
[:a {:href "/logout", :class "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white", :role "menuitem"} "Sign out"]]]] ])

View File

@@ -67,6 +67,14 @@
alpine-disappear)
(dissoc params :data-key)))
(defn alpine-mount-then-disappear [{:keys [data-key] :as params :or {data-key "show"}} ]
(merge (-> {:x-data (json {data-key true})
:x-init (format "$nextTick(() => %s=false)" (name data-key))
:x-show (name data-key)}
alpine-appear
alpine-disappear)
(dissoc params :data-key)))
(defn bind-alpine-vals [m field->alpine-field]
(assoc m "x-bind:hx-vals"

View File

@@ -15,7 +15,8 @@
[clj-time.coerce :as coerce]
[datomic.api :as dc]
[hiccup2.core :as hiccup]
[iol-ion.tx :refer [random-tempid]]))
[iol-ion.tx :refer [random-tempid]]
[auto-ap.ssr.hx :as hx]))
(def pull-expr [:transaction/description-original
:db/id
@@ -122,10 +123,10 @@
:score score}))
(defn transaction-row [r & {:keys [hide-actions? class last?] hs "_"}]
(defn transaction-row [r & {:keys [hide-actions? class last? other-params]}]
(com/data-grid-row
(cond-> {:class class}
hs (assoc "_" hs)
other-params (merge other-params)
last? (assoc :hx-get (bidi/path-for ssr-routes/only-routes
:transaction-insight-rows
@@ -223,7 +224,7 @@
(Long/parseLong transaction-id)))
:hide-actions? true
:class "live-added"
"_" (hiccup/raw "init transition opacity to 0 then remove me")))))
:other-params (hx/alpine-mount-then-disappear {})))))
(defn disapprove [{:keys [identity session] {:keys [transaction-id]} :route-params}]
(let [transaction-id (cond-> transaction-id string? (Long/parseLong))
@@ -231,8 +232,10 @@
@(dc/transact conn [[:upsert-transaction {:db/id transaction-id :transaction/outcome-recommendation nil}]])
(html-response (transaction-row
(parse-outcome (dc/pull db-before pull-expr transaction-id))
:class "live-removed"
:hide-actions? true
"_" (hiccup/raw "init transition opacity to 0 over 500ms then remove me")))))
:other-params (hx/alpine-mount-then-disappear {})))))
(defn explain [{:keys [identity session] {:keys [transaction-id]} :route-params}]
(let [r (dc/pull (dc/db conn)
pull-expr

View File

@@ -4,15 +4,14 @@
[config.core :refer [env]]
[hiccup2.core :as hiccup]
[auto-ap.ssr.components :as com]))
(defn html-page [hiccup]
{:status 200
:headers {"Content-Type" "text/html"}
:body (str
"<!DOCTYPE html>"
(hiccup/html
{}
hiccup))})
"<!DOCTYPE html>"
(hiccup/html
{}
hiccup))})
(defn base-page [request contents page-name]
@@ -28,8 +27,6 @@
[:link {:rel "stylesheet" :href "//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css"}]
[:script {:src "//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"}]
[:link {:rel "stylesheet", :href "/output.css"}]
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
[:script { :src "https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" :defer true}]
[:link {:rel "stylesheet" :href "https://unpkg.com/tippy.js@6/dist/tippy.css"}]
@@ -40,10 +37,7 @@
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
:crossorigin= "anonymous"}])
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/ext/class-tools.js" :crossorigin= "anonymous"}]
[:script {:src "https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"}]
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
[:script {:src "/js/htmx-disable.js"}]
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async"}]]
[:link {:rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.3.4/dist/css/datepicker.min.css"}]
@@ -52,14 +46,14 @@
[:script {:src "https://cdn.jsdelivr.net/npm/date-fns@3.6.0/cdn.min.js" :defer true}]
[:script {:src "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js" :integrity "sha512-CQBWl4fJHWbryGE+Pc7UAxWMUMNMWzWxF4SQo9CgkJIN1kx6djDQZjh3Y8SZ1d+6I+1zze6Z7kHXO7q3UyZAWw==" :crossorigin "anonymous" :referrerpolicy "no-referrer"}]
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js"}]
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js" :defer true}]
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
[:script {:defer true :src "/js/alpine-vals.js"}]
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-clipboard@2.x.x/dist/alpine-clipboard.js"}]
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.x.x/dist/cdn.min.js"}]
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"}]
[:script {:src "https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"}]
[:script {:src "https://cdn.jsdelivr.net/npm/jdenticon@3.3.0/dist/jdenticon.min.js" :async true :defer true :integrity "sha384-LfouGM03m83ArVtne1JPk926e3SGD0Tz8XHtW2OKGsgeBU/UfR0Fa8eX+UlwSSAZ" :crossorigin "anonymous" }]
[:script {:src "https://cdn.jsdelivr.net/npm/jdenticon@3.3.0/dist/jdenticon.min.js" :async true :defer true :integrity "sha384-LfouGM03m83ArVtne1JPk926e3SGD0Tz8XHtW2OKGsgeBU/UfR0Fa8eX+UlwSSAZ" :crossorigin "anonymous"}]
[:style
"
@@ -72,7 +66,8 @@ input::-webkit-inner-spin-button {
input[type=number] {
-moz-appearance:textfield; /* Firefox */
} "]
[:body {:hx-ext "disable-submit, class-tools"
[:body {:hx-ext "disable-submit"
":class" "$store.darkMode.on && 'dark'"
:x-data (hx/json {:globalClientSelection (or (:client-selection request)
:all)}) ;; TODO remove once session is used
:x-hx-header:x-clients "JSON.stringify(globalClientSelection)"}
@@ -114,4 +109,4 @@ input[type=number] {
"x-transition:leave-start" "!opacity-100 !translate-y-0"
"x-transition:leave-end" "!opacity-0 !translate-y-32"}
[:div#modal-content.flex.items-center.justify-center {:class "md:p-12"}]]]]]]))
[:div#modal-content.flex.items-center.justify-center {:class "md:p-12"}]]]]]]))