ccount modal
This commit is contained in:
@@ -29,8 +29,10 @@
|
|||||||
html-response
|
html-response
|
||||||
main-transformer
|
main-transformer
|
||||||
many-entity
|
many-entity
|
||||||
|
modal-response
|
||||||
ref->enum-schema
|
ref->enum-schema
|
||||||
ref->select-options
|
ref->select-options
|
||||||
|
strip
|
||||||
temp-id
|
temp-id
|
||||||
wrap-entity
|
wrap-entity
|
||||||
wrap-form-4xx-2
|
wrap-form-4xx-2
|
||||||
@@ -44,8 +46,8 @@
|
|||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-account-table)
|
:admin-account-table)
|
||||||
"hx-target" "#account-table"
|
"hx-target" "#entity-table"
|
||||||
"hx-indicator" "#account-table"}
|
"hx-indicator" "#entity-table"}
|
||||||
|
|
||||||
[:fieldset.space-y-6
|
[:fieldset.space-y-6
|
||||||
(com/field {:label "Name"}
|
(com/field {:label "Name"}
|
||||||
@@ -129,7 +131,7 @@
|
|||||||
matching-count]))
|
matching-count]))
|
||||||
|
|
||||||
(def grid-page
|
(def grid-page
|
||||||
(helper/build {:id "account-table"
|
(helper/build {:id "entity-table"
|
||||||
:nav (com/admin-aside-nav)
|
:nav (com/admin-aside-nav)
|
||||||
:page-specific-nav filters
|
:page-specific-nav filters
|
||||||
:fetch-page fetch-page
|
:fetch-page fetch-page
|
||||||
@@ -139,16 +141,12 @@
|
|||||||
:action-buttons (fn [_]
|
:action-buttons (fn [_]
|
||||||
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-account-new-dialog))
|
:admin-account-new-dialog))
|
||||||
:hx-target "#modal-content"
|
|
||||||
:hx-swap "innerHTML"
|
|
||||||
:color :primary}
|
:color :primary}
|
||||||
"New Account")])
|
"New Account")])
|
||||||
:row-buttons (fn [_ entity]
|
:row-buttons (fn [_ entity]
|
||||||
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-account-edit-dialog
|
:admin-account-edit-dialog
|
||||||
:db/id (:db/id entity)))
|
:db/id (:db/id entity)))}
|
||||||
:hx-target "#modal-content"
|
|
||||||
:hx-swap "innerHTML"}
|
|
||||||
svg/pencil)])
|
svg/pencil)])
|
||||||
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
||||||
:admin)}
|
:admin)}
|
||||||
@@ -181,31 +179,29 @@
|
|||||||
(def table* (partial helper/table* grid-page))
|
(def table* (partial helper/table* grid-page))
|
||||||
|
|
||||||
(defn account-save [{:keys [form-params request-method] :as request}]
|
(defn account-save [{:keys [form-params request-method] :as request}]
|
||||||
(let [entity (cond-> form-params
|
(let [entity (cond-> form-params
|
||||||
(= :post request-method) (assoc :db/id "new"))
|
(= :post request-method) (assoc :db/id "new"))
|
||||||
_ (cond (= :post request-method)
|
_ (cond (= :post request-method)
|
||||||
(when (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))
|
(when (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))
|
||||||
(field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
|
(field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
|
||||||
[:account/numeric-code]
|
[:account/numeric-code]
|
||||||
:form form-params))
|
:form form-params)))
|
||||||
)
|
_ (some->> form-params
|
||||||
_ (some->> form-params
|
:account/client-overrides
|
||||||
:account/client-overrides
|
(group-by :account-client-override/client)
|
||||||
(group-by :account-client-override/client)
|
(filter (fn [[_ overrides]]
|
||||||
(filter (fn [[_ overrides]]
|
(> (count overrides) 1)))
|
||||||
(> (count overrides) 1)))
|
(map first)
|
||||||
(map first)
|
seq
|
||||||
seq
|
(#(form-validation-error (format "Client(s) %s have more than one override."
|
||||||
(#(form-validation-error (format "Client(s) %s have more than one override."
|
(str/join ", "
|
||||||
(str/join ", "
|
(map (fn [client]
|
||||||
(map (fn [client]
|
(format "'%s'" (pull-attr (dc/db conn)
|
||||||
(format "'%s'" (pull-attr (dc/db conn)
|
:client/name
|
||||||
:client/name
|
(-> client)))
|
||||||
(-> client)))
|
) %)))
|
||||||
) %)))
|
:form form-params)) ;; TODO shouldnt need to bubble this through. See if we can eliminate the passing of form and last-form.
|
||||||
:form form-params))
|
)
|
||||||
|
|
||||||
)
|
|
||||||
{:keys [tempids]} (audit-transact [[:upsert-entity (cond-> entity
|
{:keys [tempids]} (audit-transact [[:upsert-entity (cond-> entity
|
||||||
(:account/numeric-code entity) (assoc :account/code (str (:account/numeric-code entity))))]]
|
(:account/numeric-code entity) (assoc :account/code (str (:account/numeric-code entity))))]]
|
||||||
(:identity request))
|
(:identity request))
|
||||||
@@ -231,8 +227,10 @@
|
|||||||
"account_client_override_id" (:db/id o)})))
|
"account_client_override_id" (:db/id o)})))
|
||||||
(html-response
|
(html-response
|
||||||
(row* identity updated-account {:flash? true})
|
(row* identity updated-account {:flash? true})
|
||||||
:headers {"hx-trigger" "modalclose"
|
:headers (cond-> {"hx-trigger" "modalclose"}
|
||||||
"hx-retarget" (format "#account-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
|
(= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
|
||||||
|
"hx-reswap" "afterbegin")
|
||||||
|
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-account)))))))
|
||||||
|
|
||||||
;; TODO decide when cursors are used. other cases it's not, some are
|
;; TODO decide when cursors are used. other cases it's not, some are
|
||||||
(defn client-override* [override]
|
(defn client-override* [override]
|
||||||
@@ -377,14 +375,14 @@
|
|||||||
:index (count (fc/field-value))
|
:index (count (fc/field-value))
|
||||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-account-client-override-new)}
|
:admin-account-client-override-new)}
|
||||||
"New override"))))
|
"New override"))))]
|
||||||
|
|
||||||
]
|
|
||||||
[:div
|
[:div
|
||||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||||
(com/validated-save-button {:errors (seq form-errors)}
|
(com/validated-save-button {:errors (seq form-errors)}
|
||||||
"Save account")])]])]))
|
"Save account")])]])]))
|
||||||
|
|
||||||
|
;; TODO saving new row should att it to the tbody
|
||||||
|
|
||||||
(defn new-client-override [{ {:keys [index]} :query-params}]
|
(defn new-client-override [{ {:keys [index]} :query-params}]
|
||||||
(html-response
|
(html-response
|
||||||
(fc/start-form-with-prefix
|
(fc/start-form-with-prefix
|
||||||
@@ -398,8 +396,8 @@
|
|||||||
[:map
|
[:map
|
||||||
[:db/id {:optional true} [:maybe entity-id]]
|
[:db/id {:optional true} [:maybe entity-id]]
|
||||||
[:account/numeric-code {:optional true} [:maybe :int]]
|
[:account/numeric-code {:optional true} [:maybe :int]]
|
||||||
[:account/name [:string {:min 1}]]
|
[:account/name [:string {:min 1 :decode/string strip}]]
|
||||||
[:account/location [:maybe :string]]
|
[:account/location {:optional true} [:maybe [:string {:decode/string strip}]]]
|
||||||
[:account/type (ref->enum-schema "account-type")]
|
[:account/type (ref->enum-schema "account-type")]
|
||||||
[:account/applicability (ref->enum-schema "account-applicability")] ;
|
[:account/applicability (ref->enum-schema "account-applicability")] ;
|
||||||
[:account/invoice-allowance (ref->enum-schema "allowance")]
|
[:account/invoice-allowance (ref->enum-schema "allowance")]
|
||||||
@@ -409,17 +407,16 @@
|
|||||||
(many-entity {}
|
(many-entity {}
|
||||||
[:db/id [:or entity-id temp-id]]
|
[:db/id [:or entity-id temp-id]]
|
||||||
[:account-client-override/client entity-id]
|
[:account-client-override/client entity-id]
|
||||||
[:account-client-override/name [:string {:min 2}]])]]]))
|
[:account-client-override/name [:string {:min 2 :decode/string strip}]])]]]))
|
||||||
|
|
||||||
(defn account-dialog [{:keys [entity form-params form-errors]}]
|
(defn account-dialog [{:keys [entity form-params form-errors]}]
|
||||||
(html-response (dialog* {:entity entity
|
(modal-response (dialog* {:entity entity
|
||||||
:form-params (or (when (seq form-params)
|
:form-params (or (when (seq form-params)
|
||||||
form-params)
|
form-params)
|
||||||
(when entity
|
(when entity
|
||||||
(mc/decode form-schema entity main-transformer))
|
(mc/decode form-schema entity main-transformer))
|
||||||
{})
|
{})
|
||||||
:form-errors form-errors})
|
:form-errors form-errors})))
|
||||||
:headers {"hx-trigger" "modalopen"}))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
html-response
|
html-response
|
||||||
main-transformer
|
main-transformer
|
||||||
many-entity
|
many-entity
|
||||||
|
modal-response
|
||||||
money
|
money
|
||||||
percentage
|
percentage
|
||||||
ref->enum-schema
|
ref->enum-schema
|
||||||
@@ -44,21 +45,14 @@
|
|||||||
[bidi.bidi :as bidi]
|
[bidi.bidi :as bidi]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[datomic.api :as dc]
|
[datomic.api :as dc]
|
||||||
[iol-ion.query :refer [ident]]
|
|
||||||
[malli.core :as mc]))
|
[malli.core :as mc]))
|
||||||
|
|
||||||
;; TODO with dependencies, I really don't like that you have to be ultra specific in what
|
|
||||||
;; you want to include, and generating the routes and interconnection is weird too.
|
|
||||||
;; I'm tempted to say to include a full snapshot of the form, and the indicator
|
|
||||||
;; as to which one to generate.
|
|
||||||
|
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-transaction-rule-table)
|
:admin-transaction-rule-table)
|
||||||
"hx-target" "#transaction-rule-table"
|
"hx-target" "#entity-table"
|
||||||
"hx-indicator" "#transaction-rule-table"}
|
"hx-indicator" "#entity-table"}
|
||||||
|
|
||||||
[:fieldset.space-y-6
|
[:fieldset.space-y-6
|
||||||
(com/field {:label "Vendor"}
|
(com/field {:label "Vendor"}
|
||||||
@@ -180,7 +174,7 @@
|
|||||||
matching-count]))
|
matching-count]))
|
||||||
|
|
||||||
(def grid-page
|
(def grid-page
|
||||||
(helper/build {:id "transaction-rule-table"
|
(helper/build {:id "entity-table"
|
||||||
:nav (com/admin-aside-nav)
|
:nav (com/admin-aside-nav)
|
||||||
:page-specific-nav filters
|
:page-specific-nav filters
|
||||||
:fetch-page fetch-page
|
:fetch-page fetch-page
|
||||||
@@ -190,16 +184,12 @@
|
|||||||
:action-buttons (fn [request]
|
:action-buttons (fn [request]
|
||||||
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-transaction-rule-new-dialog))
|
:admin-transaction-rule-new-dialog))
|
||||||
:hx-target "#modal-content"
|
|
||||||
:hx-swap "innerHTML"
|
|
||||||
:color :primary}
|
:color :primary}
|
||||||
"New Transaction Rule")])
|
"New Transaction Rule")])
|
||||||
:row-buttons (fn [request entity]
|
:row-buttons (fn [request entity]
|
||||||
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||||
:admin-transaction-rule-edit-dialog
|
:admin-transaction-rule-edit-dialog
|
||||||
:db/id (:db/id entity)))
|
:db/id (:db/id entity)))}
|
||||||
:hx-target "#modal-content"
|
|
||||||
:hx-swap "innerHTML"}
|
|
||||||
svg/pencil)])
|
svg/pencil)])
|
||||||
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
||||||
:admin)}
|
:admin)}
|
||||||
@@ -269,6 +259,7 @@
|
|||||||
bank-account-id))
|
bank-account-id))
|
||||||
|
|
||||||
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
|
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
|
||||||
|
(clojure.pprint/pprint form-params)
|
||||||
(let [entity (cond-> form-params
|
(let [entity (cond-> form-params
|
||||||
(= :post request-method) (assoc :db/id "new")
|
(= :post request-method) (assoc :db/id "new")
|
||||||
true (assoc :transaction-rule/note (entity->note form-params)))
|
true (assoc :transaction-rule/note (entity->note form-params)))
|
||||||
@@ -297,13 +288,15 @@
|
|||||||
|
|
||||||
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
|
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
|
||||||
(:identity request))
|
(:identity request))
|
||||||
updated-account (dc/pull (dc/db conn)
|
updated-rule (dc/pull (dc/db conn)
|
||||||
default-read
|
default-read
|
||||||
(or (get tempids (:db/id entity)) (:db/id entity)))]
|
(or (get tempids (:db/id entity)) (:db/id entity)))]
|
||||||
(html-response
|
(html-response
|
||||||
(row* identity updated-account {:flash? true})
|
(row* identity updated-rule {:flash? true})
|
||||||
:headers {"hx-trigger" "modalclose"
|
:headers (cond-> {"hx-trigger" "modalclose"}
|
||||||
"hx-retarget" (format "#transaction-rule-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
|
(= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
|
||||||
|
"hx-reswap" "afterbegin")
|
||||||
|
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule)))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -327,81 +320,84 @@
|
|||||||
[{:keys [name value client-id x-model]}]
|
[{:keys [name value client-id x-model]}]
|
||||||
[:div.flex.flex-col
|
[:div.flex.flex-col
|
||||||
(com/typeahead-2 {:name name
|
(com/typeahead-2 {:name name
|
||||||
:placeholder "Search..."
|
:placeholder "Search..."
|
||||||
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
|
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
|
||||||
:id name
|
:id name
|
||||||
:x-model x-model
|
:x-model x-model
|
||||||
:value value
|
:value value
|
||||||
:content-fn (fn [value]
|
:content-fn (fn [value]
|
||||||
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
|
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
|
||||||
client-id)))})])
|
client-id)))})])
|
||||||
|
|
||||||
;; TODO something is making the accountId not change the location for only existing ones?
|
|
||||||
(defn- transaction-rule-account-row*
|
(defn- transaction-rule-account-row*
|
||||||
[transaction-rule account]
|
[transaction-rule account]
|
||||||
(com/data-grid-row (-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
|
(com/data-grid-row
|
||||||
(fc/field-value (:transaction-rule-account/account account)))
|
(-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
|
||||||
:show (boolean (not (fc/field-value (:new? account))))})
|
(fc/field-value (:transaction-rule-account/account account)))
|
||||||
:data-key "show"
|
:show (boolean (not (fc/field-value (:new? account))))})
|
||||||
:x-ref "p"}
|
:data-key "show"
|
||||||
hx/alpine-mount-then-appear)
|
:x-ref "p"}
|
||||||
(let [account-name (fc/field-name (:transaction-rule-account/account account))]
|
hx/alpine-mount-then-appear)
|
||||||
(list
|
(let [account-name (fc/field-name (:transaction-rule-account/account account))]
|
||||||
|
(list
|
||||||
(fc/with-field :db/id
|
|
||||||
(com/hidden {:name (fc/field-name)
|
(fc/with-field :db/id
|
||||||
:value (fc/field-value)}))
|
(com/hidden {:name (fc/field-name)
|
||||||
(fc/with-field :transaction-rule-account/account
|
:value (fc/field-value)}))
|
||||||
(com/data-grid-cell
|
(fc/with-field :transaction-rule-account/account
|
||||||
{}
|
(com/data-grid-cell
|
||||||
(com/validated-field
|
{}
|
||||||
{:errors (fc/field-errors)}
|
(com/validated-field
|
||||||
[:div {:hx-trigger "changed"
|
{:errors (fc/field-errors)}
|
||||||
:hx-target "next div"
|
[:div {:hx-trigger "changed"
|
||||||
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
|
:hx-target "next div"
|
||||||
:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
|
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
|
||||||
:x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
|
:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
|
||||||
(account-typeahead* {:value (fc/field-value)
|
:x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
|
||||||
:client-id (:db/id (:transaction-rule/client transaction-rule))
|
(account-typeahead* {:value (fc/field-value)
|
||||||
:name (fc/field-name)
|
:client-id (:db/id (:transaction-rule/client transaction-rule))
|
||||||
:x-model "accountId"}))))
|
:name (fc/field-name)
|
||||||
(fc/with-field :transaction-rule-account/location
|
:x-model "accountId"}))))
|
||||||
(com/data-grid-cell
|
(fc/with-field :transaction-rule-account/location
|
||||||
{}
|
(com/data-grid-cell
|
||||||
(com/validated-field
|
{}
|
||||||
{:errors (fc/field-errors)
|
(com/validated-field
|
||||||
:x-data (hx/json {:location (fc/field-value)})}
|
{:errors (fc/field-errors)
|
||||||
[:div {:hx-trigger "changed"
|
:x-data (hx/json {:location (fc/field-value)})}
|
||||||
:hx-target "next *"
|
[:div {:hx-trigger "changed"
|
||||||
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
|
:hx-target "next *"
|
||||||
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
|
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
|
||||||
:x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data))"}]
|
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
|
||||||
(location-select* {:name (fc/field-name)
|
:x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data) )"}]
|
||||||
:account-location (:account/location (cond->> (:transaction-rule-account/account @account)
|
(location-select* {:name (fc/field-name)
|
||||||
(nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
|
:account-location (:account/location (cond->> (:transaction-rule-account/account @account)
|
||||||
'[:account/location])))
|
(nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
|
||||||
:client-locations (:client/locations (:transaction-rule/client transaction-rule))
|
'[:account/location])))
|
||||||
:hx-model "location"
|
:client-locations (:client/locations (:transaction-rule/client transaction-rule))
|
||||||
:value (fc/field-value)}))))
|
:hx-model "location"
|
||||||
(fc/with-field :transaction-rule-account/percentage
|
:value (fc/field-value)}))))
|
||||||
(com/data-grid-cell
|
(fc/with-field :transaction-rule-account/percentage
|
||||||
{}
|
(com/data-grid-cell
|
||||||
(com/validated-field
|
{}
|
||||||
{:errors (fc/field-errors)}
|
(com/validated-field
|
||||||
(com/money-input {:name (fc/field-name)
|
{:errors (fc/field-errors)}
|
||||||
:class "w-16"
|
(println "FIELD VALUE IS" (fc/field-value) (some-> (fc/field-value)
|
||||||
:value (some-> (fc/field-value)
|
(* 100 )
|
||||||
(* 100 )
|
(long )))
|
||||||
(long ))}))))))
|
(com/money-input {:name (fc/field-name)
|
||||||
(com/data-grid-cell {:class "align-top"}
|
:class "w-16"
|
||||||
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
|
:value (some-> (fc/field-value)
|
||||||
|
(* 100 )
|
||||||
|
(long ))}))))))
|
||||||
|
(com/data-grid-cell {:class "align-top"}
|
||||||
|
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
|
||||||
|
|
||||||
;; TODO background jobs and company 1099
|
;; TODO background jobs and company 1099
|
||||||
(defn dialog* [{:keys [entity form-params form-errors]}]
|
(defn dialog* [{:keys [entity form-params form-errors]}]
|
||||||
(fc/start-form form-params form-errors
|
(fc/start-form form-params form-errors
|
||||||
(com/modal
|
(com/modal
|
||||||
{:modal-class "max-w-2xl"
|
{:modal-class "max-w-2xl"
|
||||||
:hx-target "this"}
|
:hx-target "this"}
|
||||||
|
|
||||||
[:form {:hx-ext "response-targets"
|
[:form {:hx-ext "response-targets"
|
||||||
:hx-swap "outerHTML swap:300ms"
|
:hx-swap "outerHTML swap:300ms"
|
||||||
@@ -415,7 +411,6 @@
|
|||||||
{}
|
{}
|
||||||
[:div.flex [:div.p-2 "Transaction Rule"]]
|
[:div.flex [:div.p-2 "Transaction Rule"]]
|
||||||
[:fieldset {:class "hx-disable"
|
[:fieldset {:class "hx-disable"
|
||||||
:hx-disinherit "hx-target" ;; TODO why disinherit
|
|
||||||
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client form-params))
|
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client form-params))
|
||||||
(:transaction-rule/client form-params)
|
(:transaction-rule/client form-params)
|
||||||
(:db/id (:transaction-rule/client entity)))})}
|
(:db/id (:transaction-rule/client entity)))})}
|
||||||
@@ -542,8 +537,7 @@
|
|||||||
(com/data-grid {:headers [(com/data-grid-header {} "Account")
|
(com/data-grid {:headers [(com/data-grid-header {} "Account")
|
||||||
(com/data-grid-header {:class "w-32"} "Location")
|
(com/data-grid-header {:class "w-32"} "Location")
|
||||||
(com/data-grid-header {:class "w-16"} "%")
|
(com/data-grid-header {:class "w-16"} "%")
|
||||||
(com/data-grid-header {:class "w-16"})]
|
(com/data-grid-header {:class "w-16"})]}
|
||||||
:id "transaction-rule-account-table"}
|
|
||||||
(fc/cursor-map #(transaction-rule-account-row* form-params %))
|
(fc/cursor-map #(transaction-rule-account-row* form-params %))
|
||||||
(com/data-grid-new-row {:colspan 4
|
(com/data-grid-new-row {:colspan 4
|
||||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||||
@@ -604,7 +598,8 @@
|
|||||||
client-id client-id]
|
client-id client-id]
|
||||||
(html-response (account-typeahead* {:name name
|
(html-response (account-typeahead* {:name name
|
||||||
:value account
|
:value account
|
||||||
:client-id client-id}))))
|
:client-id client-id
|
||||||
|
:x-model "accountId"}))))
|
||||||
|
|
||||||
(def form-schema (mc/schema
|
(def form-schema (mc/schema
|
||||||
[:map
|
[:map
|
||||||
@@ -627,14 +622,13 @@
|
|||||||
[:transaction-rule-account/percentage percentage])]]))
|
[:transaction-rule-account/percentage percentage])]]))
|
||||||
|
|
||||||
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
|
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
|
||||||
(html-response (dialog* {:entity entity
|
(modal-response (dialog* {:entity entity
|
||||||
:form-params (or (when (seq form-params)
|
:form-params (or (when (seq form-params)
|
||||||
form-params)
|
form-params)
|
||||||
(when entity
|
(when entity
|
||||||
(mc/decode form-schema entity main-transformer)) ;; TODO coerce into form params
|
(mc/decode form-schema entity main-transformer))
|
||||||
{})
|
{})
|
||||||
:form-errors form-errors})
|
:form-errors form-errors})))
|
||||||
:headers {"hx-trigger" "modalopen"}))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
(ns auto-ap.ssr.ui
|
(ns auto-ap.ssr.ui
|
||||||
(:require
|
(:require
|
||||||
[hiccup2.core :as hiccup]
|
[auto-ap.ssr.hx :as hx]
|
||||||
[auto-ap.ssr.hx :as hx]))
|
[config.core :refer [env]]
|
||||||
|
[hiccup2.core :as hiccup]))
|
||||||
|
|
||||||
(defn html-page [hiccup]
|
(defn html-page [hiccup]
|
||||||
{:status 200
|
{:status 200
|
||||||
@@ -27,8 +28,12 @@
|
|||||||
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
|
[: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/@popperjs/core@2.11.8/dist/umd/popper.min.js"}]
|
||||||
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
|
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
|
||||||
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
|
(if (= "dev" (:dd-env env))
|
||||||
:crossorigin= "anonymous"}]
|
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.js"
|
||||||
|
:crossorigin= "anonymous"}]
|
||||||
|
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
|
||||||
|
:crossorigin= "anonymous"}])
|
||||||
|
|
||||||
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
|
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
|
||||||
[:script {:src "/js/htmx-disable.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.yodlee.com/fastlink/v4/initialize.js", :async "async"}]]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
html-response
|
html-response
|
||||||
main-transformer
|
main-transformer
|
||||||
many-entity
|
many-entity
|
||||||
|
modal-response
|
||||||
ref->enum-schema
|
ref->enum-schema
|
||||||
ref->select-options
|
ref->select-options
|
||||||
wrap-entity
|
wrap-entity
|
||||||
@@ -213,9 +214,7 @@
|
|||||||
:hx-vals (format "{\"db/id\": \"%s\"}" (:db/id entity))} "Impersonate")
|
:hx-vals (format "{\"db/id\": \"%s\"}" (:db/id entity))} "Impersonate")
|
||||||
(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||||
:user-edit-dialog
|
:user-edit-dialog
|
||||||
:db/id (:db/id entity)))
|
:db/id (:db/id entity)))}
|
||||||
:hx-target "#modal-content"
|
|
||||||
:hx-swap "innerHTML"}
|
|
||||||
svg/pencil)])
|
svg/pencil)])
|
||||||
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
|
||||||
:admin)}
|
:admin)}
|
||||||
@@ -352,16 +351,14 @@
|
|||||||
[:user/role (ref->enum-schema "user-role")]]))
|
[:user/role (ref->enum-schema "user-role")]]))
|
||||||
|
|
||||||
(defn user-dialog [{:keys [form-params entity form-errors]}]
|
(defn user-dialog [{:keys [form-params entity form-errors]}]
|
||||||
(html-response
|
(modal-response
|
||||||
(dialog* {:form-params (or (when (seq form-params)
|
(dialog* {:form-params (or (when (seq form-params)
|
||||||
form-params)
|
form-params)
|
||||||
(when entity
|
(when entity
|
||||||
(mc/decode form-schema entity main-transformer))
|
(mc/decode form-schema entity main-transformer))
|
||||||
{})
|
{})
|
||||||
:entity entity
|
:entity entity
|
||||||
:form-errors form-errors})
|
:form-errors form-errors})))
|
||||||
|
|
||||||
:headers {"hx-trigger" "modalopen"}))
|
|
||||||
|
|
||||||
(defn new-client [{ {:keys [index]} :query-params}]
|
(defn new-client [{ {:keys [index]} :query-params}]
|
||||||
(html-response
|
(html-response
|
||||||
|
|||||||
@@ -27,6 +27,16 @@
|
|||||||
o))
|
o))
|
||||||
oob)))})
|
oob)))})
|
||||||
|
|
||||||
|
(defn modal-response [hiccup & {:as opts}]
|
||||||
|
(apply html-response
|
||||||
|
(into
|
||||||
|
[hiccup]
|
||||||
|
(mapcat identity
|
||||||
|
(-> opts
|
||||||
|
(assoc-in [:headers "hx-trigger"] "modalopen")
|
||||||
|
(assoc-in [:headers "hx-retarget"] "#modal-content")
|
||||||
|
(assoc-in [:headers "hx-reswap"] "innerHTML"))))))
|
||||||
|
|
||||||
(defn wrap-error-response [handler]
|
(defn wrap-error-response [handler]
|
||||||
(fn [request]
|
(fn [request]
|
||||||
(try
|
(try
|
||||||
@@ -105,8 +115,11 @@
|
|||||||
|
|
||||||
(def temp-id (mc/schema [:string {:min 1}]))
|
(def temp-id (mc/schema [:string {:min 1}]))
|
||||||
(def money (mc/schema [:double]))
|
(def money (mc/schema [:double]))
|
||||||
(def percentage (mc/schema [:double {:decode/arbitrary (fn [x] (some-> x (* 0.01)))
|
(def percentage (mc/schema [:double {:decode/string {:enter (fn [x]
|
||||||
:max 1.0
|
(if (and (string? x) (re-find #"^\d+(\.\d+)?$" x))
|
||||||
|
(-> x (Double/parseDouble) (* 0.01))
|
||||||
|
x))}
|
||||||
|
:max 1.0
|
||||||
:error/message "1-100"}]))
|
:error/message "1-100"}]))
|
||||||
|
|
||||||
(def regex (mc/schema [:fn {:error/message "not a regex"}
|
(def regex (mc/schema [:fn {:error/message "not a regex"}
|
||||||
@@ -124,13 +137,7 @@
|
|||||||
x
|
x
|
||||||
(into []
|
(into []
|
||||||
(for [[k v] (sort-by (comp #(Long/parseLong %) name first) x)]
|
(for [[k v] (sort-by (comp #(Long/parseLong %) name first) x)]
|
||||||
v
|
v))))})
|
||||||
#_(assoc v :db/id (cond (and (string? k) (re-find #"^\d+$" k))
|
|
||||||
(Long/parseLong k)
|
|
||||||
(keyword? k)
|
|
||||||
(name k)
|
|
||||||
:else
|
|
||||||
k))))))})
|
|
||||||
|
|
||||||
(defn many-entity [params & keys]
|
(defn many-entity [params & keys]
|
||||||
(mc/schema
|
(mc/schema
|
||||||
@@ -174,6 +181,16 @@
|
|||||||
(mt2/transformer {:name :arbitrary})
|
(mt2/transformer {:name :arbitrary})
|
||||||
mt2/default-value-transformer))
|
mt2/default-value-transformer))
|
||||||
|
|
||||||
|
(defn strip [s]
|
||||||
|
(cond (and (string? s) (str/blank? s))
|
||||||
|
nil
|
||||||
|
|
||||||
|
(string? s)
|
||||||
|
(str/trim s)
|
||||||
|
|
||||||
|
:else
|
||||||
|
s))
|
||||||
|
|
||||||
(defn wrap-schema-decode [handler & {:keys [form-schema query-schema route-schema params-schema]}]
|
(defn wrap-schema-decode [handler & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||||
(fn [{:keys [form-params query-params params] :as request}]
|
(fn [{:keys [form-params query-params params] :as request}]
|
||||||
(let [request (try
|
(let [request (try
|
||||||
@@ -207,7 +224,6 @@
|
|||||||
main-transformer)))
|
main-transformer)))
|
||||||
(catch Exception e
|
(catch Exception e
|
||||||
(alog/warn ::validation-error :error e)
|
(alog/warn ::validation-error :error e)
|
||||||
|
|
||||||
(throw (ex-info (->> (-> e
|
(throw (ex-info (->> (-> e
|
||||||
(ex-data )
|
(ex-data )
|
||||||
:data
|
:data
|
||||||
@@ -251,17 +267,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#_(defn namespaceize-decoder [n]
|
|
||||||
{:exit (fn [m]
|
|
||||||
(when m
|
|
||||||
(reduce
|
|
||||||
(fn [m [k v]]
|
|
||||||
(if (= k "id")
|
|
||||||
(assoc m :db/id v)
|
|
||||||
(assoc m (keyword n (name k)) v)))
|
|
||||||
m
|
|
||||||
m)))})
|
|
||||||
|
|
||||||
|
|
||||||
(defn wrap-form-4xx [handler]
|
(defn wrap-form-4xx [handler]
|
||||||
(fn [request]
|
(fn [request]
|
||||||
@@ -274,17 +279,6 @@
|
|||||||
(html-response [:span.error-content.text-red-500 (:message &throw-context)]
|
(html-response [:span.error-content.text-red-500 (:message &throw-context)]
|
||||||
:status 400)))))
|
:status 400)))))
|
||||||
|
|
||||||
(defn assoc-errors-into-meta [entity errors]
|
|
||||||
(reduce
|
|
||||||
(fn add-error [entity {:keys [path message] :as se}]
|
|
||||||
(if (= (count path) 1)
|
|
||||||
(with-meta entity (assoc (meta entity) (last path) {:errors message}))
|
|
||||||
|
|
||||||
(update-in entity (butlast path)
|
|
||||||
(fn [terminal]
|
|
||||||
(with-meta terminal (assoc (meta terminal) (last path) {:errors message}))))))
|
|
||||||
entity
|
|
||||||
errors))
|
|
||||||
|
|
||||||
(defn wrap-form-4xx-2 [handler form-handler]
|
(defn wrap-form-4xx-2 [handler form-handler]
|
||||||
(fn [request]
|
(fn [request]
|
||||||
|
|||||||
Reference in New Issue
Block a user