Implements the ability to dig into history
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"downshift": "^6.1.3",
|
||||
"dropzone": "^4.3.0",
|
||||
"htmx.org": "^1.8.4",
|
||||
"minisearch": "^3.0.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.1",
|
||||
|
||||
@@ -1,27 +1,17 @@
|
||||
(ns auto-ap.ssr.admin
|
||||
(:require
|
||||
[auto-ap.datomic :refer [conn]]
|
||||
[auto-ap.graphql.utils :refer [assert-admin]]
|
||||
[auto-ap.logging :as alog]
|
||||
[auto-ap.time :as atime]
|
||||
[clj-time.coerce :as coerce]
|
||||
[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]
|
||||
[compojure.core :refer [context defroutes GET POST routes]]
|
||||
[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]))
|
||||
[hiccup2.core :as hiccup]))
|
||||
|
||||
(defn base-page [contents]
|
||||
(defn base-page [request contents]
|
||||
[:html.has-navbar-fixed-top
|
||||
[:head
|
||||
[:meta {:charset "utf-8"}]
|
||||
@@ -43,37 +33,57 @@
|
||||
:integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
|
||||
:crossorigin="anonymous"}]
|
||||
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async" }]]
|
||||
[:script {:type "text/javascript"}
|
||||
(hiccup/raw
|
||||
(str
|
||||
"
|
||||
window.onload = function () {
|
||||
document.body.addEventListener(\"htmx:configRequest\", function(event) {
|
||||
event.detail.headers[\"Authorization\"] = \"Token " (get (:query-params request) "jwt")" \" ;
|
||||
});
|
||||
}"))]
|
||||
|
||||
[:body
|
||||
[:div {:id "app"}
|
||||
[:div
|
||||
[:nav {:class "navbar has-shadow is-fixed-top"}
|
||||
[:nav {:class "navbar has-shadow is-fixed-top is-grey"}
|
||||
|
||||
[: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.navbar-menu {:id "navMenu"}
|
||||
[:div.navbar-start
|
||||
[:a.navbar-item {:href "/"}
|
||||
"Home" ]
|
||||
[:a.navbar-item {:href "/invoices/"}
|
||||
"Invoices" ]
|
||||
[:a.navbar-item {:href "/payments/"}
|
||||
"Payments" ]
|
||||
[:a.navbar-item {:href "/pos/sales-orders/"}
|
||||
"POS" ]
|
||||
[:a.navbar-item {:href "/transactions/"}
|
||||
"Transactions" ]
|
||||
|
||||
[:a.navbar-item {:href "/ledger/"}
|
||||
"Ledger" ]]]]]
|
||||
[: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 {:class "inbox-messages"}
|
||||
contents]]]
|
||||
[:div]
|
||||
[:div {:id "dz-hidden"}]]]]])
|
||||
|
||||
(defn wrap-html [handler]
|
||||
(fn [request]
|
||||
(doto
|
||||
(defn html-response [hiccup]
|
||||
{:status 200
|
||||
:headers {"Content-Type" "text/html"}
|
||||
:body (handler request)
|
||||
}
|
||||
println)))
|
||||
:body (str
|
||||
(hiccup/html
|
||||
{}
|
||||
hiccup))})
|
||||
|
||||
|
||||
(defn inline-add-deletes [history]
|
||||
@@ -121,6 +131,7 @@
|
||||
(pr-str v)))
|
||||
|
||||
(comment "_" )
|
||||
|
||||
(defn page-template [& {:keys [table entity-id]}]
|
||||
[:div
|
||||
[:div.columns
|
||||
@@ -128,19 +139,21 @@
|
||||
[: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
|
||||
"_" (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" }]]
|
||||
[: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 history-search [{:keys [form-params params] :as request}]
|
||||
(defn history-search [{:keys [form-params params] identity :identity :as request}]
|
||||
|
||||
(assert-admin identity)
|
||||
(log/info ::request
|
||||
request)
|
||||
(try
|
||||
@@ -158,7 +171,7 @@
|
||||
inline-add-deletes
|
||||
(sort-by (comp :db/txInstant :tx))
|
||||
vec)
|
||||
best-guess-entity (->> history
|
||||
best-guess-entity (or (->> history
|
||||
(group-by
|
||||
(comp
|
||||
namespace
|
||||
@@ -169,6 +182,7 @@
|
||||
(sort-by second)
|
||||
last
|
||||
first)
|
||||
"?")
|
||||
table [:div [:h1.title "History for "
|
||||
(str/capitalize best-guess-entity)
|
||||
" "
|
||||
@@ -181,7 +195,7 @@
|
||||
[:td {:style "width: 12em"} "Transaction" ]
|
||||
[:td {:style "width: 12em"} "Date"]
|
||||
[:td {:style "width: 12em"} "User"]
|
||||
[:td {:style "width: 15em"} "Field"]
|
||||
[:td {:style "width: 10em"} "Field"]
|
||||
[:td "Change"]]]
|
||||
[:tbody
|
||||
(for [[tx a c] history]
|
||||
@@ -193,9 +207,16 @@
|
||||
(atime/unparse atime/standard-time))]
|
||||
[:td (str (:audit/user tx))]
|
||||
[:td (namespace a) ": " (name a)]
|
||||
[:td (format-value (:removed c))
|
||||
" => "
|
||||
(format-value (:added c))]])]
|
||||
[:td
|
||||
[:div.tags
|
||||
[:div.tag.is-danger.is-light
|
||||
[:span
|
||||
"FROM "
|
||||
(format-value (:removed c))]]
|
||||
[:div.tag.is-primary.is-light
|
||||
[:span
|
||||
"TO "
|
||||
(format-value (:added c))]]]]])]
|
||||
]]
|
||||
[:div.column.is-3
|
||||
[:div#inspector.card]]]]]
|
||||
@@ -203,23 +224,24 @@
|
||||
(alog/info ::trace
|
||||
:bge best-guess-entity
|
||||
:headers (:headers request))
|
||||
(html (if (= "history-table"
|
||||
(get (:headers request) "hx-target"))
|
||||
(html-response
|
||||
(if (get (:headers request) "hx-request")
|
||||
table
|
||||
(do
|
||||
(println "WHOLE PAGOE")
|
||||
(base-page request
|
||||
(page-template :table table
|
||||
:entity-id entity-id)))))
|
||||
(catch NumberFormatException e
|
||||
(html [:div.notification.is-danger.is-light
|
||||
(html-response
|
||||
(str [:div.notification.is-danger.is-light
|
||||
"Cannot parse the entity-id " (or (:entity-id form-params)
|
||||
(:entity-id params))
|
||||
|
||||
". It should be a number."]))))
|
||||
". It should be a number."])))))
|
||||
|
||||
(defn inspect [{{:keys [entity-id]} :params :as request}]
|
||||
(defn inspect [{{:keys [entity-id]} :params identity :identity :as request}]
|
||||
(alog/info ::inspect
|
||||
:request request)
|
||||
(assert-admin identity)
|
||||
(try
|
||||
(let [entity-id (Long/parseLong entity-id)
|
||||
data (d/pull (d/db conn)
|
||||
@@ -227,34 +249,27 @@
|
||||
entity-id
|
||||
) ]
|
||||
|
||||
|
||||
(html [:div.box [:h1.title "Snapshot of "
|
||||
(html-response
|
||||
[: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
|
||||
(html-response
|
||||
[: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)))))
|
||||
(defn history [{:keys [identity] :as request}]
|
||||
(html-response
|
||||
(base-page request (page-template ))))
|
||||
|
||||
(defroutes admin-routes
|
||||
(wrap-routes
|
||||
(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))
|
||||
(GET "/history/:entity-id" [entity-id] history-search)
|
||||
(GET "/history/inspect/:entity-id" [entity-id] inspect))))
|
||||
|
||||
@@ -381,7 +381,7 @@
|
||||
|
||||
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
|
||||
(defn tx-detail [i]
|
||||
(map (juxt :e #(d/ident (d/db (d/connect uri)) (:a %)) :v)
|
||||
(map (juxt :e #(d/ident (d/db (d/connect uri)) (:a %)) :v :added?)
|
||||
(:data (first
|
||||
(d/tx-range (d/log (d/connect uri))
|
||||
i
|
||||
|
||||
@@ -27,13 +27,7 @@
|
||||
(defn ^:export init []
|
||||
(dev-setup)
|
||||
|
||||
(.addEventListener (.-body js/document)
|
||||
"htmx:configRequest"
|
||||
(fn [event]
|
||||
(aset (.-headers (.-detail event))
|
||||
"Authorization"
|
||||
(some->> (.getItem js/localStorage "jwt")
|
||||
(str "Token ")))))
|
||||
|
||||
|
||||
|
||||
;; document.body.addEventListener('htmx:configRequest', function(evt) {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
[:span {:class "icon icon-cog-play-1" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "Rules"]]]
|
||||
[:li.menu-item
|
||||
[:a {:href "/admin/history", :class (str "item" (active-when ap = :admin-history))}
|
||||
[:a {:href (str "/admin/history?jwt=" (.getItem js/localStorage "jwt")) :class (str "item" (active-when ap = :admin-history))}
|
||||
[:span {:class "icon icon-cog-play-1" :style {:font-size "25px"}}]
|
||||
[:span {:class "name"} "History"]]]
|
||||
[:ul ]]
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
[auto-ap.views.pages.error :refer [error-page]]
|
||||
[auto-ap.views.pages.ledger.balance-sheet :refer [balance-sheet-page]]
|
||||
[auto-ap.views.pages.admin.jobs :refer [jobs-page]]
|
||||
[auto-ap.views.pages.admin.history :refer [history-page]]
|
||||
[auto-ap.views.pages.ledger.external-import :refer [external-import-page]]
|
||||
[auto-ap.views.pages.ledger.external-ledger :refer [external-ledger-page]]
|
||||
[auto-ap.views.pages.ledger.profit-and-loss :refer [profit-and-loss-page]]
|
||||
@@ -155,9 +154,6 @@
|
||||
[admin-excel-import-page])
|
||||
|
||||
|
||||
(defmethod page :admin-history [_]
|
||||
[history-page])
|
||||
|
||||
(defmethod page :initial-error [_]
|
||||
[error-page])
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
(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