Vendors form progress
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
:refer [assert-can-see-client can-see-client? cleanse-query is-admin?]]
|
||||
[auto-ap.solr :as solr]
|
||||
[auto-ap.ssr.utils
|
||||
:refer [entity-id ref->enum-schema wrap-schema-decode]]
|
||||
:refer [entity-id ref->enum-schema wrap-schema-enforce]]
|
||||
[com.brunobonacci.mulog :as mu]
|
||||
[datomic.api :as dc]
|
||||
[ring.middleware.json :refer [wrap-json-response]]))
|
||||
@@ -91,7 +91,7 @@
|
||||
xform))))
|
||||
[]))}))
|
||||
|
||||
(def account-search (wrap-json-response (wrap-schema-decode account-search
|
||||
(def account-search (wrap-json-response (wrap-schema-enforce account-search
|
||||
:query-schema [:map
|
||||
[:q :string]
|
||||
[:client-id {:optional true
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
temp-id
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
@@ -412,18 +412,18 @@
|
||||
{:admin-accounts (helper/page-route grid-page)
|
||||
:admin-account-table (helper/table-route grid-page)
|
||||
:admin-account-client-override-new (-> new-client-override
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]])
|
||||
wrap-admin wrap-client-redirect-unauthenticated)
|
||||
:admin-account-save (-> account-save
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (wrap-entity account-dialog [:form-params :db/id] default-read)))
|
||||
: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-enforce :route-schema [:map [:db/id entity-id]]))
|
||||
:admin-account-new-dialog account-dialog})
|
||||
(fn [h]
|
||||
(-> h
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
html-response
|
||||
modal-response
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-time.coerce :as coerce]
|
||||
@@ -256,9 +256,9 @@
|
||||
(->>
|
||||
{:admin-jobs (helper/page-route grid-page)
|
||||
:admin-job-table (helper/table-route grid-page)
|
||||
:admin-job-subform (-> subform (wrap-schema-decode :query-schema [:map [:name {:optional true} [:maybe :string]]]))
|
||||
:admin-job-subform (-> subform (wrap-schema-enforce :query-schema [:map [:name {:optional true} [:maybe :string]]]))
|
||||
:admin-job-start (-> job-start
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 job-start-dialog))
|
||||
:admin-job-start-dialog job-start-dialog})
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:refer [apply-middleware-to-all-handlers
|
||||
html-response
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clj-time.coerce :as coerce]
|
||||
@@ -311,7 +311,7 @@
|
||||
(->>
|
||||
{::route/page page
|
||||
::route/import (-> import
|
||||
(wrap-schema-decode :form-schema [:map [:tsv :string]])
|
||||
(wrap-schema-enforce :form-schema [:map [:tsv :string]])
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 form))
|
||||
})
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
temp-id
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[auto-ap.utils :refer [dollars=]]
|
||||
[bidi.bidi :as bidi]
|
||||
@@ -832,6 +832,7 @@
|
||||
{})
|
||||
:form-errors form-errors})))
|
||||
|
||||
|
||||
(defn check-badges [{query-params :query-params}]
|
||||
(html-response
|
||||
[:div (if (not-empty (:all query-params))
|
||||
@@ -875,21 +876,21 @@
|
||||
{::route/page (helper/page-route grid-page)
|
||||
::route/table (helper/table-route grid-page)
|
||||
::route/new-account (-> new-account
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]])
|
||||
wrap-admin wrap-client-redirect-unauthenticated)
|
||||
::route/location-select (-> location-select
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:name :string]
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]
|
||||
[:account-id {:optional true}
|
||||
[:maybe entity-id]]]))
|
||||
::route/account-typeahead (-> account-typeahead
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:name :string]
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]
|
||||
@@ -897,7 +898,7 @@
|
||||
[:maybe entity-id]]]))
|
||||
::route/save (-> save
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> edit-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
@@ -905,8 +906,8 @@
|
||||
::route/execute (-> execute
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode :route-schema [:map [:db/id entity-id]])
|
||||
(wrap-schema-decode :form-schema
|
||||
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]])
|
||||
(wrap-schema-enforce :form-schema
|
||||
[:map
|
||||
[:transaction-id {:optional true}
|
||||
[:maybe [:vector {:decode/arbitrary (fn [x] ;; TODO make this easier
|
||||
@@ -920,13 +921,13 @@
|
||||
|
||||
::route/test (-> test
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> edit-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
|
||||
::route/check-badges (-> check-badges
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:transaction-id {:optional true}
|
||||
[:maybe [:vector {:decode/arbitrary (fn [x]
|
||||
(if (sequential? x)
|
||||
@@ -936,11 +937,11 @@
|
||||
[:all {:optional true} [:maybe :string]]]))
|
||||
::route/execute-dialog (-> execute-dialog
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
|
||||
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
|
||||
|
||||
::route/edit-dialog (-> edit-dialog
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
|
||||
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
|
||||
::route/new-dialog edit-dialog})
|
||||
(fn [h]
|
||||
(-> h
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns auto-ap.ssr.admin.vendors
|
||||
(:require
|
||||
[auto-ap.cursor :as cursor]
|
||||
[auto-ap.datomic
|
||||
:refer [add-sorter-fields
|
||||
apply-pagination
|
||||
@@ -10,13 +11,15 @@
|
||||
pull-attr
|
||||
pull-many
|
||||
query2]]
|
||||
[auto-ap.routes.admin.vendors :as route]
|
||||
[auto-ap.datomic.accounts :as d-accounts]
|
||||
[auto-ap.logging :as alog]
|
||||
[auto-ap.query-params :as query-params]
|
||||
[auto-ap.routes.admin.vendors :as route]
|
||||
[auto-ap.routes.utils
|
||||
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
|
||||
[auto-ap.solr :as solr]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.components :as com]
|
||||
[auto-ap.ssr.components.timeline :as timeline]
|
||||
[auto-ap.ssr.form-cursor :as fc]
|
||||
[auto-ap.ssr.grid-page-helper :as helper]
|
||||
[auto-ap.ssr.hx :as hx]
|
||||
@@ -25,26 +28,24 @@
|
||||
[auto-ap.ssr.utils
|
||||
:refer [apply-middleware-to-all-handlers
|
||||
entity-id
|
||||
field-validation-error
|
||||
form-validation-error
|
||||
html-response
|
||||
main-transformer
|
||||
many-entity
|
||||
modal-response
|
||||
ref->enum-schema
|
||||
ref->select-options
|
||||
schema-enforce-request
|
||||
strip
|
||||
temp-id
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
[malli.core :as mc]
|
||||
[auto-ap.ssr.hiccup-helper :as hh]
|
||||
[auto-ap.logging :as alog]
|
||||
[auto-ap.cursor :as cursor]))
|
||||
[malli.util :as mut]
|
||||
[com.brunobonacci.mulog :as mu]
|
||||
[hiccup.util :as hu]))
|
||||
|
||||
(defn filters [request]
|
||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||
@@ -85,10 +86,12 @@
|
||||
:vendor/legal-entity-middle-name
|
||||
:vendor/legal-entity-last-name
|
||||
{:vendor/primary-contact [:contact/email :contact/first-name :contact/middle-name :contact/last-name]
|
||||
:vendor/address [:address/street1 :address/street2 :address/city :address/state :address/zip]
|
||||
:vendor/terms-overrides [:vendor-terms-override/terms {:vendor-terms-override/client [:client/name :db/id]}]
|
||||
:vendor/account-overrides [{:vendor-terms-override/account [:account/name :db/id]
|
||||
:vendor-terms-override/client [:client/name :db/id]}]
|
||||
:vendor/address [:address/street1 :address/street2 :address/city :address/state :address/zip :db/id]
|
||||
:vendor/terms-overrides [:vendor-terms-override/terms {:vendor-terms-override/client [:client/name :db/id]} :db/id]
|
||||
:vendor/automatically-paid-when-due [:db/id :client/name]
|
||||
:vendor/account-overrides [{:vendor-account-override/account [:account/name :db/id]
|
||||
:vendor-account-override/client [:client/name :db/id]}
|
||||
:db/id]
|
||||
:vendor/default-account [:account/name :account/numeric-code :db/id]
|
||||
[:vendor-usage/_vendor :as :vendor/usage] [:vendor-usage/client :vendor-usage/count]
|
||||
[:vendor/legal-entity-1099-type :xform iol-ion.query/ident] [:db/ident]
|
||||
@@ -191,7 +194,6 @@
|
||||
(when (> client-usage 0)
|
||||
[:div (com/pill {:color :secondary}
|
||||
(format "Used %d times" total-usage))])]))}
|
||||
|
||||
{:key "email"
|
||||
:name "Email"
|
||||
:sort-key "email"
|
||||
@@ -206,9 +208,8 @@
|
||||
|
||||
(defn save [{:keys [form-params request-method] :as request}]
|
||||
(let [entity (alog/peek (cond-> form-params
|
||||
(= :post request-method) (assoc :db/id "new")))
|
||||
|
||||
|
||||
(= :post request-method) (assoc :db/id "new")
|
||||
(not (some identity (vals (dissoc (:vendor/address form-params) :db/id)))) (assoc :vendor/address nil)))
|
||||
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
|
||||
(:identity request))
|
||||
updated-vendor (dc/pull (dc/db conn)
|
||||
@@ -238,64 +239,43 @@
|
||||
"hx-reswap" "afterbegin")
|
||||
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-vendor)))))))
|
||||
|
||||
#_(defn client-override* [override]
|
||||
(com/data-grid-row (-> {:x-ref "p"
|
||||
:data-key "show"
|
||||
:x-data (hx/json {:show (boolean (doto (not (fc/field-value (:new? override)))
|
||||
println))})}
|
||||
hx/alpine-mount-then-appear)
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
(fc/with-field :account-client-override/client
|
||||
(com/data-grid-cell {}
|
||||
(com/validated-field {:errors (fc/field-errors)}
|
||||
(com/typeahead {:name (fc/field-name)
|
||||
:placeholder "Search..."
|
||||
:class "w-96"
|
||||
:url (bidi/path-for ssr-routes/only-routes
|
||||
:company-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn #(pull-attr (dc/db conn) :client/name %)}))))
|
||||
(fc/with-field :account-client-override/name
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field {:errors (fc/field-errors)}
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:class "w-96"
|
||||
:value (fc/field-value)}))))
|
||||
(com/data-grid-cell {:class "align-top"}
|
||||
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
|
||||
|
||||
(defn back-button []
|
||||
[:a {"@click" "$dispatch('modalprevious')"
|
||||
"class" "text-sm font-medium text-gray-700 cursor-pointer"}
|
||||
"Back"])
|
||||
|
||||
(defn dialog* [{:keys [entity form-params form-errors]}]
|
||||
(alog/peek ::dialog-entity form-params)
|
||||
(fc/start-form form-params form-errors
|
||||
[:div {:x-data (hx/json {"vendorName" (or (:vendor/name form-params) (:vendor/name entity))
|
||||
"showPrintAs" (boolean (not-empty (:vendor/print-as form-params)))
|
||||
"printAs" (or (:vendor/print-as form-params) (:vendor/print-as entity))})
|
||||
:class "w-full h-full"}
|
||||
[:form#my-form (-> {:hx-ext "response-targets"
|
||||
:hx-swap "outerHTML swap:300ms"
|
||||
:hx-target-400 "#form-errors .error-content"
|
||||
:hx-trigger "submit"
|
||||
:class "h-full w-full"}
|
||||
(assoc (if (:db/id entity)
|
||||
:hx-put
|
||||
:hx-post)
|
||||
(str (bidi/path-for ssr-routes/only-routes ::route/save))))
|
||||
(com/modal
|
||||
;; TODO -
|
||||
;; make new vendor work
|
||||
;; generalize
|
||||
|
||||
|
||||
|
||||
;; TODO warn about usage on the vendor based on the thing
|
||||
|
||||
(defn timeline [{:keys [active]}]
|
||||
(let [steps ["Info" "Terms" "Account" "Address" "Legal"]
|
||||
active-index (.indexOf steps active )]
|
||||
(timeline/timeline
|
||||
{}
|
||||
(com/stacked-modal-card
|
||||
(for [[n i] (map vector steps (range))]
|
||||
(timeline/timeline-step (cond-> {}
|
||||
(= i active-index) (assoc :active? true)
|
||||
(< i active-index) (assoc :visited? true)
|
||||
(= i (dec (count steps))) (assoc :last? true))
|
||||
n)))))
|
||||
|
||||
(defn info-modal [{:keys [form-params form-errors entity]}]
|
||||
(com/stacked-modal-card-2
|
||||
0
|
||||
{"@keydown.enter.prevent.stop" "$refs.next.click()"}
|
||||
(com/modal-header {}
|
||||
[:div.flex [:div.p-2 "Basic Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
|
||||
[:span {:x-text "vendorName"}]]]
|
||||
[:div.space-y-1
|
||||
[:span {:x-text "vendorName"}]]])
|
||||
(com/modal-header-attachment
|
||||
{}
|
||||
(timeline {:active "Info"}))
|
||||
(com/modal-body {}
|
||||
[:div.space-y-1.mt-4 {:class "w-[600px] h-[350px]"}
|
||||
(when-let [id (:db/id entity)]
|
||||
(com/hidden {:name "db/id"
|
||||
:value id}))
|
||||
@@ -304,13 +284,16 @@
|
||||
(com/validated-field {:label "Name"
|
||||
:errors (fc/field-errors)
|
||||
}
|
||||
[:div.flex.items-baseline.space-x-2
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:x-model "vendorName"
|
||||
:autofocus true
|
||||
:class "w-64"})
|
||||
(com/checkbox {:x-model "showPrintAs" "@change" "if (!showPrintAs) { printAs = ''; } "} "Use different name for checks")]))
|
||||
:class "w-96"})))
|
||||
(com/validated-field
|
||||
{}
|
||||
[:div (com/checkbox
|
||||
{:x-model "showPrintAs" "@change" "if (!showPrintAs) { printAs = ''; } "}
|
||||
"Use different name for checks")])
|
||||
|
||||
(fc/with-field :vendor/print-as
|
||||
(com/validated-field (-> {:label "Print as"
|
||||
@@ -321,42 +304,145 @@
|
||||
(com/text-input {:name (fc/field-name)
|
||||
:x-model "printAs"
|
||||
:value (fc/field-value)
|
||||
:class "w-64"})))
|
||||
:class "w-96"})))
|
||||
|
||||
(fc/with-field :vendor/hidden
|
||||
(alog/peek (cursor/path fc/*current*))
|
||||
(com/checkbox {:name (fc/field-name)
|
||||
:value (boolean (fc/field-value))
|
||||
:value (boolean (fc/field-value)) ;
|
||||
:checked (alog/peek :checked (fc/field-value))}
|
||||
"Hidden"))]
|
||||
"Admin-only"))])
|
||||
(com/modal-footer
|
||||
{}
|
||||
[:div.flex.justify-end
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
|
||||
(com/validated-save-button {:errors (seq form-errors)
|
||||
:x-ref "next"
|
||||
:class "w-48"
|
||||
"@click.prevent" "$dispatch('modalnext'); console.log($el)"}
|
||||
:hx-put (hu/url (bidi/path-for ssr-routes/only-routes ::route/validate)
|
||||
{:step "Info"})
|
||||
|
||||
}
|
||||
|
||||
"Terms"
|
||||
[:div.w-5.h-5 svg/arrow-right])]])
|
||||
[:div.w-5.h-5 svg/arrow-right])]])))
|
||||
|
||||
(com/stacked-modal-card
|
||||
;; TODO add plaid merchant
|
||||
;; TODO each client only used once
|
||||
|
||||
(defn terms-override-row [terms-override-cursor]
|
||||
(com/data-grid-row
|
||||
(-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? terms-override-cursor))))})
|
||||
:data-key "show"
|
||||
:x-ref "p"}
|
||||
hx/alpine-mount-then-appear)
|
||||
(list
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
(fc/with-field :vendor-terms-override/client
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)}
|
||||
(com/typeahead {:name (fc/field-name)
|
||||
:error? (fc/error?)
|
||||
:autofocuse true
|
||||
:class "w-full grow shrink"
|
||||
:placeholder "Search..."
|
||||
:url (bidi/path-for ssr-routes/only-routes :company-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :client/name c))}))))
|
||||
(fc/with-field :vendor-terms-override/terms
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)}
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(com/int-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:class "w-16"})
|
||||
"days"])))
|
||||
(com/data-grid-cell {:class "align-top"}
|
||||
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)))))
|
||||
|
||||
|
||||
(defn automatically-paid-when-due-row [terms-override-cursor]
|
||||
(com/data-grid-row
|
||||
(-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? terms-override-cursor))))})
|
||||
:data-key "show"
|
||||
:x-ref "p"}
|
||||
hx/alpine-mount-then-appear)
|
||||
(list
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field {:errors (fc/field-errors (:db/id fc/*current*))}
|
||||
(com/typeahead {:name (fc/field-name (:db/id fc/*current*))
|
||||
:class "w-full"
|
||||
:url (bidi/path-for ssr-routes/only-routes
|
||||
:company-search)
|
||||
:value (fc/field-value)
|
||||
:value-fn :db/id
|
||||
|
||||
|
||||
:content-fn #(pull-attr (dc/db conn) :client/name (:db/id %))
|
||||
:size :small})))
|
||||
|
||||
|
||||
(com/data-grid-cell {:class "align-top"}
|
||||
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)))))
|
||||
|
||||
;; TODO when a validation fails, only re render that page
|
||||
|
||||
(defn terms-modal [{:keys [form-errors entity form-params]}]
|
||||
(com/stacked-modal-card-2
|
||||
1
|
||||
{"@keydown.enter.prevent.stop" "$refs.next.click()"}
|
||||
(com/modal-header {}
|
||||
[:div.flex
|
||||
[:div.p-2 "Vendor Terms"]
|
||||
[:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
|
||||
[:span {:x-text "vendorName"}]]]
|
||||
[:div
|
||||
[:div.space-y-1
|
||||
[:span {:x-text "vendorName"}]]])
|
||||
(com/modal-header-attachment {}
|
||||
(timeline {:active "Terms"}))
|
||||
(com/modal-body {}
|
||||
[:div.space-y-1 {:class "w-[600px] h-[350px]"}
|
||||
(fc/with-field :vendor/terms
|
||||
(com/validated-field {:label "Terms"
|
||||
:errors (fc/field-errors)}
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(com/int-input {:name (fc/field-name)
|
||||
:value (fc/field-value)
|
||||
:autofocus true
|
||||
:class "w-24"})))]]
|
||||
})
|
||||
"days"]))
|
||||
(fc/with-field :vendor/terms-overrides
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)
|
||||
:label "Terms Overrides"}
|
||||
(com/data-grid {:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {:class "w-16"} "Terms")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(terms-override-row %))
|
||||
(com/data-grid-new-row {:colspan 3
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
::route/new-terms-override)
|
||||
:index (count (fc/field-value))}
|
||||
"New override"))))
|
||||
|
||||
(fc/with-field :vendor/automatically-paid-when-due
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)
|
||||
:label "Automatically pay when due"}
|
||||
(com/data-grid {:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(automatically-paid-when-due-row %))
|
||||
(com/data-grid-new-row {:colspan 2
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-automatic-payment)
|
||||
:index (count (fc/field-value))}
|
||||
"New automatic payment for client"))))])
|
||||
(com/modal-footer
|
||||
{}
|
||||
[:div.flex.justify-end
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
@@ -364,20 +450,85 @@
|
||||
(com/validated-save-button {:errors (seq form-errors)
|
||||
:x-ref "next"
|
||||
:class "w-48"
|
||||
"@click.prevent" "$dispatch('modalnext'); console.log($el)"}
|
||||
:hx-put (hu/url (bidi/path-for ssr-routes/only-routes ::route/validate)
|
||||
{:step "Terms"})}
|
||||
|
||||
"Account assignments"
|
||||
[:div.w-5.h-5 svg/arrow-right])]])
|
||||
[:div.w-5.h-5 svg/arrow-right])]])))
|
||||
|
||||
(com/stacked-modal-card
|
||||
(defn- account-typeahead*
|
||||
[{:keys [name value client-id x-model]}]
|
||||
[:div.flex.flex-col
|
||||
(com/typeahead {:name name
|
||||
:placeholder "Search..."
|
||||
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
|
||||
:id name
|
||||
:x-model x-model
|
||||
:value value
|
||||
:content-fn (fn [value]
|
||||
(:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
|
||||
client-id)))})])
|
||||
|
||||
(defn account-override-row [terms-override-cursor]
|
||||
(alog/peek @terms-override-cursor)
|
||||
(let [client-id (fc/field-value (:vendor-account-override/client terms-override-cursor))]
|
||||
(com/data-grid-row
|
||||
(-> {:x-data (hx/json {:show (boolean (not (fc/field-value (:new? terms-override-cursor))))
|
||||
:clientId client-id
|
||||
:accountId (fc/field-value (:vendor-account-override/account terms-override-cursor))})
|
||||
:data-key "show"
|
||||
:x-ref "p"}
|
||||
hx/alpine-mount-then-appear)
|
||||
(list
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
(fc/with-field :vendor-account-override/client
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)}
|
||||
(com/typeahead {:name (fc/field-name)
|
||||
:error? (fc/error?)
|
||||
:x-model "clientId"
|
||||
:autofocuse true
|
||||
:class "w-full grow shrink"
|
||||
:placeholder "Search..."
|
||||
:url (bidi/path-for ssr-routes/only-routes :company-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :client/name c))}))))
|
||||
(fc/with-field :vendor-account-override/account
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)}
|
||||
[:div {:hx-trigger "changed"
|
||||
:hx-target "next div"
|
||||
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId, value: event.detail.accountId || ''}" (fc/field-name))
|
||||
:hx-get (str (bidi/path-for ssr-routes/only-routes ::route/account-typeahead))
|
||||
:x-init "$watch('clientId', cid => $dispatch('changed', $data));"}]
|
||||
(account-typeahead* {:value (fc/field-value)
|
||||
:client-id client-id
|
||||
:name (fc/field-name)
|
||||
:x-model "accountId"}))))
|
||||
(com/data-grid-cell {:class "align-top"}
|
||||
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))))
|
||||
|
||||
(defn account-modal [{:keys [form-errors entity form-params]}]
|
||||
(com/stacked-modal-card-2
|
||||
2
|
||||
{"@keydown.enter.prevent.stop" "$refs.next.click()"}
|
||||
(com/modal-header
|
||||
{}
|
||||
[:div.flex
|
||||
[:div.p-2 "Vendor Account"]
|
||||
[:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
|
||||
[:span {:x-text "vendorName"}]]]
|
||||
[:div
|
||||
[:div.space-y-1
|
||||
[:span {:x-text "vendorName"}]]])
|
||||
(com/modal-header-attachment {}
|
||||
(timeline {:active "Account"}))
|
||||
(com/modal-body
|
||||
{}
|
||||
[:div.space-y-1 {:class "w-[600px] h-[350px] "}
|
||||
(fc/with-field :vendor/default-account
|
||||
(alog/info ::acount-check :a (fc/field-value))
|
||||
(com/validated-field {:label "Default Account"
|
||||
@@ -388,28 +539,52 @@
|
||||
:placeholder "Search..."
|
||||
:url (bidi/path-for ssr-routes/only-routes :account-search)
|
||||
:value (fc/field-value)
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :account/name c))})))]]
|
||||
:content-fn (fn [c] (pull-attr (dc/db conn) :account/name c))})))
|
||||
(fc/with-field :vendor/account-overrides
|
||||
(com/validated-field
|
||||
{:errors (fc/field-errors)
|
||||
:label "Account Overrides"}
|
||||
(com/data-grid {:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {} "Account")
|
||||
(com/data-grid-header {:class "w-16"})]}
|
||||
(fc/cursor-map #(account-override-row %))
|
||||
(com/data-grid-new-row {:colspan 3
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-account-override)
|
||||
:index (count (fc/field-value))}
|
||||
"New override"))))])
|
||||
(com/modal-footer
|
||||
{}
|
||||
[:div.flex.justify-end
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(back-button)
|
||||
(com/validated-save-button {:errors (seq form-errors)
|
||||
:x-ref "next"
|
||||
"@click.prevent" "$dispatch('modalnext'); console.log($el)"}
|
||||
|
||||
:hx-put (hu/url (bidi/path-for ssr-routes/only-routes ::route/validate)
|
||||
{:step "Account"})}
|
||||
"Address"
|
||||
[:div.w-5.h-5 svg/arrow-right])]])
|
||||
(com/stacked-modal-card
|
||||
[:div.w-5.h-5 svg/arrow-right])]])))
|
||||
|
||||
(defn address-modal [{:keys [form-errors entity form-params]}]
|
||||
(com/stacked-modal-card-2
|
||||
3
|
||||
{"@keydown.enter.prevent.stop" "$refs.next.click()"}
|
||||
(com/modal-header
|
||||
{}
|
||||
[:div.flex ;; TODO standardize how these headers are built
|
||||
[:div.p-2 "Address"]
|
||||
[:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
|
||||
[:span {:x-text "vendorName"}]]]
|
||||
[:div.mt-2
|
||||
[:div.space-y-1
|
||||
[:span {:x-text "vendorName"}]]])
|
||||
(com/modal-header-attachment {}
|
||||
(timeline {:active "Address"}))
|
||||
(com/modal-body
|
||||
{}
|
||||
[:div.space-y-1 {:class "w-[600px] h-[350px]"}
|
||||
(fc/with-field :vendor/address
|
||||
[:div.flex.flex-col.w-full
|
||||
(fc/with-field :db/id
|
||||
(com/hidden {:name (fc/field-name)
|
||||
:value (fc/field-value)}))
|
||||
(fc/with-field :address/street1
|
||||
(com/validated-field {:label "Street"
|
||||
:errors (fc/field-errors)}
|
||||
@@ -450,25 +625,36 @@
|
||||
:error? (fc/error?)
|
||||
:placeholder "Suite 300"
|
||||
:class "w-full"
|
||||
:value (fc/field-value)})))]])]]
|
||||
:value (fc/field-value)})))]])])
|
||||
(com/modal-footer
|
||||
{}
|
||||
[:div.flex.justify-end
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(back-button)
|
||||
(com/validated-save-button {:errors (seq form-errors)
|
||||
:x-ref "next"
|
||||
"@click.prevent" "$dispatch('modalnext'); console.log($el)"}
|
||||
:hx-put (hu/url (bidi/path-for ssr-routes/only-routes ::route/validate)
|
||||
{:step "Address"})}
|
||||
|
||||
"Legal Entity"
|
||||
[:div.w-5.h-5 svg/arrow-right])]])
|
||||
(com/stacked-modal-card
|
||||
[:div.w-5.h-5 svg/arrow-right])]])))
|
||||
|
||||
(defn legal-modal [{:keys [form-params entity form-errors]}]
|
||||
(com/stacked-modal-card-2
|
||||
4
|
||||
{"@keydown.enter.prevent.stop" "$refs.next.click()"}
|
||||
(com/modal-header
|
||||
{}
|
||||
[:div.flex
|
||||
[:div.p-2 "Legal Entity Info"]
|
||||
[:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
|
||||
[:span {:x-text "vendorName"}]]]
|
||||
[:div
|
||||
[:span {:x-text "vendorName"}]]])
|
||||
(com/modal-header-attachment {}
|
||||
(timeline {:active "Legal"}))
|
||||
(com/modal-body
|
||||
{}
|
||||
[:div {:class "w-[600px] h-[350px]"}
|
||||
[:div.grid.grid-cols-6.gap-x-4.gap-y-2
|
||||
[:div.col-span-6
|
||||
(fc/with-field :vendor/legal-entity-name
|
||||
@@ -523,23 +709,40 @@
|
||||
(com/select {:name (fc/field-name)
|
||||
:allow-blank? true
|
||||
:value (some-> (fc/field-value) name)
|
||||
:options (ref->select-options "legal-entity-1099-type")})))]]]
|
||||
:options (ref->select-options "legal-entity-1099-type")})))]]])
|
||||
(com/modal-footer
|
||||
{}
|
||||
[:div.flex.justify-end
|
||||
(com/form-errors {:errors (:errors fc/*form-errors*)})
|
||||
[:div.flex.items-baseline.gap-x-4
|
||||
(back-button)
|
||||
(com/validated-save-button {:errors (seq form-errors)
|
||||
:x-ref "next"}
|
||||
"Save vendor")]]))]]))
|
||||
"Save vendor")]])))
|
||||
|
||||
#_(defn new-client-override [{ {:keys [index]} :query-params}]
|
||||
(html-response
|
||||
(fc/start-form-with-prefix
|
||||
[:account/client-overrides (or index 0)]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:new? true}
|
||||
[]
|
||||
(client-override* fc/*current*))))
|
||||
(defn dialog* [{:keys [entity form-params form-errors] :as params}]
|
||||
(alog/peek ::dialog-entity form-params)
|
||||
(fc/start-form form-params form-errors
|
||||
[:div {:x-data (hx/json {"vendorName" (:vendor/name form-params)
|
||||
"showPrintAs" (boolean (not-empty (:vendor/print-as form-params)))
|
||||
"printAs" (:vendor/print-as form-params)})
|
||||
:class "w-full h-full"}
|
||||
[:form#my-form (-> {:hx-ext "response-targets"
|
||||
:hx-swap "outerHTML swap:300ms"
|
||||
:hx-target-400 "#form-errors .error-content"
|
||||
:hx-trigger "submit"
|
||||
:class "h-full w-full"}
|
||||
(assoc (if (:db/id entity)
|
||||
:hx-put
|
||||
:hx-post)
|
||||
(str (bidi/path-for ssr-routes/only-routes ::route/save))))
|
||||
(com/modal
|
||||
{}
|
||||
(info-modal params)
|
||||
(terms-modal params)
|
||||
(account-modal params)
|
||||
(address-modal params)
|
||||
(legal-modal params))]]))
|
||||
|
||||
(def form-schema (mc/schema
|
||||
[:map
|
||||
@@ -548,15 +751,31 @@
|
||||
[:vendor/print-as {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
[:vendor/default-account entity-id]
|
||||
[:vendor/terms {:optional true} [:maybe :int]]
|
||||
[:vendor/hidden {:optional true :default false}
|
||||
[:boolean {:decode/string {:enter #(if (= % "on") true (boolean %))}}]] ;; TODO cant turn off
|
||||
[:vendor/address {:optional true}
|
||||
[:maybe [:map
|
||||
[:vendor/automatically-paid-when-due {:optional true}
|
||||
[:maybe
|
||||
(many-entity {} [:db/id entity-id])]]
|
||||
[:vendor/terms-overrides {:optional true}
|
||||
(many-entity {}
|
||||
[:db/id [:or entity-id temp-id]]
|
||||
[:vendor-terms-override/terms :int]
|
||||
[:vendor-terms-override/client entity-id])]
|
||||
[:vendor/account-overrides {:optional true}
|
||||
(many-entity {}
|
||||
[:db/id [:or entity-id temp-id]]
|
||||
[:vendor-account-override/account entity-id]
|
||||
[:vendor-account-override/client entity-id])]
|
||||
[:vendor/hidden {:default false}
|
||||
[:boolean {:decode/string {:enter #(if (= % "on") true
|
||||
|
||||
(boolean %))}}]]
|
||||
[:vendor/address {:default {}}
|
||||
[:map
|
||||
[:db/id {:default "new-account"} [:or entity-id temp-id]]
|
||||
[:address/street1 {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
[:address/street2 {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
[:address/city {:optional true} [:maybe [:string {:min 2 :decode/string strip}]]]
|
||||
[:address/state {:optional true} [:maybe [:string {:min 2 :max 2 :decode/string strip}]]]
|
||||
[:address/zip {:optional true} [:maybe [:string {:min 5 :max 5 :decode/string strip}]] ]]]]
|
||||
[:address/zip {:optional true} [:maybe [:string {:min 5 :max 5 :decode/string strip}]]]]]
|
||||
[:vendor/legal-entity-tin {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
[:vendor/legal-entity-name {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
[:vendor/legal-entity-first-name {:optional true} [:maybe [:string {:min 3 :decode/string strip}]]]
|
||||
@@ -566,55 +785,131 @@
|
||||
[:vendor/legal-entity-1099-type {:optional true} [:maybe (ref->enum-schema "legal-entity-1099-type")]]]))
|
||||
|
||||
(defn dialog [{:keys [entity form-params form-errors]}]
|
||||
(alog/info ::here :fp entity)
|
||||
(modal-response (dialog* {:entity entity
|
||||
:form-params (or (when (seq form-params)
|
||||
form-params)
|
||||
(when entity
|
||||
(mc/decode form-schema entity main-transformer))
|
||||
{})
|
||||
(mc/decode form-schema {} main-transformer))
|
||||
:form-errors form-errors})))
|
||||
|
||||
(defn terms-dialog [{:keys [entity form-params form-errors]}]
|
||||
(let [form-params (merge {}
|
||||
(when entity
|
||||
(mc/decode form-schema entity main-transformer))
|
||||
(when (seq form-params)
|
||||
form-params))]
|
||||
|
||||
|
||||
(defn new-terms-override [{{:keys [index]} :query-params}]
|
||||
(html-response
|
||||
(fc/start-form-with-prefix
|
||||
[:vendor/terms-overrides (or index 0)]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:new? true}
|
||||
[]
|
||||
(terms-override-row fc/*current*))))
|
||||
|
||||
:headers (-> {}
|
||||
(assoc "hx-trigger-after-settle" "modalnext")
|
||||
(assoc "hx-retarget" ".modal-stack")
|
||||
(assoc "hx-reswap" "beforeend")))))
|
||||
(defn new-automatic-payment [{{:keys [index]} :query-params}]
|
||||
(html-response
|
||||
(fc/start-form-with-prefix
|
||||
[:vendor/automatically-paid-when-due (or index 0)]
|
||||
{:db/id nil
|
||||
:new? true}
|
||||
[]
|
||||
(automatically-paid-when-due-row fc/*current*))))
|
||||
|
||||
(defn new-account-override [{{:keys [index]} :query-params}]
|
||||
(html-response
|
||||
(fc/start-form-with-prefix
|
||||
[:vendor/account-overrides (or index 0)]
|
||||
{:db/id (str (java.util.UUID/randomUUID))
|
||||
:new? true}
|
||||
[]
|
||||
(account-override-row fc/*current*))))
|
||||
|
||||
(defn validate [request]
|
||||
(cond (= (:step (:query-params request))
|
||||
"Info")
|
||||
(schema-enforce-request request
|
||||
:form-schema (mut/select-keys form-schema #{:vendor/name :vendor/print-as}))
|
||||
|
||||
(= (:step (:query-params request))
|
||||
"Terms")
|
||||
(schema-enforce-request request
|
||||
:form-schema (mut/select-keys form-schema #{:vendor/terms :vendor/terms-overrides :vendor/automatically-paid-when-due}))
|
||||
|
||||
(= (:step (:query-params request))
|
||||
"Account")
|
||||
(schema-enforce-request request
|
||||
:form-schema (mut/select-keys form-schema #{:vendor/default-account :vendor/account-overrides}))
|
||||
|
||||
(= (:step (:query-params request))
|
||||
"Address")
|
||||
(schema-enforce-request request
|
||||
:form-schema (mut/select-keys form-schema #{:vendor/address}))
|
||||
|
||||
(= (:step (:query-params request))
|
||||
"Legal")
|
||||
(schema-enforce-request request
|
||||
:form-schema form-schema)
|
||||
|
||||
:else nil)
|
||||
(html-response [:div]
|
||||
:headers {"hx-trigger-after-settle" "modalnext"
|
||||
"hx-reswap" "none"}))
|
||||
|
||||
#_(defn validate-failed [request]
|
||||
(d)
|
||||
(html-response ()
|
||||
:headers {"hx-trigger-after-settle" "modalnext"
|
||||
"hx-reswap" "none"}))
|
||||
|
||||
(defn account-typeahead [{{:keys [name value client-id] :as qp} :query-params}]
|
||||
(html-response (account-typeahead* {:name name
|
||||
:value value
|
||||
:client-id client-id
|
||||
:x-model "accountId"})))
|
||||
|
||||
(def key->handler
|
||||
(apply-middleware-to-all-handlers
|
||||
(->>
|
||||
{::route/page (helper/page-route grid-page)
|
||||
::route/table (helper/table-route grid-page)
|
||||
::route/new nil #_ (-> new-client-override
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]])
|
||||
wrap-admin wrap-client-redirect-unauthenticated)
|
||||
::route/new dialog
|
||||
::route/validate (-> validate
|
||||
(wrap-schema-enforce :query-schema [:map [:step :string]])
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> dialog
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
::route/save (-> save
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (wrap-entity dialog [:form-params :db/id] default-read)))
|
||||
::route/edit (-> dialog
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
|
||||
(wrap-schema-enforce :route-schema [:map [:db/id entity-id]]))
|
||||
::route/edit-terms (-> terms-dialog
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> dialog
|
||||
(wrap-entity [:form-params :db/id] default-read))))
|
||||
#_#_:admin-account-new-dialog account-dialog})
|
||||
::route/new-terms-override (-> new-terms-override
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]]))
|
||||
::route/account-typeahead (-> account-typeahead
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:name :string]
|
||||
[:client-id {:optional true}
|
||||
[:maybe entity-id]]
|
||||
[:value {:optional true}
|
||||
[:maybe entity-id]]]))
|
||||
::route/new-automatic-payment (-> new-automatic-payment
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]]))
|
||||
::route/new-account-override (-> new-account-override
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]]))})
|
||||
(fn [h]
|
||||
(-> h
|
||||
(wrap-admin)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
strip
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
@@ -365,18 +365,18 @@
|
||||
:company-1099-vendor-table vendor-table
|
||||
:company-1099-vendor-dialog (-> vendor-dialog
|
||||
(wrap-entity [:route-params :vendor-id] default-vendor-read)
|
||||
(wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
|
||||
(wrap-schema-enforce :route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]]))
|
||||
:company-1099-vendor-save (-> vendor-save
|
||||
(wrap-entity [:form-params :db/id] default-vendor-read)
|
||||
(wrap-schema-decode :form-schema form-schema
|
||||
(wrap-schema-enforce :form-schema form-schema
|
||||
:route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]])
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (-> vendor-dialog
|
||||
(wrap-entity [:form-params :db/id] default-vendor-read)
|
||||
(wrap-entity [:route-params :vendor-id] default-vendor-read)
|
||||
(wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
|
||||
(wrap-schema-enforce :route-schema [:map [:vendor-id entity-id]]
|
||||
:query-schema [:map [:client-id entity-id]]))))})
|
||||
(fn [h]
|
||||
(-> h
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
(def modal dialog/modal-)
|
||||
(def modal-card dialog/modal-card-)
|
||||
(def stacked-modal-card dialog/stacked-modal-card-)
|
||||
(def stacked-modal-card-2 dialog/stacked-modal-card-2-)
|
||||
(def modal-header dialog/modal-header-)
|
||||
(def modal-header-attachment dialog/modal-header-attachment-)
|
||||
(def modal-body dialog/modal-body-)
|
||||
(def modal-footer dialog/modal-footer-)
|
||||
|
||||
(def text-input inputs/text-input-)
|
||||
(def checkbox inputs/checkbox-)
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
(defn stacked-modal-card- [index params header content footer]
|
||||
[:div (merge params
|
||||
{:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content flex flex-col h-full"
|
||||
{:class (hh/add-class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content flex flex-col h-full" (:class params ""))
|
||||
:x-data (hx/json {:i index})
|
||||
:x-show "index == i && hidingIndex != i"
|
||||
"x-trap" "index == i && hidingIndex == -1 && !transitioning"
|
||||
@@ -67,12 +67,46 @@
|
||||
"x-transition:leave" "transition duration-150",
|
||||
"x-transition:leave-start" "translate-x-0 scale-100 opacity-100",
|
||||
})
|
||||
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
|
||||
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header] ;; todo componentize these
|
||||
[:div {:class "px-6 space-y-6 overflow-y-scroll w-full shrink"}
|
||||
|
||||
content]
|
||||
content] ;; TODO componentize
|
||||
(when footer [:div {:class "p-4"}
|
||||
[:span.items-center.bg-red-100.text-red-800.text-xs.font-medium.mb-2.p-1.rounded-full.inline-flex (hx/alpine-appear {:x-show "unexpectedError" :class "dark:bg-red-900 dark:text-red-300"})
|
||||
[:span {:class "w-2 h-2 bg-red-500 rounded-full"}]
|
||||
[:span.px-2.py-0.5 "An unexpected error has occured. Integreat staff have been notified."]]
|
||||
[:div {:class "shrink-0"}]footer])])
|
||||
|
||||
(defn modal-header- [params & children]
|
||||
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"}
|
||||
children])
|
||||
|
||||
|
||||
(defn modal-header-attachment- [params & children]
|
||||
[:div {:class "flex items-start justify-between p-4 border-b shrink-0"}
|
||||
children])
|
||||
|
||||
(defn modal-body- [params & children]
|
||||
[:div {:class "px-6 py-2 space-y-6 overflow-y-scroll w-full shrink"}
|
||||
children])
|
||||
|
||||
(defn modal-footer- [params & children]
|
||||
[:div {:class "p-4"}
|
||||
[:span.items-center.bg-red-100.text-red-800.text-xs.font-medium.mb-2.p-1.rounded-full.inline-flex (hx/alpine-appear {:x-show "unexpectedError" :class "dark:bg-red-900 dark:text-red-300"})
|
||||
[:span {:class "w-2 h-2 bg-red-500 rounded-full"}]
|
||||
[:span.px-2.py-0.5 "An unexpected error has occured. Integreat staff have been notified."]]
|
||||
[:div {:class "shrink-0"}]
|
||||
children])
|
||||
|
||||
(defn stacked-modal-card-2- [index params & children]
|
||||
[:div (merge params
|
||||
{:class (hh/add-class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content flex flex-col h-full" (:class params ""))
|
||||
:x-data (hx/json {:i index})
|
||||
:x-show "index == i && hidingIndex != i"
|
||||
"x-trap" "index == i && hidingIndex == -1 && !transitioning"
|
||||
"x-transition:enter" "transition duration-150",
|
||||
"x-transition:enter-end" "translate-x-0 scale-100 opacity-100",
|
||||
"x-transition:leave" "transition duration-150",
|
||||
"x-transition:leave-start" "translate-x-0 scale-100 opacity-100",
|
||||
})
|
||||
children])
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
[:input
|
||||
(-> params
|
||||
(dissoc :error?)
|
||||
(assoc :type "text")
|
||||
(assoc :type "text" :autocomplete "off")
|
||||
(update
|
||||
:class #(-> ""
|
||||
(hh/add-class default-input-classes)
|
||||
|
||||
28
src/clj/auto_ap/ssr/components/timeline.clj
Normal file
28
src/clj/auto_ap/ssr/components/timeline.clj
Normal file
@@ -0,0 +1,28 @@
|
||||
(ns auto-ap.ssr.components.timeline
|
||||
(:require [auto-ap.ssr.hiccup-helper :as hh]))
|
||||
|
||||
(defn timeline-step [{:keys [active? visited? last?]} & children]
|
||||
(if active?
|
||||
[:li {:class "flex items-center text-primary-600 font-medium dark:text-primary-500"}
|
||||
[:span {:class "flex items-center justify-center w-5 h-5 mr-2 text-xs border-2 border-primary-600 rounded-full shrink-0 dark:border-primary-500"} ]
|
||||
children
|
||||
(when-not last?
|
||||
[:svg {:class "w-3 h-3 ml-2 sm:ml-4", :aria-hidden "true", :xmlns "http://www.w3.org/2000/svg", :fill "none", :viewbox "0 0 12 10"}
|
||||
[:path {:stroke "currentColor", :stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "m7 9 4-4-4-4M1 9l4-4-4-4"}]])]
|
||||
[:li {:class (cond-> "flex items-center"
|
||||
(not visited?) (hh/add-class "text-gray-400"))}
|
||||
[:span {:class "flex items-center justify-center w-5 h-5 mr-2 text-xs border border-gray-500 rounded-full shrink-0 dark:border-gray-400"}
|
||||
(when visited?
|
||||
[:svg {:class "w-3 h-3 text-primary-600 dark:text-primary-500", :aria-hidden "true", :xmlns "http://www.w3.org/2000/svg", :fill "none", :viewbox "0 0 16 12"}
|
||||
[:path {:stroke "currentColor", :stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "M1 5.917 5.724 10.5 15 1.5"}]])]
|
||||
children
|
||||
(when-not last?
|
||||
[:svg {:class "w-3 h-3 ml-2 sm:ml-4", :aria-hidden "true", :xmlns "http://www.w3.org/2000/svg", :fill "none", :viewbox "0 0 12 10"}
|
||||
[:path {:stroke "currentColor", :stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "m7 9 4-4-4-4M1 9l4-4-4-4"}]])]))
|
||||
|
||||
(defn timeline [params & children]
|
||||
[:ol {:class "flex items-center w-full space-x-2 text-xs text-center text-gray-500 bg-white dark:text-gray-400 sm:text-base dark:bg-gray-800 sm:space-x-4 px-2"}
|
||||
children
|
||||
#_[:li {:class "flex items-center"}
|
||||
[:span {:class "flex items-center justify-center w-5 h-5 mr-2 text-xs border border-gray-500 rounded-full shrink-0 dark:border-gray-400"} ]]])
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
ref->select-options
|
||||
wrap-entity
|
||||
wrap-form-4xx-2
|
||||
wrap-schema-decode]]
|
||||
wrap-schema-enforce]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[buddy.sign.jwt :as jwt]
|
||||
@@ -375,20 +375,20 @@
|
||||
:user-table (helper/table-route grid-page)
|
||||
:user-edit-save (-> user-edit-save
|
||||
(wrap-entity [:form-params :db/id] default-read)
|
||||
(wrap-schema-decode :form-schema form-schema)
|
||||
(wrap-schema-enforce :form-schema form-schema)
|
||||
(wrap-nested-form-params)
|
||||
(wrap-form-4xx-2 (wrap-entity user-dialog [:form-params :db/id] default-read)))
|
||||
:user-client-new (-> new-client
|
||||
(wrap-schema-decode :query-schema [:map
|
||||
(wrap-schema-enforce :query-schema [:map
|
||||
[:index {:optional true
|
||||
:default 0} [nat-int? {:default 0}]]]))
|
||||
:user-edit-dialog (-> user-dialog
|
||||
(wrap-entity [:route-params :db/id] default-read)
|
||||
(wrap-schema-decode
|
||||
(wrap-schema-enforce
|
||||
:route-schema (mc/schema [:map [:db/id entity-id]])))
|
||||
:user-impersonate (-> impersonate
|
||||
(wrap-entity [:params :db/id] default-read)
|
||||
(wrap-schema-decode
|
||||
(wrap-schema-enforce
|
||||
:params-schema (mc/schema [:map [:db/id entity-id]])))}
|
||||
(fn [h]
|
||||
(-> h
|
||||
|
||||
@@ -174,8 +174,7 @@
|
||||
:else
|
||||
s))
|
||||
|
||||
(defn wrap-schema-decode [handler & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||
(fn [{:keys [form-params query-params params] :as request}]
|
||||
(defn schema-enforce-request [{:keys [form-params query-params params] :as request} & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||
(let [request (try
|
||||
(cond-> request
|
||||
(and (:params request) params-schema)
|
||||
@@ -222,7 +221,55 @@
|
||||
{:type :schema-validation
|
||||
:decoded (:value (:data (ex-data e)))
|
||||
:error (:data (ex-data e))}))))]
|
||||
(handler request))))
|
||||
request))
|
||||
|
||||
(defn wrap-schema-enforce [handler & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||
(fn [request]
|
||||
(handler (schema-enforce-request request
|
||||
:form-schema form-schema
|
||||
:query-schema query-schema
|
||||
:route-schema route-schema
|
||||
:params-schema params-schema))))
|
||||
|
||||
|
||||
(defn schema-decode-request [{:keys [form-params query-params params] :as request} & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||
(let [request (cond-> request
|
||||
(and (:params request) params-schema)
|
||||
(assoc :params
|
||||
(mc/decode
|
||||
params-schema
|
||||
(:params request)
|
||||
main-transformer))
|
||||
|
||||
(and (:route-params request) route-schema)
|
||||
(assoc :route-params
|
||||
(mc/decode
|
||||
route-schema
|
||||
(:route-params request)
|
||||
main-transformer))
|
||||
|
||||
(and form-schema form-params)
|
||||
(assoc :form-params
|
||||
(mc/decode
|
||||
form-schema
|
||||
form-params
|
||||
main-transformer))
|
||||
|
||||
(and query-schema query-params)
|
||||
(assoc :query-params
|
||||
(mc/decode
|
||||
query-schema
|
||||
query-params
|
||||
main-transformer)))]
|
||||
request))
|
||||
|
||||
(defn wrap-schema-decode [handler & {:keys [form-schema query-schema route-schema params-schema]}]
|
||||
(fn [request]
|
||||
(handler (schema-decode-request request
|
||||
:form-schema form-schema
|
||||
:query-schema query-schema
|
||||
:route-schema route-schema
|
||||
:params-schema params-schema))))
|
||||
|
||||
(defn ref->enum-schema [n]
|
||||
(into [:enum {:decode/string #(if (keyword? %)
|
||||
|
||||
@@ -38,7 +38,14 @@
|
||||
"")
|
||||
(:user-name item)
|
||||
)
|
||||
(puget/cprint (reduce
|
||||
(println (reduce
|
||||
(fn [acc [k v]]
|
||||
(assoc acc k v))
|
||||
{}
|
||||
(dissoc
|
||||
item
|
||||
:user)))
|
||||
#_(puget/cprint (reduce
|
||||
(fn [acc [k v]]
|
||||
(assoc acc k v))
|
||||
{}
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
:put ::save
|
||||
:post ::save}
|
||||
"/table" ::table
|
||||
"/terms" ::edit-terms
|
||||
"/terms/override" ::new-terms-override
|
||||
"/automatic-payment" ::new-automatic-payment
|
||||
"/account-override" ::new-account-override
|
||||
"/account-typeahead" ::account-typeahead
|
||||
"/validate" ::validate
|
||||
"/new" {:get ::new}
|
||||
["/" [#"\d+" :db/id] "/edit"] {:get ::edit
|
||||
}})
|
||||
|
||||
Reference in New Issue
Block a user