Another admin page

This commit is contained in:
2023-10-31 12:44:10 -07:00
parent f61aca26cd
commit 7796e34834
11 changed files with 238 additions and 41 deletions

View File

@@ -2,7 +2,6 @@
(:require
[amazonica.aws.ecs :as ecs]
[auto-ap.logging :as alog]
[clojure.string :as str]
[auto-ap.routes.utils
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
[auto-ap.ssr-routes :as ssr-routes]
@@ -22,9 +21,9 @@
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
[clj-time.core :as time]
[clojure.string :as str]
[config.core :refer [env]]
[malli.core :as mc]
[auto-ap.ssr.hx :as hx])
[malli.core :as mc])
(:import
(com.amazonaws.services.ecs.model AssignPublicIp)))

View File

@@ -0,0 +1,188 @@
(ns auto-ap.ssr.admin.import-batch
(:require
[auto-ap.datomic
:refer [add-sorter-fields
apply-pagination
apply-sort-3
conn
merge-query
pull-many
query2]]
[auto-ap.routes.admin.import-batch :as route]
[auto-ap.routes.utils
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.components.date-range :refer [date-range-field]]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers ref->select-options]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
[datomic.api :as dc]
[clj-time.coerce :as c]
[auto-ap.logging :as alog]
[hiccup.util :as hu]
[auto-ap.client-routes :as client-routes]
[auto-ap.ssr.svg :as svg]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
::route/table)
"hx-target" "#entity-table"
"hx-indicator" "#entity-table"}
[:fieldset.space-y-6
(date-range-field {:value {:start (:start-date (:parsed-query-params request))
:end (:end-date (:parsed-query-params request))}
:id "date-range"})
(com/field {:label "Source"}
(com/select {:name "source"
:class "hot-filter w-full"
:value (:source (:parsed-query-params request))
:placeholder ""
:options (ref->select-options "import-source" :allow-nil? true)}))
#_(com/field {:label "Code"}
(com/text-input {:name "code"
:id "code"
:class "hot-filter"
:value (:code (:parsed-query-params request))
:placeholder "11101"
:size :small}))]])
(def default-read '[:db/id
[:import-batch/date :xform clj-time.coerce/from-date]
:import-batch/suppressed
:import-batch/extant
:import-batch/user-name
:import-batch/imported
{[:import-batch/source :xform iol-ion.query/ident] [:db/ident]
[:import-batch/status :xform iol-ion.query/ident] [:db/ident]}])
(defn fetch-ids [db request]
(let [query-params (:parsed-query-params request)
query (cond-> {:query {:find []
:in '[$ ]
:where '[]}
:args [db ]}
(:sort query-params) (add-sorter-fields {"source" ['[?e :import-batch/source ?s]
'[?s :db/ident ?s2]
'[(name ?s2) ?sort-source]]
"status" ['[?e :import-batch/status ?st]
'[?st :db/ident ?st2]
'[(name ?st2) ?sort-status]]
"user" ['[?e :import-batch/user-name ?sort-user]]
"date" ['[?e :import-batch/date ?sort-date]]
"type" ['[?e :account/type ?t]
'[?t :db/ident ?ti]
'[(name ?ti) ?sort-type]]}
query-params)
(or (:start-date query-params)
(:end-date query-params))
(merge-query {:query '{:where [[?e :import-batch/date ?d]]}})
(:start-date query-params)
(merge-query {:query '{:in [?start-date]
:where [[(>= ?d ?start-date)]]}
:args [(-> query-params :start-date c/to-date)]})
(:end-date query-params)
(merge-query {:query '{:in [?end-date]
:where [[(< ?d ?end-date)]]}
:args [(-> query-params :end-date c/to-date)]})
(not-empty (:source query-params))
(merge-query {:query '{:in [?source]
:where [[?e :import-batch/source ?source]]}
:args [(keyword "import-source" (:source query-params))]})
true
(merge-query {:query {:find ['?sort-default '?e]
:where ['[?e :import-batch/date ?sort-default]]}}))]
(cond->> (query2 query)
true (apply-sort-3 query-params)
true (apply-pagination query-params))))
(defn hydrate-results [ids db _]
(let [results (->> (pull-many db default-read ids)
(group-by :db/id))
refunds (->> ids
(map results)
(map first))]
refunds))
(defn fetch-page [request]
(let [db (dc/db conn)
{ids-to-retrieve :ids matching-count :count} (fetch-ids db request)]
[(->> (hydrate-results ids-to-retrieve db request))
matching-count]))
(def grid-page
(helper/build {:id "entity-table"
:id-fn :db/id
:nav (com/admin-aside-nav)
:fetch-page fetch-page
:page-specific-nav filters
:row-buttons (fn [_ entity]
[(com/a-icon-button {:href (hu/url (bidi/path-for client-routes/routes :transactions)
{:import-batch-id (:db/id entity)})
:hx-boost true}
svg/external-link)])
:oob-render
(fn [request]
[(assoc-in (date-range-field {:value {:start (:start-date (:parsed-query-params request))
:end (:end-date (:parsed-query-params request))}
:id "date-range"}) [1 :hx-swap-oob] true)])
:parse-query-params (comp
(helper/default-parse-query-params grid-page))
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
"Admin"]
[:a {:href (bidi/path-for ssr-routes/only-routes
::route/page)}
"Import Batches"]]
:title "Import Batches"
:entity-name "Batch"
:route ::route/table
:headers [{:key "date"
:name "Date"
:sort-key "date"
:render #(some-> % :import-batch/date (atime/unparse-local atime/standard-time))}
{:key "source"
:name "Source"
:sort-key "source"
:render :import-batch/source}
{:key "status"
:name "Status"
:sort-key "status"
:render #(some-> % :import-batch/status name)}
{:key "user"
:name "User"
:sort-key "user"
:render :import-batch/user-name}
{:key "imported"
:name "imported"
:render :import-batch/imported}
{:key "extant"
:name "Pre-existing"
:render :import-batch/extant}
{:key "suppresed"
:name "Suppressed"
:render :import-batch/suppressed}]}))
(def row* (partial helper/row* grid-page))
(def table* (partial helper/table* grid-page))
(def key->handler
(apply-middleware-to-all-handlers
(->>
{::route/page (helper/page-route grid-page)
::route/table (helper/table-route grid-page)})
(fn [h]
(-> h
(wrap-admin)
(wrap-client-redirect-unauthenticated)))))

View File

@@ -6,7 +6,8 @@
[auto-ap.client-routes :as client-routes]
[auto-ap.ssr.hx :as hx]
[auto-ap.routes.admin.transaction-rules :as transaction-rules]
[auto-ap.ssr.hiccup-helper :as hh]))
[auto-ap.ssr.hiccup-helper :as hh]
[auto-ap.routes.admin.import-batch :as ib-routes]))
(defn menu-button- [params & children]
[:div
@@ -242,8 +243,8 @@
{:x-show "open"})
(menu-button- {:href (bidi/path-for client-routes/routes
:admin-excel-import)} "Excel Invoices")
(menu-button- {:href (bidi/path-for client-routes/routes
:admin-import-batches)} "Import Batches")
(menu-button- {:href (bidi/path-for ssr-routes/only-routes
::ib-routes/page)} "Import Batches")
(menu-button- {:href (bidi/path-for ssr-routes/only-routes
:admin-ezcater-xls)
:hx-boost "true"} "EZCater XLS Import"))]])

View File

@@ -0,0 +1,29 @@
(ns auto-ap.ssr.components.date-range
(:require [auto-ap.ssr.components :as com]
[auto-ap.time :as atime]))
(defn date-range-field [{:keys [value id] }]
[:div {:id id}
(com/field {:label "Date Range"}
[:div.space-y-4
[:div
(com/button-group {:name "date-range"}
(com/button-group-button {:size :small :value "all" :hx-trigger "click"} "All")
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))
]
[:div.flex.space-x-1.items-baseline.w-full.justify-start
(com/date-input {:name "start-date"
:value (some-> (:start value)
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small
:class "shrink"})
(com/date-input {:name "end-date"
:value (some-> (:end value)
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small
:class "shrink"})]])])

View File

@@ -155,7 +155,7 @@
(dissoc :size))])
(defn date-input- [{:keys [size] :as params}]
[:div
[:div.shrink
[:input
(-> params
(update :class (fnil hh/add-class "") default-input-classes)
@@ -163,7 +163,7 @@
(assoc "_" (hiccup/raw "init initDatepicker(me)"))
(assoc "hx-on" (hiccup/raw "changeDate: htmx.trigger(this, \"change\")
htmx:beforeCleanupElement: this.dp.destroy()"))
(update :class #(str % (use-size size)))
(update :class #(str % (use-size size) " w-full"))
(dissoc :size))]])

View File

@@ -11,6 +11,7 @@
[auto-ap.ssr.company.company-1099 :as company-1099]
[auto-ap.ssr.company.plaid :as company-plaid]
[auto-ap.ssr.admin.accounts :as admin-accounts]
[auto-ap.ssr.admin.import-batch :as import-batch]
[auto-ap.ssr.company.reports :as company-reports]
[auto-ap.ssr.company.yodlee :as company-yodlee]
[auto-ap.ssr.invoice.glimpse :as invoice-glimpse]
@@ -73,6 +74,7 @@
:admin-ezcater-xls (wrap-client-redirect-unauthenticated (wrap-admin ezcater-xls/page))
:search (wrap-client-redirect-unauthenticated (wrap-secure search/dialog-contents))}
(into company-1099/key->handler)
(into import-batch/key->handler)
(into pos-sales/key->handler)
(into pos-expected-deposits/key->handler)
(into pos-tenders/key->handler)

View File

@@ -3,34 +3,6 @@
[auto-ap.time :as atime]
[auto-ap.ssr.svg :as svg]))
(defn date-range-field* [request]
[:div#date-range {}
(com/field {:label "Date Range"}
[:div.space-y-4
[:div
(com/button-group {:name "date-range"}
(com/button-group-button {:size :small :value "all" :hx-trigger "click"} "All")
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))
]
[:div.flex.space-x-1.items-baseline
(com/date-input {:name "start-date"
:value (some-> request
:parsed-query-params
:start-date
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small})
(com/date-input {:name "end-date"
:value (some-> request
:parsed-query-params
:end-date
(atime/unparse-local atime/normal-date))
:placeholder "Date"
:size :small})]])])
(defn processor-field* [request]
(com/field {:label "Processor"}
(com/radio {:size :small

View File

@@ -11,7 +11,6 @@
[:id] {"" :admin-specific-client
"/bank-accounts/" {[:bank-account] :admin-specific-bank-account}}}
"rules" :admin-rules
"import-batches" :admin-import-batches
"vendors" :admin-vendors
"excel-import" :admin-excel-import
}

View File

@@ -0,0 +1,3 @@
(ns auto-ap.routes.admin.import-batch)
(def routes {"" {:get ::page}
"/table" ::table})

View File

@@ -3,7 +3,9 @@
[auto-ap.client-routes :as client-routes]
[auto-ap.ssr-routes :as ssr-routes]
#?(:cljs [re-frame.core :as re-frame])
#?(:cljs [reagent.core :as r])))
#?(:cljs [reagent.core :as r])
[auto-ap.routes.admin.import-batch :as ib-routes]
[auto-ap.routes.admin.transaction-rules :as tr-routes]))
(defn deep-merge [v & vs]
(letfn [(rec-merge [v1 v2]
@@ -62,7 +64,7 @@
:icon-style {:font-size "25px"}})
(menu-item {:label "Rules"
:icon-class "icon icon-cog-play-1"
:test-route #{:admin-transaction-rules}
:test-route #{::tr-routes/page}
:active-route active-route
:route :admin-transaction-rules
:icon-style {:font-size "25px"}})
@@ -88,7 +90,7 @@
:icon-class "fa fa-download"
:test-route #{:admin-import-batches}
:active-route active-route
:route :admin-import-batches})
:route ::ib-routes/page})
(menu-item {:label "EZCater XLS Import"
:icon-class "icon icon-cog-play-1"
:test-route #{:admin-ezcater-xls}

View File

@@ -1,5 +1,6 @@
(ns auto-ap.ssr-routes
(:require [auto-ap.routes.admin.transaction-rules :as tr-routes]))
(:require [auto-ap.routes.admin.transaction-rules :as tr-routes]
[auto-ap.routes.admin.import-batch :as ib-routes]))
(def routes {"impersonate" :impersonate
"logout" :logout
@@ -34,6 +35,7 @@
"/new" {:get :admin-job-start-dialog}
"/subform" :admin-job-subform}
"/ezcater-xls" :admin-ezcater-xls
"/import-batch" ib-routes/routes
"/transaction-rule" tr-routes/routes}
"transaction" {"/insights" {"" :transaction-insights
"/table" :transaction-insight-table