Makes tailwind version of history page

This commit is contained in:
Bryce
2023-06-01 09:26:52 -07:00
parent fad492e26d
commit 3540346fc8
14 changed files with 253 additions and 246 deletions

View File

@@ -1,5 +1,6 @@
htmx.defineExtension('disable-submit', {
onEvent: function (name, evt, data) {
/*
let elt = evt.detail.elt;
let result = elt.querySelectorAll('.hx-disable');
@@ -12,5 +13,6 @@ htmx.defineExtension('disable-submit', {
result.forEach(element => element.disabled = false);
if (elt.classList.contains('hx-disable')) elt.disabled = false;
}
*/
}
})

View File

@@ -1228,6 +1228,10 @@ input:checked + .toggle-bg {
margin-top: 1.25rem;
}
.mt-4 {
margin-top: 1rem;
}
.block {
display: block;
}
@@ -1368,6 +1372,10 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
.max-w-lg {
max-width: 32rem;
}
.flex-1 {
flex: 1 1 0%;
}
@@ -1773,6 +1781,11 @@ input:checked + .toggle-bg {
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
}
.bg-red-100 {
--tw-bg-opacity: 1;
background-color: rgb(255 205 205 / var(--tw-bg-opacity));
}
.bg-opacity-50 {
--tw-bg-opacity: 0.5;
}
@@ -2520,6 +2533,11 @@ input:checked + .toggle-bg {
background-color: rgb(99 49 18 / var(--tw-bg-opacity));
}
:is(.dark .dark\:bg-red-900) {
--tw-bg-opacity: 1;
background-color: rgb(51 1 1 / var(--tw-bg-opacity));
}
:is(.dark .dark\:bg-opacity-80) {
--tw-bg-opacity: 0.8;
}
@@ -2584,6 +2602,11 @@ input:checked + .toggle-bg {
color: rgb(250 202 21 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-red-300) {
--tw-text-opacity: 1;
color: rgb(255 104 104 / var(--tw-text-opacity));
}
:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
@@ -2730,6 +2753,10 @@ input:checked + .toggle-bg {
margin-right: 6rem;
}
.md\:table-cell {
display: table-cell;
}
.md\:flex-row {
flex-direction: row;
}
@@ -2760,6 +2787,10 @@ input:checked + .toggle-bg {
display: flex;
}
.lg\:table-cell {
display: table-cell;
}
.lg\:hidden {
display: none;
}

View File

@@ -2,14 +2,15 @@
(:require
[auto-ap.datomic :refer [conn]]
[auto-ap.logging :as alog]
[auto-ap.shared-views.admin.side-bar :refer [admin-side-bar]]
[auto-ap.ssr.ui :refer [base-page]]
[auto-ap.ssr.utils :refer [html-response]]
[auto-ap.time :as atime]
[clj-time.coerce :as coerce]
[clojure.string :as str]
[datomic.api :as dc]
[hiccup2.core :as hiccup]))
[auto-ap.ssr.components :as com]
[auto-ap.ssr-routes :as ssr-routes]
[bidi.bidi :as bidi]))
(defn tx-rows->changes [history]
(->> history
@@ -25,9 +26,6 @@
changes))]
[t a changes])))))
(def error-script
(hiccup/raw "on htmx:responseError from me set event.detail.target's innerHTML to event.detail.xhr.responseText end"))
(defn format-value [v]
(cond (inst? v)
(-> v
@@ -40,126 +38,27 @@
(and (integer? v)
(> v 1000000))
[:span
[:a {:hx-get (str "/admin/history/" v)
:hx-swap "innerHTML"
:hx-push-url "true"
:hx-target "#history-table"}
v]
" [" [:a
{:hx-get (str "/admin/history/inspect/" v)
:hx-swap "innerHTML"
:hx-target "#inspector"
:hx-trigger "click"
"_" error-script}
"snapshot"] "]"]
[:span
(com/link
{:href "#"
:hx-get (str "/admin/history/" v)
:hx-swap "innerHTML"
:hx-push-url "true"
:hx-select "#history-table"
:hx-target "#history-table"}
v)
" ["
(com/link
{:href "#"
:hx-get (str "/admin/history/inspect/" v)
:hx-swap "innerHTML"
:hx-target "#inspector"
:hx-trigger "click"}
"snapshot") "]"]
:else
(pr-str v)))
(defn page-template [& {:keys [table entity-id]}]
[:div
[:div.columns
[:div.column.is-4
[:form {"hx-target" "#history-table"
"hx-post" "/admin/history/search"
"hx-swap" "innerHTML"
"_" (hiccup/raw "on htmx:beforeRequest toggle @disabled on me then toggle .is-loading on <#dig/> end
on htmx:afterRequest toggle @disabled on me then toggle .is-loading on <#dig /> end")
}
[:div.field.is-grouped
[:p.control {}
[:input.input {:type "text" :name "entity-id" :placeholder "Entity id" :value entity-id}]]
[:p.control
[:button#dig.button.is-primary {}
"Dig"]]]]]]
[:div#history-table
table]])
(defn table [entity-id best-guess-entity history]
[:div [:h1.title "History for "
(str/capitalize best-guess-entity)
" "
entity-id]
[:div.columns
[:div.column.is-9
[:table.table.compact.grid {:style "width: 100%"}
[:thead
[:tr
[:td {:style "width: 14em"} "Date"]
[:td {:style "width: 14em"} "User"]
[:td {:style "width: 18em"} "Field"]
[:td "From"]
[:td "To"]]]
[:tbody
(for [[tx a c] history]
[:tr
[:td [:div [:div (some-> (:db/txInstant tx)
coerce/to-date-time
atime/localize
(atime/unparse atime/standard-time))
]
[:div.tag (:db/id tx)]]]
[:td (str (:audit/user tx))]
[:td (namespace a) ": " (name a)]
[:td
[:div.tag.is-danger.is-light
[:span
(format-value (:removed c))]]]
[:td
[:div.tag.is-primary.is-light
[:span
(format-value (:added c))]]]])]
]]
[:div.column.is-3
[:div#inspector]]]])
(defn history-search [{:keys [form-params params] :as request}]
(try
(let [entity-id (Long/parseLong (or (some-> (:entity-id form-params) not-empty)
(:entity-id params)
(get params "entity-id")
(get form-params "entity-id")))
history (->>
(dc/q '[:find ?a2 ?v (pull ?tx [:db/txInstant :audit/user :db/id]) ?ad
:in $ $$ ?i
:where
[$$ ?i ?a ?v ?tx ?ad]
[$ ?a :db/ident ?a2]]
(dc/db conn)
(dc/history (dc/db conn))
entity-id )
tx-rows->changes
(sort-by (comp :db/id first))
vec)
best-guess-entity (or (->> history
(group-by
(comp
namespace
second)
)
(map (fn [[k v]]
[k v]))
(sort-by second)
last
first)
"?")]
(if (get (:headers request) "hx-request")
(html-response
(table entity-id best-guess-entity history))
(base-page request (page-template :table (table entity-id best-guess-entity history)
:entity-id entity-id)
(admin-side-bar :admin-history))))
(catch NumberFormatException _
(html-response
[:div.notification.is-danger.is-light
"Cannot parse the entity-id " (or (:entity-id form-params)
(:entity-id params))
". It should be a number."]))))
(defn inspect [{{:keys [entity-id]} :params :as request}]
(alog/info ::inspect
@@ -167,34 +66,126 @@
(try
(let [entity-id (Long/parseLong entity-id)
data (dc/pull (dc/db conn)
'[*]
entity-id)]
'[*]
entity-id)]
(html-response
[:div.box {:style {:position "sticky"
:display "inline-block"
:vertical-align "top"
:overflow-y "auto"
:max-height "100vh"
:top "0px"
:bottom "0px"}}
[:div {:style {:display "inline-block"}}
[:h1.title "Snapshot of "
entity-id]
[:ul
(for [[k v] data]
[:li [:strong k] ":" (format-value v)]
)]]]))
(html-response
[:section.py-3.sm:py-5.max-w-lg
(com/card {:class "p-2"}
[:div {:style {:display "inline-block"}}
[:h1.title "Snapshot of "
entity-id]
[:ul
(for [[k v] data]
[:li [:strong k] ":" (format-value v)])]])]))
(catch NumberFormatException _
(html-response
[:div.notification.is-danger.is-light
"Cannot parse the entity-id " entity-id ". It should be a number."]))))
(defn history [{:keys [matched-route] :as request}]
(base-page request
(page-template )
(admin-side-bar matched-route)))
(html-response
[:div.notification.is-danger.is-light
"Cannot parse the entity-id " entity-id ". It should be a number."]))))
(defn result-table [{:keys [entity-id]}]
(try
(let [history (->>
(dc/q '[:find ?a2 ?v (pull ?tx [:db/txInstant :audit/user :db/id]) ?ad
:in $ $$ ?i
:where
[$$ ?i ?a ?v ?tx ?ad]
[$ ?a :db/ident ?a2]]
(dc/db conn)
(dc/history (dc/db conn))
entity-id)
tx-rows->changes
(sort-by (comp :db/id first))
vec)
best-guess-entity (or (->> history
(group-by
(comp
namespace
second))
(map (fn [[k v]]
[k v]))
(sort-by second)
last
first)
"?")]
(com/data-grid-card {:id "history-table"
:title (format "History for %s: %d" (str/capitalize best-guess-entity) entity-id)
:route :history-table
:start 0
:per-page (count history)
:total (count history)
:subtitle nil
:action-buttons nil
:rows (for [[tx a c] history]
(com/data-grid-row
{}
(com/data-grid-cell {} [:div [:div (some-> (:db/txInstant tx)
coerce/to-date-time
atime/localize
(atime/unparse atime/standard-time))]
[:div.tag (:db/id tx)]])
(com/data-grid-cell {} (str (:audit/user tx)))
(com/data-grid-cell {} (namespace a) ": " (name a))
(com/data-grid-cell {}
(com/pill {:color :red}
(format-value (:removed c))))
(com/data-grid-cell {}
[:div.tag.is-primary.is-light
[:span
(format-value (:added c))]])))
:headers
[(com/data-grid-header {}
"Date")
(com/data-grid-header {}
"User")
(com/data-grid-header {}
"Field")
(com/data-grid-header {}
"From")
(com/data-grid-header {}
"To")]}))
(catch NumberFormatException e
(throw e))))
(defn search-box [{:keys [entity-id]}]
[:div.mt-4
[:form.flex.gap-2 {"hx-target" "#history-table"
"hx-get" (bidi/path-for ssr-routes/only-routes
: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"}})
(com/button {:color :primary}
"DIG")]])
(defn history [{:keys [matched-route route-params query-params] :as request}]
(let [entity-id (or (some-> query-params (get "entity-id") Long/parseLong)
(some-> route-params (get :entity-id) Long/parseLong))]
(base-page request
(com/page {:nav (com/company-aside-nav)
:active-client (:client (:session request))
:identity (:identity request)
:app-params {:hx-get (bidi/path-for ssr-routes/only-routes
:admin-history)
:hx-trigger "clientSelected from:body"
:hx-select "#app-contents"
:hx-swap "outerHTML swap:300ms"}}
(com/breadcrumbs {}
[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
"Admin"]
[:a {:href (bidi/path-for ssr-routes/only-routes
:admin-history)}
"History"])
(search-box {:entity-id entity-id})
[:div.flex.gap-4.flex-col.lg:flex-row
(if entity-id
(result-table {:entity-id entity-id})
[:div#history-table])
[:div#inspector]
])
nil)))

View File

@@ -142,6 +142,7 @@
:vendor-id (:db/id (second e)))
"?"
(url/map->query {:client-id (:db/id (first e))}))
:hx-ext "debug"
:hx-target "#modal-holder"
:hx-swap "outerHTML"}
svg/pencil)])
@@ -183,7 +184,7 @@
{:key "address"
:name "Address"
:sort-key "address"
:show-starting "lg"
:show-starting "lg"
:render (fn [[_ vendor]]
(if (-> vendor :vendor/address :address/street1)
[:div

View File

@@ -26,6 +26,7 @@
(def left-aside aside/left-aside-)
(def company-aside-nav aside/company-aside-nav-)
(def main-aside-nav aside/main-aside-nav-)
(def content-card card/content-card-)
(def card card/card-)
@@ -42,9 +43,8 @@
(def data-grid-cell data-grid/cell-)
(def data-grid-right-stack-cell data-grid/right-stack-cell-)
(defn link [{:keys [class href]} & children]
(into [:a {:href href
:class (str "font-medium text-blue-600 dark:text-blue-500 hover:underline " class)}]
(defn link [params & children]
(into [:a (update params :class str " font-medium text-blue-600 dark:text-blue-500 hover:underline ")]
children))

View File

@@ -30,7 +30,7 @@
[:ul {:id (:id params) :class "hidden py-2 space-y-2"}
(for [c children]
[:li
(update-in c [1 :class ] str " flex items-center p-2 pl-11 w-full text-base font-normal text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")])])
(update-in c [1 1 :class ] str " flex items-center p-2 pl-11 w-full text-base font-normal text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")])])
(defn left-aside- [{:keys [nav page-specific]} & children]
[:aside {:id "left-nav", :class "fixed top-0 left-0 pt-16 z-20 w-64 h-screen transition-transform -translate-x-full lg:translate-x-0", :aria-labelledby "left-nav" :aria-hidden "true"}
@@ -140,7 +140,7 @@
}
};
var collapse = new Collapse($targetEl, $triggerEl, options);
// var collapse = new Collapse($targetEl, $triggerEl, options);
")]])

View File

@@ -1,7 +1,7 @@
(ns auto-ap.ssr.components.card)
(defn card- [params & children]
(into [:div {:class "shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white overflow-hidden"}]
(into [:div (update params :class str " shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white overflow-hidden")]
children))
(defn content-card- [params & children]

View File

@@ -46,9 +46,13 @@
[:tbody]
rest)])
;; needed for tailwind
;; lg:table-cell md:table-cell
(defn data-grid-card- [{:keys [id
route
title
paginate?
action-buttons
total
subtitle
@@ -60,37 +64,36 @@
rows] :as params}]
[:div {:hx-get (bidi/path-for ssr-routes/only-routes
route
:request-method :get)
:request-method :get)
:hx-trigger "clientSelected from:body"
:hx-swap "outerHTML swap:300ms"
:id id}
(content-card-
{}
[:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
[:div
[:h1.text-2xl.mb-3.font-bold title]
[:div {:class "flex items-center flex-1 space-x-4"}
[:h5
(when subtitle
[:span subtitle])]]]
(into [:div {:class "flex flex-col flex-shrink-0 space-y-3 md:flex-row md:items-center lg:justify-end md:space-y-0 md:space-x-3"}
]
action-buttons)]
[:div {:class "overflow-x-auto"}
(data-grid- {:headers headers
:thead-params thead-params
}
rows
{}
[:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
[:div
[:h1.text-2xl.mb-3.font-bold title]
[:div {:class "flex items-center flex-1 space-x-4"}
[:h5
(when subtitle
[:span subtitle])]]]
(into [:div {:class "flex flex-col flex-shrink-0 space-y-3 md:flex-row md:items-center lg:justify-end md:space-y-0 md:space-x-3"}]
action-buttons)]
[:div {:class "overflow-x-auto"}
(data-grid- {:headers headers
:thead-params thead-params}
rows)]
)]
(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
route
:request-method :get)
"?start=" (* page per-page))
:hx-target (str "#" id)
:hx-swap "outerHTML show:#app:top"})}))])
(when (or paginate?
(not (nil? paginate?)))
(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
route
:request-method :get)
"?start=" (* page per-page))
:hx-target (str "#" id)
:hx-swap "outerHTML show:#app:top"})})))])

