a lot of streamlining for validation

This commit is contained in:
2023-10-24 11:12:31 -07:00
parent 48347bb8c5
commit 91f7e79aed
7 changed files with 161 additions and 168 deletions

View File

@@ -31,12 +31,12 @@
ref->enum-schema ref->enum-schema
ref->select-options ref->select-options
temp-id temp-id
wrap-entity
wrap-form-4xx-2 wrap-form-4xx-2
wrap-schema-decode]] wrap-schema-decode]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[clojure.string :as str] [clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup2.core :as hiccup]
[malli.core :as mc])) [malli.core :as mc]))
(defn filters [request] (defn filters [request]
@@ -291,16 +291,21 @@
;; ensure that adding a new one results in a new row ;; ensure that adding a new one results in a new row
(defn dialog* [& {:keys [entity form-params form-errors]}] (defn dialog* [{:keys [entity form-params form-errors]}]
(fc/start-form entity form-errors (fc/start-form form-params form-errors
[:div {:x-data (hx/json {"accountName" (:account/name entity) [:div {:x-data (hx/json {"accountName" (or (:account/name form-params) (:account/numeric-code entity))
"accountCode" (:account/numeric-code entity)})} "accountCode" (or (:account/numeric-code form-params) (:account/numeric-code entity) )})
:hx-target "this"}
(com/modal (com/modal
{} {}
[:form#edit-form (merge {:hx-ext "response-targets" [:form#edit-form (-> {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms" :hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content"} :hx-target-400 "#form-errors .error-content"}
form-params) (assoc (if (:db/id entity)
:hx-put
:hx-post)
(str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))))
[:fieldset {:class "hx-disable"} [:fieldset {:class "hx-disable"}
(com/modal-card (com/modal-card
{} {}
@@ -318,6 +323,7 @@
(com/validated-field {:label "Numeric code" (com/validated-field {:label "Numeric code"
:errors (fc/field-errors)} :errors (fc/field-errors)}
(com/text-input {:name (fc/field-name) (com/text-input {:name (fc/field-name)
:value (fc/field-value)
:x-model "accountCode" :x-model "accountCode"
:autofocus true :autofocus true
:class "w-32"})) :class "w-32"}))
@@ -388,9 +394,7 @@
] ]
[:div [:div
[:div [:div#form-errors (when (:errors fc/*form-errors*) (com/form-errors {:errors (:errors fc/*form-errors*)})
[:span.error-content
(com/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")])]])]))
@@ -403,34 +407,15 @@
[] []
(client-override* fc/*current*)))) (client-override* fc/*current*))))
(defn account-edit-dialog [request] (defn account-dialog [{:keys [entity form-params form-errors]}]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))] (html-response (dialog* {:entity entity
(html-response (dialog* :entity account :form-params (or (when (seq form-params)
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes form-params)
:admin-account-edit-save))}) entity
:headers {"hx-trigger" "modalopen"}))) {})
:form-errors form-errors})
(defn account-new-dialog [_]
(html-response (dialog* :entity {}
:form-errors {}
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-account-new-save))})
:headers {"hx-trigger" "modalopen"})) :headers {"hx-trigger" "modalopen"}))
(defn account-save-error [request]
;; TODO hydration
;; TODO consistency of error handling and passing, on all form examples
(let [entity (some-> request :last-form)]
(html-response (dialog* :entity entity
:form-errors (:form-errors request)
:form-params (if (:db/id entity)
{:hx-put (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))}
{:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))}))
:headers {"hx-retarget" "#edit-form fieldset"
"hx-reselect" "#edit-form fieldset"})))
(def account-schema (mc/schema (def account-schema (mc/schema
[:map [:map
@@ -439,14 +424,14 @@
[:account/name [:string {:min 1}]] [:account/name [:string {:min 1}]]
[:account/location [:maybe :string]] [:account/location [:maybe :string]]
[: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")]
[:account/vendor-allowance (ref->enum-schema "allowance")] [:account/vendor-allowance (ref->enum-schema "allowance")]
[:account/client-overrides {:optional true} [:account/client-overrides {:optional true}
[:maybe [:maybe
(many-entity {} (many-entity {}
[:db/id [:or entity-id temp-id]] [:db/id [:or entity-id temp-id]]
[:account-client-override/client [:or entity-id :string]] [:account-client-override/client entity-id]
[:account-client-override/name [:string {:min 2}]])]]])) [:account-client-override/name [:string {:min 2}]])]]]))
(def key->handler (def key->handler
@@ -460,12 +445,14 @@
:default 0} [nat-int? {:default 0}]]]) :default 0} [nat-int? {:default 0}]]])
wrap-admin wrap-client-redirect-unauthenticated) wrap-admin wrap-client-redirect-unauthenticated)
:admin-account-save (-> account-save :admin-account-save (-> account-save
(wrap-entity [:form-params :db/id] default-read)
(wrap-schema-decode :form-schema account-schema) (wrap-schema-decode :form-schema account-schema)
(wrap-nested-form-params) (wrap-nested-form-params)
(wrap-form-4xx-2 account-save-error)) (wrap-form-4xx-2 (wrap-entity account-dialog [:form-params :db/id] default-read)))
:admin-account-edit-dialog (-> account-edit-dialog :admin-account-edit-dialog (-> account-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]])) (wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
:admin-account-new-dialog account-new-dialog}) :admin-account-new-dialog account-dialog})
(fn [h] (fn [h]
(-> h (-> h
(wrap-admin) (wrap-admin)

View File

@@ -18,9 +18,9 @@
[auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.company :refer [bank-account-typeahead*]] [auto-ap.ssr.company :refer [bank-account-typeahead*]]
[auto-ap.ssr.components :as com] [auto-ap.ssr.components :as com]
[auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper] [auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.hx :as hx] [auto-ap.ssr.hx :as hx]
[auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]] [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils [auto-ap.ssr.utils
@@ -31,24 +31,20 @@
html-response html-response
many-entity many-entity
money money
path->name2
percentage percentage
ref->enum-schema ref->enum-schema
ref->radio-options ref->radio-options
regex regex
temp-id temp-id
wrap-entity
wrap-form-4xx-2 wrap-form-4xx-2
wrap-schema-decode]] wrap-schema-decode]]
[auto-ap.utils :refer [dollars=]] [auto-ap.utils :refer [dollars=]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[cheshire.core :as cheshire]
[clojure.string :as str] [clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup2.core :as hiccup]
[iol-ion.query :refer [ident]] [iol-ion.query :refer [ident]]
[malli.core :as mc] [malli.core :as mc]))
[auto-ap.cursor :as cursor]
[auto-ap.ssr.hiccup-helper :as hh]))
;; TODO with dependencies, I really don't like that you have to be ultra specific in what ;; 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. ;; you want to include, and generating the routes and interconnection is weird too.
@@ -401,25 +397,29 @@
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)))) (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
;; TODO dialog is no longer closeable ;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [entity form-params form-errors]}] ;; TODO might not need #edit-form id
(fc/start-form entity form-errors (defn dialog* [{:keys [entity 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"}
[:form#edit-form (merge {:hx-ext "response-targets" [:form#edit-form {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms" :hx-swap "outerHTML swap:300ms"
:hx-target "#modal-holder" ;; TODO sort :hx-target-400 "#form-errors .error-content"
:hx-target-400 "#form-errors .error-content" :x-trap "true"
:x-trap "true" :class "group/form"
:class "group/form"} (if (:db/id entity)
form-params) :hx-put
:hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
(com/modal-card (com/modal-card
{} {}
[: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 :hx-disinherit "hx-target" ;; TODO why disinherit
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity)) :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client form-params))
(:transaction-rule/client entity))})} (:transaction-rule/client form-params)
(:db/id (:transaction-rule/client entity)))})}
[:div.space-y-1 [:div.space-y-1
(when-let [id (:db/id entity)] (when-let [id (:db/id entity)]
@@ -486,7 +486,7 @@
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name)) :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
:x-init "$watch('clientId', cid => $dispatch('changed', $data))"}] :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
(bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity)) (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client form-params))
:name (fc/field-name) :name (fc/field-name)
:value (fc/field-value)})])) :value (fc/field-value)})]))
@@ -543,18 +543,20 @@
:content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})])) :content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})]))
(fc/with-field :transaction-rule/accounts (fc/with-field :transaction-rule/accounts
(com/data-grid {:headers [(com/data-grid-header {} "Account") (com/validated-field
(com/data-grid-header {:class "w-32"} "Location") {:errors (fc/field-errors)}
(com/data-grid-header {:class "w-16"} "%") (com/data-grid {:headers [(com/data-grid-header {} "Account")
(com/data-grid-header {:class "w-16"})] (com/data-grid-header {:class "w-32"} "Location")
:id "transaction-rule-account-table"} (com/data-grid-header {:class "w-16"} "%")
(fc/cursor-map #(transaction-rule-account-row* entity %)) (com/data-grid-header {:class "w-16"})]
(com/data-grid-new-row {:colspan 4 :id "transaction-rule-account-table"}
:hx-get (bidi/path-for ssr-routes/only-routes (fc/cursor-map #(transaction-rule-account-row* form-params %))
:admin-transaction-rule-new-account) (com/data-grid-new-row {:colspan 4
:index (count (fc/field-value)) :hx-get (bidi/path-for ssr-routes/only-routes
:tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})} :admin-transaction-rule-new-account)
"New account"))) :index (count (fc/field-value))
:tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
"New account"))))
(fc/with-field :transaction-rule/transaction-approval-status (fc/with-field :transaction-rule/transaction-approval-status
(com/validated-field {:label "Approval status" (com/validated-field {:label "Approval status"
@@ -567,10 +569,8 @@
]] ]]
[:div [:div
[:div#form-errors (when (:errors fc/*form-errors*) (com/form-errors {:errors (:errors fc/*form-errors*)})
[:span.error-content (com/validated-save-button {:errors (:errors form-errors)} "Save rule")])])))
(com/errors {:errors (:errors fc/*form-errors*)})])]
(com/validated-save-button {:errors form-errors} "Save rule")])])))
;; TODO Should forms have some kind of helper to render an individual field? saving ;; TODO Should forms have some kind of helper to render an individual field? saving
@@ -619,34 +619,14 @@
:value account :value account
:client-id client-id})))) :client-id client-id}))))
(defn transaction-rule-edit-dialog [request] (defn transaction-dialog [{:keys [entity form-params form-errors]}]
(let [entity (or (html-response (dialog* {:entity entity
(some-> request :last-form) :form-params (or (when (seq form-params)
(some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %))))] form-params)
(html-response (dialog* :entity entity entity ;; TODO coerce into form params
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes {})
:admin-transaction-rule-edit-save))}) :form-errors form-errors})
:headers {"hx-trigger-after-settle" "modalopen"}))) :headers {"hx-trigger" "modalopen"}))
(defn transaction-rule-error [request]
(let [entity (some-> request :last-form)]
(html-response (dialog* :entity entity
:form-errors (:form-errors request)
:form-params (if (:db/id entity)
{:hx-put (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))}
{:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))}))
:headers {"hx-retarget" "#edit-form fieldset"
"hx-reselect" "#edit-form fieldset"})))
(defn transaction-rule-new-dialog [_]
(html-response (dialog* :entity {}
:form-errors {}
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))})
:headers {"hx-trigger-after-settle" "modalopen"}))
(def transaction-rule-schema (mc/schema (def transaction-rule-schema (mc/schema
[:map [:map
@@ -695,12 +675,15 @@
[:value {:optional true} [:value {:optional true}
[:maybe entity-id]]])) [:maybe entity-id]]]))
:admin-transaction-rule-save (-> transaction-rule-save :admin-transaction-rule-save (-> transaction-rule-save
(wrap-entity [:form-params :db/id] default-read)
(wrap-schema-decode :form-schema transaction-rule-schema) (wrap-schema-decode :form-schema transaction-rule-schema)
(wrap-nested-form-params) (wrap-nested-form-params)
(wrap-form-4xx-2 transaction-rule-error)) (wrap-form-4xx-2 (-> transaction-dialog
:admin-transaction-rule-edit-dialog (-> transaction-rule-edit-dialog (wrap-entity [:form-params :db/id] default-read))))
:admin-transaction-rule-edit-dialog (-> transaction-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]])) (wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
:admin-transaction-rule-new-dialog transaction-rule-new-dialog}) :admin-transaction-rule-new-dialog transaction-dialog})
(fn [h] (fn [h]
(-> h (-> h
(wrap-admin) (wrap-admin)

View File

@@ -37,6 +37,7 @@
(def field inputs/field-) (def field inputs/field-)
(def validated-field inputs/validated-field-) (def validated-field inputs/validated-field-)
(def errors inputs/errors-) (def errors inputs/errors-)
(def form-errors inputs/form-errors-)
(def left-aside aside/left-aside-) (def left-aside aside/left-aside-)
(def company-aside-nav aside/company-aside-nav-) (def company-aside-nav aside/company-aside-nav-)

View File

@@ -4,11 +4,13 @@
[auto-ap.ssr.hiccup-helper :as hh])) [auto-ap.ssr.hiccup-helper :as hh]))
(defn modal- [params & children] (defn modal- [params & children]
[:div {:class (-> (:class params) [:div (-> params
(or "max-w-4xl w-1/4 overflow-visible") (update :class #(-> %
(hh/add-class "h-min")) (or "max-w-4xl w-1/4 overflow-visible")
"@click.outside" "open=false" (hh/add-class "h-min")))
} children])
(assoc "@click.outside" "open=false"))
children])
(defn modal-card- [params header content footer] (defn modal-card- [params header content footer]
[:div#modal-card (update params [:div#modal-card (update params

View File

@@ -152,6 +152,7 @@ c.clearChoices();
[:input [:input
(-> params (-> params
(dissoc :error?) (dissoc :error?)
(assoc :type "text")
(update (update
:class (fnil hh/add-class "") default-input-classes) :class (fnil hh/add-class "") default-input-classes)
(update :class #(str % (use-size size))))]) (update :class #(str % (use-size size))))])
@@ -210,6 +211,11 @@ c.clearChoices();
(when (sequential? errors) (when (sequential? errors)
(str/join ", " (filter string? errors)))]) (str/join ", " (filter string? errors)))])
(defn form-errors- [{:keys [errors]}]
[:div#form-errors (when errors
[:span.error-content
(errors- {:errors errors})])])
(defn validated-field- [params & rest] (defn validated-field- [params & rest]
(field- (cond-> params (field- (cond-> params
true (dissoc :errors) true (dissoc :errors)

View File

@@ -26,6 +26,7 @@
many-entity many-entity
ref->enum-schema ref->enum-schema
ref->select-options ref->select-options
wrap-entity
wrap-form-4xx-2 wrap-form-4xx-2
wrap-schema-decode]] wrap-schema-decode]]
[auto-ap.time :as atime] [auto-ap.time :as atime]
@@ -34,9 +35,7 @@
[clojure.string :as str] [clojure.string :as str]
[config.core :refer [env]] [config.core :refer [env]]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup2.core :as hiccup] [malli.core :as mc]))
[malli.core :as mc]
[clj-time.format :as f]))
(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"
@@ -257,14 +256,17 @@
(def table* (partial helper/table* grid-page)) (def table* (partial helper/table* grid-page))
(defn impersonate [request] (defn impersonate [request]
(let [user (some-> request :params :db/id (#(dc/pull (dc/db conn) default-read %))) ] (println (:entity request))
(if (:entity request)
{:status 200 {:status 200
:headers {"hx-redirect" (str "/?jwt=" (jwt/sign (auth/user->jwt user "FAKE_TOKEN") :headers {"hx-redirect" (str "/?jwt=" (jwt/sign (auth/user->jwt (:entity request) "FAKE_TOKEN")
(:jwt-secret env) (:jwt-secret env)
{:alg :hs512})) {:alg :hs512}))
} }
:session {:identity (dissoc (auth/user->jwt user "FAKE_TOKEN") :session {:identity (dissoc (auth/user->jwt (:entity request) "FAKE_TOKEN")
:exp)}})) :exp)}}
{:status 404}))
(defn client-row* [client] (defn client-row* [client]
(com/data-grid-row (-> {:x-ref "p" (com/data-grid-row (-> {:x-ref "p"
:data-key "show" :data-key "show"
@@ -288,19 +290,20 @@
(com/data-grid-cell {:class "align-top"} (com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)))) (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
(defn dialog* [{:keys [entity form-params form-errors]}]
;; TODO hydrate user name
(defn dialog* [{:keys [form-params form-errors entity]}]
(fc/start-form (fc/start-form
entity form-errors form-params form-errors
(com/modal (com/modal
{} {:hx-target "this"}
[:form#edit-form (merge {:hx-ext "response-targets" [:form#edit-form {:hx-ext "response-targets"
:hx-put (str (bidi/path-for ssr-routes/only-routes :hx-put (str (bidi/path-for ssr-routes/only-routes
:user-edit-save :user-edit-save
:request-method :put)) :request-method :put))
:hx-swap "outerHTML swap:300ms" :hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content" :hx-target-400 "#form-errors .error-content"
:class "w-full"} :class "w-full"}
form-params)
[:fieldset {:class "hx-disable"} [:fieldset {:class "hx-disable"}
(com/modal-card (com/modal-card
{} {}
@@ -329,9 +332,7 @@
:user-client-new)} :user-client-new)}
"Assign new client"))))] "Assign new client"))))]
[:div [:div
[:div [:div#form-errors (when (:errors fc/*form-errors*) (com/form-errors {:errors (:errors fc/*form-errors*)})
[:span.error-content
(com/errors {:errors (:errors fc/*form-errors*)})])]]
(com/validated-save-button {:errors (seq form-errors)} (com/validated-save-button {:errors (seq form-errors)}
"Save user")])]]))) "Save user")])]])))
@@ -348,22 +349,17 @@
(defn user-save-error [request] (defn user-save-error [request]
;; TODO hydration ;; TODO hydration
;; TODO consistency of error handling and passing, on all form examples ;; TODO consistency of error handling and passing, on all form examples
(let [entity (some-> request :last-form)] (html-response (dialog* {:form-params (:form-params request)
(html-response (dialog* {:entity entity :entity (:entity request)
:form-errors (:form-errors request)}) :form-errors (:form-errors request)})))
:headers {"hx-retarget" "#edit-form fieldset"
"hx-reselect" "#edit-form fieldset"})))
(defn user-edit-dialog [request] (defn user-edit-dialog [request]
(let [user (some-> request (html-response
:route-params (dialog* {:form-params (:entity request)
:db/id :entity (:entity request)
(#(dc/pull (dc/db conn) default-read %)))] :form-errors {}})
(html-response
(dialog* {:entity user
:form-errors {}})
:headers {"hx-trigger" "modalopen"}))) :headers {"hx-trigger" "modalopen"}))
(defn new-client [{ {:keys [index]} :query-params}] (defn new-client [{ {:keys [index]} :query-params}]
(html-response (html-response
@@ -371,28 +367,34 @@
:new? true} [] :new? true} []
(client-row* fc/*current*)))) (client-row* fc/*current*))))
(def user-form-schema
(mc/schema
[:map
[:db/id entity-id]
[:user/clients {:optional true}
[:maybe
(many-entity {} [:db/id entity-id])]]
[:user/role (ref->enum-schema "user-role")]]))
(def key->handler (def key->handler
(apply-middleware-to-all-handlers (apply-middleware-to-all-handlers
{:users (helper/page-route grid-page) {:users (helper/page-route grid-page)
:user-table (helper/table-route grid-page) :user-table (helper/table-route grid-page)
:user-edit-save (-> user-edit-save :user-edit-save (-> user-edit-save
(wrap-schema-decode :form-schema (mc/schema (wrap-entity [:form-params :db/id] default-read)
[:map (wrap-schema-decode :form-schema user-form-schema)
[:db/id entity-id]
[:user/clients {:optional true}
[:maybe
(many-entity {} [:db/id entity-id])]]
[:user/role (ref->enum-schema "user-role")]]))
(wrap-nested-form-params) (wrap-nested-form-params)
(wrap-form-4xx-2 user-save-error)) (wrap-form-4xx-2 (wrap-entity user-save-error [:form-params :db/id] default-read)))
:user-client-new (-> new-client :user-client-new (-> new-client
(wrap-schema-decode :query-schema [:map (wrap-schema-decode :query-schema [:map
[:index {:optional true [:index {:optional true
:default 0} [nat-int? {:default 0}]]])) :default 0} [nat-int? {:default 0}]]]))
:user-edit-dialog (-> user-edit-dialog :user-edit-dialog (-> user-edit-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode (wrap-schema-decode
:route-schema (mc/schema [:map [:db/id entity-id]]))) :route-schema (mc/schema [:map [:db/id entity-id]])))
:user-impersonate (-> impersonate :user-impersonate (-> impersonate
(wrap-entity [:params :db/id] default-read)
(wrap-schema-decode (wrap-schema-decode
:params-schema (mc/schema [:map [:db/id entity-id]])))} :params-schema (mc/schema [:map [:db/id entity-id]])))}
(fn [h] (fn [h]

View File

@@ -1,15 +1,15 @@
(ns auto-ap.ssr.utils (ns auto-ap.ssr.utils
(:require (:require
[auto-ap.datomic :refer [all-schema]] [auto-ap.datomic :refer [all-schema conn]]
[auto-ap.logging :as alog] [auto-ap.logging :as alog]
[clojure.string :as str] [clojure.string :as str]
[config.core :refer [env]] [config.core :refer [env]]
[datomic.api :as dc]
[hiccup2.core :as hiccup] [hiccup2.core :as hiccup]
[malli.core :as mc] [malli.core :as mc]
[malli.error :as me] [malli.error :as me]
[malli.transform :as mt2] [malli.transform :as mt2]
[slingshot.slingshot :refer [throw+ try+]] [slingshot.slingshot :refer [throw+ try+]]))
[manifold.time :as mt]))
(defn html-response [hiccup & {:keys [status headers oob] :or {status 200 headers {} oob []}}] (defn html-response [hiccup & {:keys [status headers oob] :or {status 200 headers {} oob []}}]
{:status status {:status status
@@ -99,7 +99,7 @@
(def entity-id (mc/schema [nat-int? {:error/message "required"} ])) (def entity-id (mc/schema [nat-int? {:error/message "required"} ]))
(def temp-id (mc/schema :string)) (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/arbitrary (fn [x] (some-> x (* 0.01)))
:max 1.0 :max 1.0
@@ -292,18 +292,18 @@
(:errors (:explain (:error e))))] (:errors (:explain (:error e))))]
(alog/warn ::form-4xx :errors errors) (alog/warn ::form-4xx :errors errors)
(form-handler (assoc request (form-handler (assoc request
:last-form (:decoded e) :form-params (:decoded e)
:field-validation-errors errors :field-validation-errors errors
:form-errors humanized))) :form-errors humanized)))
#_(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))
(catch [:type :field-validation] e (catch [:type :field-validation] e
(form-handler (assoc request (form-handler (assoc request
:last-form (:form e) :form-params (:form e)
:form-errors (:form-errors e)))) :form-errors (:form-errors e))))
(catch [:type :form-validation] e (catch [:type :form-validation] e
(form-handler (assoc request (form-handler (assoc request
:last-form (:form e) :form-params (:form e)
:form-validation-errors (:form-validation-errors e) :form-validation-errors (:form-validation-errors e)
:form-errors {:errors (:form-validation-errors e)})))))) :form-errors {:errors (:form-validation-errors e)}))))))
@@ -326,3 +326,15 @@
(map (fn [k] (map (fn [k]
(str "[" (k->n k) "]")) (str "[" (k->n k) "]"))
rest))))) rest)))))
(defn wrap-entity [handler path read]
(fn wrap-entity-request [request]
(let [entity (some->>
(get-in request path)
(#(if (string? %) (Long/parseLong %) %))
(dc/pull (dc/db conn) read ))]
(handler (if entity
(assoc request
:entity entity)
request)))))