This commit is contained in:
Bryce Covert
2023-01-11 11:01:48 -08:00
parent 7cec382c52
commit 2facb0c64f
2 changed files with 300 additions and 0 deletions

View File

@@ -0,0 +1,260 @@
(ns auto-ap.ssr.admin
(:require
[auto-ap.logging :as alog]
[clojure.string :as str]
[clojure.tools.logging :as log]
#_{:clj-kondo/ignore [:refer-all]}
[compojure.core :refer [defroutes GET POST context ANY wrap-routes]]
[compojure.route :as route]
[config.core :refer [env]]
[mount.core :as mount]
[ring.middleware.edn :refer [wrap-edn-params]]
[ring.middleware.multipart-params :as mp]
[ring.middleware.params :refer [wrap-params]]
[ring.middleware.reload :refer [wrap-reload]]
[ring.util.response :as response]
[datomic.api :as d]
[auto-ap.datomic :refer [conn]]
[clj-time.coerce :as coerce]
[auto-ap.time :as atime]
[hiccup.core :refer [html]]
[hiccup.page :refer [html5]]
[unilog.context :as lc]))
(defn base-page [contents]
[: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 {:rel "stylesheet", :href "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css", :integrity "sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=", :crossorigin "anonymous"}]
[:link {:href "/css/font.min.css", :rel "stylesheet"}]
[:link {:rel "stylesheet", :href "/css/bulma.min.css"}]
[:link {:rel "stylesheet", :href "/css/bulma-calendar.min.css"}]
[:link {:rel "stylesheet", :href "/css/bulma-badge.min.css"}]
[:link {:rel "stylesheet", :href "/css/react-datepicker.min.inc.css"}]
[:link {:rel "stylesheet", :href "/css/animate.css"}]
[:link {:rel "stylesheet", :href "/finance-font/style.css"}]
[:link {:rel "stylesheet", :href "/css/main.css"}]
[:link {:rel "stylesheet", :href "https://unpkg.com/placeholder-loading/dist/css/placeholder-loading.min.css"}]
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7"}]
[:script {:src "https://unpkg.com/htmx.org@1.8.4"
:integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
:crossorigin="anonymous"}]
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async" }]]
[:body
[:div {:id "app"}
[:div
[:nav {:class "navbar has-shadow is-fixed-top"}
[:div {:class "container"}
[:div {:class "navbar-brand"}
[:a {:class "navbar-item", :href "../"}
[:img {:src "/img/logo.png"}]]]
[:div {:class "navbar-menu"}
[:div {:class "navbar-burger burger", :data-target "navMenu"}
[:span]
[:span]
[:span]]]]]
[:div {:class "columns has-shadow", :id "mail-app", :style "margin-bottom: 0px; height: calc(100vh - 46px);"}
[:aside {:class "column aside menu is-2 "}
[:div {:class "main left-nav"}
[:div]]]
[:div {:class "column messages hero ", :id "message-feed", :style "overflow: auto;"}
(into [:div {:class "inbox-messages"}]
contents)]]
[:div]
[:div {:id "dz-hidden"}]]]]])
(defn wrap-html [handler]
(fn [request]
(doto
{:status 200
:headers {"Content-Type" "text/html"}
:body (handler request)
}
println)))
(defn inline-add-deletes [history]
(->> history
(group-by (fn [[a _ t]]
[a t]))
(map (fn [[[a t] changes]]
(let [changes (-> (reduce
(fn [acc [_ v _ added]]
(if added
(assoc acc :added v)
(assoc acc :removed v)))
{}
changes))]
[t a changes])))))
(defn format-value [v]
(cond (inst? v)
(-> v
coerce/to-date-time
atime/localize
(atime/unparse atime/normal-date))
(nil? v)
[:em "(none)"]
(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"}
"snapshot"] "]"
]
:else
(pr-str v)))
(comment "_" )
(defn page-template [& {:keys [table entity-id]}]
[:div
[:div.columns
[:div.column.is-4
[:form.hello {"hx-target" "#history-table"
"hx-post" "/admin/history/search"
"hx-swap" "innerHTML"
"_" (hiccup2.core/raw "on submit 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" }]]
[:p.control
[:button#dig.button.is-primary {}
"Dig"]]]]]]
[:div#history-table
table]])
(defn history-search [{:keys [form-params params] :as request}]
(log/info ::request
request)
(try
(let [entity-id (Long/parseLong (or (some-> (:entity-id form-params) not-empty)
(:entity-id params)))
history (->>
(d/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]]
(d/db conn)
(d/history (d/db conn))
entity-id )
inline-add-deletes
(sort-by (comp :db/txInstant :tx))
vec)
best-guess-entity (->> history
(group-by
(comp
namespace
second)
)
(map (fn [[k v]]
[k v]))
(sort-by second)
last
first)
table [: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: 12em"} "Transaction" ]
[:td {:style "width: 12em"} "Date"]
[:td {:style "width: 12em"} "User"]
[:td {:style "width: 15em"} "Field"]
[:td "Change"]]]
[:tbody
(for [[tx a c] history]
[:tr
[:td (:db/id tx)]
[:td (-> (:db/txInstant tx)
coerce/to-date-time
atime/localize
(atime/unparse atime/standard-time))]
[:td (str (:audit/user tx))]
[:td (namespace a) ": " (name a)]
[:td (format-value (:removed c))
" => "
(format-value (:added c))]])]
]]
[:div.column.is-3
[:div#inspector.card]]]]]
(alog/info ::trace
:bge best-guess-entity
:headers (:headers request))
(html (if (= "history-table"
(get (:headers request) "hx-target"))
table
(do
(println "WHOLE PAGOE")
(page-template :table table
:entity-id entity-id)))))
(catch NumberFormatException e
(html [: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
:request request)
(try
(let [entity-id (Long/parseLong entity-id)
data (d/pull (d/db conn)
'[*]
entity-id
) ]
(html [:div.box [:h1.title "Snapshot of "
entity-id]
[:ul
(for [[k v] data]
[:li [:strong k] ":" v]
)]]))
(catch NumberFormatException e
(html [:div.notification.is-danger.is-light
"Cannot parse the entity-id " entity-id ". It should be a number."]))))
(defn history [request]
(str "<!DOCTYPE html>"
(html
(base-page (page-template )))))
(defn- with-ignore-trailing-slash [handler]
(fn [request]
(let [uri (request :uri)
clean-uri (str/replace uri #"^(.+?)/+$" "$1")]
(handler (assoc request :uri clean-uri)))))
(defroutes admin-routes
(wrap-routes
(context "/admin" []
(GET "/history" [] history)
(GET "/history/" [] history)
(POST "/history/search" [] history-search)
#_(GET "/history/:entity-id" [entity-id] history-search)
#_(GET "/history/inspect/:entity-id" [entity-id] inspect))
with-ignore-trailing-slash))

View File

@@ -0,0 +1,40 @@
(ns auto-ap.views.pages.admin.history
(:require
[auto-ap.status :as status]
[auto-ap.subs :as subs]
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
[auto-ap.views.components.layouts :refer [side-bar-layout]]
[auto-ap.views.pages.admin.jobs.table :as table]
[auto-ap.views.components.modal :as modal]
[auto-ap.views.components :as com]
[auto-ap.views.pages.data-page :as data-page]
[auto-ap.views.utils :refer [dispatch-event with-user]]
[clojure.set :as set]
[re-frame.core :as re-frame]
[vimsical.re-frame.fx.track :as track]
[auto-ap.forms.builder :as form-builder]
[vimsical.re-frame.cofx.inject :as inject]
[auto-ap.forms :as forms]
[clojure.string :as str]
["htmx.org" :as htmx]
))
;; VIEWS
(def history-content
(let [c (atom nil)]
(with-meta
(fn []
(println "bothered?")
[:div {"hx-get" (.-pathname (.-location js/document))
"hx-trigger" "load"
"hx-swap" "outerHTML"
:ref (fn [i] (reset! c i))}
"test"])
{:should-component-update (fn [] false)
:component-did-mount (fn []
(.process htmx @c))})))
(defn history-page []
[side-bar-layout {:side-bar [admin-side-bar {}]
:main [history-content]}])