View File

@@ -9,7 +9,7 @@
[:div#app
(navbar- {:client active-client
:identity identity})
[:div#app-contents.flex.pt-16.overflow-hidden app-params
[:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params :hx-disinherit "*")
(left-aside- {:nav nav
:page-specific page-specific})
[:div#main-content {:class "relative w-full h-full lg:pl-64 overflow-y-auto px-4 bg-gray-100 dark:bg-gray-900 min-h-content "

View File

@@ -2,17 +2,19 @@
(defn pill- [params & children]
(into
[:span (cond-> params
true (update :class str " text-xs font-medium px-2 py-0.5 rounded whitespace-nowrap")
(into
[:span (cond-> params
true (update :class str " text-xs font-medium px-2 py-0.5 rounded whitespace-nowrap")
(= :primary (:color params))
(update :class str " bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300 ")
(= :primary (:color params))
(update :class str " bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300 ")
(= :secondary (:color params))
(update :class str " bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300 ")
(= :secondary (:color params))
(update :class str " bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300 ")
(= :yellow (:color params))
(update :class str " bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300")
)]
children))
(= :yellow (:color params))
(update :class str " bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300")
(= :red (:color params))
(update :class str " bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300"))]
children))

View File

@@ -13,7 +13,7 @@
[: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()")}
[: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"}]]]
[: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"}
[:div {:class "px-4 py-3", :role "none"}
[:p {:class "text-sm text-gray-900 dark:text-white", :role "none"} (:user/name identity)]

View File

@@ -12,53 +12,30 @@
hiccup))})
(defn base-page [request contents side-bar-contents]
(html-page
[:html.has-navbar-fixed-top
[:head
[:meta {:charset "utf-8"}]
[:meta {:http-equiv "X-UA-Compatible", :content "IE=edge"}]
[:meta {:name "viewport", :content "width=device-width, initial-scale=1"}]
[:title "Integreat"]
[:link {:href "/css/font.min.css", :rel "stylesheet"}]
[:link {:rel "stylesheet", :href "/css/react-datepicker.min.inc.css"}]
[:link {:rel "stylesheet", :href "/output.css"}]
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
[:script {:src "https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js"}]
#_[:script {:src "https://unpkg.com/htmx.org@1.8.4"
:integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
: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.9.3/dist/min/dropzone.min.js"}]
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
[:body {:hx-ext "disable-submit"
}
contents
[:script {:src "/js/flowbite.min.js"}]
[:script {:lang "text/javascript"}
(hiccup/raw "
var $targetEl = document.getElementById('left-nav');
(html-page
[:html.has-navbar-fixed-top
[:head
[:meta {:charset "utf-8"}]
[:meta {:http-equiv "X-UA-Compatible", :content "IE=edge"}]
[:meta {:name "viewport", :content "width=device-width, initial-scale=1"}]
[:title "Integreat"]
[:link {:href "/css/font.min.css", :rel "stylesheet"}]
[:link {:rel "stylesheet", :href "/css/react-datepicker.min.inc.css"}]
[:link {:rel "stylesheet", :href "/output.css"}]
var $triggerEl = document.getElementById('left-nav-toggle');
var options = {
onCollapse: () => {
document.getElementById('main-content').classList.remove('lg:pl-64')
},
onExpand: () => {
document.getElementById('main-content').classList.add('lg:pl-64')
},
onToggle: () => {
}
};
var collapse = new Collapse($targetEl, $triggerEl, options);
"
)]]]))
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
[:script {:src "https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js"}]
#_[:script {:src "https://unpkg.com/htmx.org@1.8.4"
:integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
:crossorigin= "anonymous"}]
[:script {:src "https://unpkg.com/htmx.org@1.9.0/dist/htmx.js"
:crossorigin= "anonymous"}]
[: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"}]]
[: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.9.3/dist/min/dropzone.min.js"}]
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
[:body {:hx-ext "disable-submit"}
contents
[:script {:src "/js/flowbite.min.js"}]]]))

View File

@@ -5,7 +5,7 @@
"admin" {"/history" {"" :admin-history
"/" :admin-history
#"/search/?" :admin-history-search
["/" [#"\d+" :entity-id] #"/?"] :admin-history-search
["/" [#"\d+" :entity-id] #"/?"] :admin-history
["/inspect/" [#"\d+" :entity-id] #"/?"] :admin-history-inspect}
"/ezcater-xls" :admin-ezcater-xls}
"transaction" {"/insights" {"" :transaction-insights

View File

@@ -1,7 +1,7 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: "class",
content: ["./src/**/*.{cljs,clj}",
content: ["./src/**/*.{cljs,clj,cljc}",
"./node_modules/flowbite/**/*.js"],
theme: {
extend: {