test
This commit is contained in:
260
src/clj/auto_ap/ssr/admin.clj
Normal file
260
src/clj/auto_ap/ssr/admin.clj
Normal 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))
|
||||
40
src/cljs/auto_ap/views/pages/admin/history.cljs
Normal file
40
src/cljs/auto_ap/views/pages/admin/history.cljs
Normal 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]}])
|
||||
|
||||
Reference in New Issue
Block a user