improved two major forms.
This commit is contained in:
@@ -142,10 +142,6 @@
|
||||
(re-frame/reg-event-fx
|
||||
::set-active-route
|
||||
(fn [{:keys [db]} [_ handler params route-params]]
|
||||
(println "HANDELR IS" handler (:user db))
|
||||
|
||||
|
||||
|
||||
(cond
|
||||
(and (not= :login handler) (not (:user db)))
|
||||
{:redirect (bidi/path-for routes/routes :login)
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
[auto-ap.forms :as forms]
|
||||
[auto-ap.status :as status]
|
||||
[malli.core :as m]
|
||||
[malli.error :as me]))
|
||||
[malli.error :as me]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defonce ^js/React.Context form-context (react/createContext "default"))
|
||||
(def ^js/React.Provider Provider (. form-context -Provider))
|
||||
@@ -161,7 +162,9 @@
|
||||
[:div
|
||||
[:p.help.has-text-danger error-message]]))))]))])
|
||||
|
||||
(defn raw-field-v2 [{:keys [field]}]
|
||||
(defn raw-field-v2 [{:keys [field] :as props}]
|
||||
(when-not field
|
||||
(throw (ex-info (str "Missing field") (clj->js {:props props}))))
|
||||
(let [[child] (r/children (r/current-component))]
|
||||
[:> Consumer {}
|
||||
(fn [consume-form]
|
||||
@@ -188,7 +191,6 @@
|
||||
(if on-change
|
||||
(partial form-change-handler (aget consume-form "data") full-field-path (aget consume-form "on-change"))
|
||||
(partial change-handler full-field-path (aget consume-form "change-event")))
|
||||
|
||||
:on-blur (partial blur-handler full-field-path (aget consume-form "blur-event"))
|
||||
:value value)
|
||||
(update :class (fn [class]
|
||||
@@ -198,8 +200,12 @@
|
||||
""
|
||||
(not (valid-field? (aget consume-form "problems") full-field-path))
|
||||
" is-danger"
|
||||
|
||||
value
|
||||
"is-success"
|
||||
|
||||
:else
|
||||
"is-success"))))))))))]))]))
|
||||
""))))))))))]))]))
|
||||
|
||||
(defn with-scope [{:keys [scope]}]
|
||||
(r/create-element FormScopeProvider #js {:value scope}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
(def money (m/schema [float? {:error/message "Invalid money"}]))
|
||||
(def not-empty-string (m/schema [:re {:error/message "Required"} #"\S+"]))
|
||||
(def keyword (m/schema [:fn (fn [d]
|
||||
(keyword? d))]))
|
||||
|
||||
(def expense-account (m/schema [:map
|
||||
[:id :string]
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
(when (:user db)
|
||||
(sort-by :name (vals (:clients db))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::client-refs
|
||||
:<- [::clients]
|
||||
(fn [c]
|
||||
(map #(select-keys % [:id :name]) c)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::all-accounts
|
||||
(fn [db]
|
||||
|
||||
34
src/cljs/auto_ap/views/components.cljs
Normal file
34
src/cljs/auto_ap/views/components.cljs
Normal file
@@ -0,0 +1,34 @@
|
||||
(ns auto-ap.views.components
|
||||
(:require [reagent.core :as r]
|
||||
[clojure.string :as str]))
|
||||
|
||||
|
||||
(defn checkbox [{:keys [on-change
|
||||
value
|
||||
label]
|
||||
:as props}]
|
||||
(into [:label.checkbox
|
||||
[:input (-> props
|
||||
(assoc
|
||||
:type "checkbox"
|
||||
:on-change (fn []
|
||||
(on-change (not value)))
|
||||
:checked value)
|
||||
(dissoc :value))]
|
||||
" " label
|
||||
]
|
||||
(r/children (r/current-component))))
|
||||
|
||||
(defn select-field [{:keys [options allow-nil? class] :as props}]
|
||||
[:div.select {:class class}
|
||||
[:select (-> props
|
||||
(dissoc :allow-nil? :class :options)
|
||||
(update :value (fn [v]
|
||||
(if (str/blank? v)
|
||||
""
|
||||
v))))
|
||||
[:<>
|
||||
(when allow-nil?
|
||||
[:option {:value nil}])
|
||||
(for [[k v] options]
|
||||
^{:key k} [:option {:value k} v])]]])
|
||||
@@ -1,108 +1,34 @@
|
||||
(ns auto-ap.views.components.address
|
||||
(:require [auto-ap.entities.address :as address]
|
||||
[auto-ap.views.utils :refer [dispatch-value-change dispatch-event bind-field horizontal-field]]
|
||||
[auto-ap.forms.builder :as form-builder]))
|
||||
[auto-ap.forms.builder :as form-builder]
|
||||
[auto-ap.views.components.level :as level]))
|
||||
|
||||
(defn address-field [{:keys [event field subscription]}]
|
||||
[:span
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "Address"]
|
||||
[bind-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:field (conj field :street1)
|
||||
:spec ::address/street1
|
||||
:event event
|
||||
:subscription subscription}]]]]
|
||||
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[bind-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "Suite 400"
|
||||
:field (conj field :street2)
|
||||
:spec ::address/street2
|
||||
:event event
|
||||
:subscription subscription}]]]]
|
||||
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "City"]
|
||||
[bind-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "Cupertino"
|
||||
:field (conj field :city)
|
||||
:spec ::address/city
|
||||
:event event
|
||||
:subscription subscription}]]]
|
||||
[:div.control
|
||||
[:p.help "State"]
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
:placeholder "CA"
|
||||
:field (conj field :state)
|
||||
:spec ::address/state
|
||||
:size 2
|
||||
:max-length "2"
|
||||
:event event
|
||||
:subscription subscription}]]]
|
||||
[:div.control
|
||||
[:p.help "Zip"]
|
||||
[bind-field
|
||||
[:input.input {:type "text"
|
||||
:field (conj field :zip)
|
||||
:spec ::address/zip
|
||||
:event event
|
||||
:subscription subscription
|
||||
:placeholder "95014"}]]]]])
|
||||
|
||||
(defn address2-field []
|
||||
[:span
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
(defn address2-field [{:keys [value on-change]}]
|
||||
[form-builder/virtual-builder {:value (or value {})
|
||||
:on-change on-change}
|
||||
[:div
|
||||
[form-builder/field-v2 {:field :street1}
|
||||
[:p.help "Street Address"]
|
||||
[form-builder/raw-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:field [:street1]
|
||||
:spec ::address/street1}]]]]
|
||||
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[form-builder/raw-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "Suite 400"
|
||||
:field [:street2]
|
||||
:spec ::address/street2}]]]]
|
||||
|
||||
[horizontal-field
|
||||
nil
|
||||
[:div.control
|
||||
[:p.help "City"]
|
||||
[form-builder/raw-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "1700 Pennsylvania Ave"}]]
|
||||
[form-builder/raw-field-v2 {:field :street2}
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "Suite 400"}]]
|
||||
[level/left-stack
|
||||
[form-builder/field-v2 {:field :city}
|
||||
[:p.help "City"]
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:placeholder "Cupertino"
|
||||
:field [:city]
|
||||
:spec ::address/city}]]]
|
||||
[:div.control
|
||||
[:p.help "State"]
|
||||
[form-builder/raw-field
|
||||
[:input.input {:type "text"
|
||||
:placeholder "CA"
|
||||
:field [:state]
|
||||
:spec ::address/state
|
||||
:size 2
|
||||
:max-length "2"}]]]
|
||||
[:div.control
|
||||
[:p.help "Zip"]
|
||||
[form-builder/raw-field
|
||||
[:input.input {:type "text"
|
||||
:field [:zip]
|
||||
:spec ::address/zip
|
||||
:placeholder "95014"}]]]]])
|
||||
:field [:city]
|
||||
:spec ::address/city}]]
|
||||
[form-builder/field-v2 {:field :state}
|
||||
[:p.help "State"]
|
||||
[:input.input {:type "text"
|
||||
:placeholder "CA"
|
||||
:size 2
|
||||
:max-length "2"}]]
|
||||
[form-builder/field-v2 {:field :zip}
|
||||
[:p.help "Zip"]
|
||||
[:input.input {:type "text"
|
||||
:placeholder "95014"}]]]]])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns auto-ap.views.components.bank-account-filter
|
||||
(:require
|
||||
[auto-ap.views.utils :refer [->$]]
|
||||
[auto-ap.subs :as subs]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
|
||||
68
src/cljs/auto_ap/views/components/multi.cljs
Normal file
68
src/cljs/auto_ap/views/components/multi.cljs
Normal file
@@ -0,0 +1,68 @@
|
||||
(ns auto-ap.views.components.multi
|
||||
(:require
|
||||
[cemerick.url]
|
||||
#_{:clj-kondo/ignore [:unused-namespace]}
|
||||
[reagent.core :as reagent]
|
||||
[react :as react]
|
||||
[auto-ap.entities.shared :as shared]
|
||||
[auto-ap.views.utils :refer [appearing-group]]
|
||||
[auto-ap.forms.builder :as form-builder]))
|
||||
|
||||
|
||||
(defn multi-field-v2-internal [{:keys [template key-fn next-key allow-change? disable-new? disable-remove? schema on-change disabled new-text] prop-value :value :as props} ]
|
||||
(let [prop-value (if (seq prop-value)
|
||||
prop-value
|
||||
[])]
|
||||
[form-builder/virtual-builder {:value prop-value
|
||||
:schema schema
|
||||
:on-change on-change}
|
||||
[:fieldset {:disabled disabled}
|
||||
[:div {:style {:margin-bottom "0.25em"}}
|
||||
(into [appearing-group]
|
||||
(for [[i override] (map vector (range) prop-value)
|
||||
:let [is-disabled? (if (= false allow-change?)
|
||||
(not (boolean (::new? override)))
|
||||
nil)]]
|
||||
|
||||
^{:key (or (key-fn override)
|
||||
(::key override))}
|
||||
[form-builder/with-scope {:scope [i]}
|
||||
^{:key (or (key-fn override)
|
||||
(::key override))}
|
||||
[:div.level {:style {:margin-bottom "0.25em"}}
|
||||
[:div.level-left {:style {:padding "0.5em 1em"}
|
||||
:class (when-not (key-fn override)
|
||||
"has-background-info-light")}
|
||||
(let [template (if (fn? template)
|
||||
(template override)
|
||||
template)]
|
||||
(for [[idx template] (map vector (range ) template)]
|
||||
^{:key idx}
|
||||
[:div.level-item
|
||||
template]))
|
||||
(when-not disable-remove?
|
||||
[:div.level-item
|
||||
[:a.button.level-item
|
||||
{:disabled is-disabled?
|
||||
:on-click (fn []
|
||||
(on-change (into []
|
||||
(for [[idx item] (map vector (range) prop-value)
|
||||
:when (not= idx i)]
|
||||
item))))}
|
||||
[:span.icon [:span.icon-remove]]]])]]]))
|
||||
(when-not disable-new?
|
||||
[:button.button.is-outline
|
||||
{:type "button"
|
||||
:on-click (fn [e]
|
||||
(on-change (conj prop-value {::key next-key}))
|
||||
(.stopPropagation e)
|
||||
(.preventDefault e))}
|
||||
[:span.icon [:i.fa.fa-plus]]
|
||||
[:span (or new-text "New")]])]]]))
|
||||
|
||||
|
||||
(defn multi-field-v2 []
|
||||
(into
|
||||
[:f> multi-field-v2-internal
|
||||
(reagent/props (reagent/current-component))]
|
||||
(reagent/children (reagent/current-component))))
|
||||
43
src/cljs/auto_ap/views/components/number.cljs
Normal file
43
src/cljs/auto_ap/views/components/number.cljs
Normal file
@@ -0,0 +1,43 @@
|
||||
(ns auto-ap.views.components.number
|
||||
(:require [react :as react]
|
||||
[reagent.core :as r]))
|
||||
|
||||
|
||||
(defn number-internal [props]
|
||||
|
||||
(let [[text set-text ] (react/useState (some-> props :value str))
|
||||
[value set-value ] (react/useState (some-> props :value))
|
||||
coerce-value (fn [new-value]
|
||||
(let [new-value (js/parseInt new-value)]
|
||||
(cond
|
||||
(nil? new-value)
|
||||
nil
|
||||
|
||||
(js/Number.isNaN new-value)
|
||||
nil
|
||||
|
||||
:else
|
||||
new-value)))]
|
||||
(react/useEffect (fn []
|
||||
(let [prop-value (:value props)]
|
||||
(when (not (= prop-value value))
|
||||
(set-value prop-value)
|
||||
(if prop-value
|
||||
(set-text (str prop-value))
|
||||
(set-text ""))))))
|
||||
[:div.field.has-addons
|
||||
[:div.control
|
||||
[:input.input (assoc props
|
||||
:on-change (fn [e]
|
||||
((:on-change props)
|
||||
(coerce-value (.. e -target -value))))
|
||||
:value text
|
||||
:type "number"
|
||||
:step "1"
|
||||
:style {:width "5em"}
|
||||
:size 3)]]]))
|
||||
|
||||
(defn number-input []
|
||||
[:f> number-internal
|
||||
(r/props (r/current-component))])
|
||||
|
||||
@@ -7,26 +7,76 @@
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.views.components.level :refer [left-stack]]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components :as com]
|
||||
[auto-ap.views.components.address :refer [address2-field]]
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[auto-ap.views.components.number :refer [number-input]]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
||||
[auto-ap.views.components.typeahead.vendor
|
||||
:refer [search-backed-typeahead]]
|
||||
[auto-ap.views.pages.admin.vendors.common :as common]
|
||||
[auto-ap.views.components.multi :refer [multi-field-v2]]
|
||||
[auto-ap.views.utils
|
||||
:refer [dispatch-event multi-field str->int with-is-admin? with-user]]
|
||||
[clojure.spec.alpha :as s]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]))
|
||||
[reagent.core :as r]
|
||||
[malli.core :as m]
|
||||
[auto-ap.schema :as schema]
|
||||
[malli.error :as me]))
|
||||
|
||||
;; Remaining cleanup todos:
|
||||
;; test minification
|
||||
|
||||
(def terms-override-schema (m/schema [:map
|
||||
[:client schema/reference]
|
||||
[:terms :int]]))
|
||||
|
||||
(def automatically-paid-schema (m/schema [:map
|
||||
[:client schema/reference]]))
|
||||
|
||||
(def schedule-payment-dom-schema (m/schema [:map
|
||||
[:client schema/reference]
|
||||
[:dom [:int {:max 30}]]]))
|
||||
|
||||
(def account-override-schema (m/schema [:map
|
||||
[:client schema/reference]
|
||||
[:account schema/reference]]))
|
||||
|
||||
(def schema (m/schema [:map [:name schema/not-empty-string]
|
||||
[:print-as {:optional true}
|
||||
[:maybe :string]]
|
||||
[:hidden {:optional true}
|
||||
[:maybe :boolean]]
|
||||
[:terms {:optional true}
|
||||
[:maybe :int]]
|
||||
[:terms-overrides {:optional true}
|
||||
[:maybe [:sequential terms-override-schema]]]
|
||||
[:schedule-payment-dom {:optional true}
|
||||
[:maybe [:sequential schedule-payment-dom-schema]]]
|
||||
[:default-account schema/reference]
|
||||
[:account-overrides {:optional true}
|
||||
[:sequential account-override-schema]]
|
||||
[:legal-entity-first-name {:optional true}
|
||||
[:maybe :string]]
|
||||
[:legal-entity-middle-name {:optional true}
|
||||
[:maybe :string]]
|
||||
[:legal-entity-last-name {:optional true}
|
||||
[:maybe :string]]
|
||||
[:legal-entity-tin {:optional true}
|
||||
[:maybe :string]]
|
||||
[:legal-entity-tin-type {:optional true}
|
||||
[:or [:maybe :string]
|
||||
[:maybe keyword?]]]
|
||||
[:legal-entity-1099-type {:optional true}
|
||||
[:or [:maybe :string]
|
||||
[:maybe keyword?]]]]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::can-submit
|
||||
:<- [::forms/form ::vendor-form]
|
||||
(fn [form]
|
||||
(s/valid? ::entity/vendor (:data form))))
|
||||
(m/validate schema (:data form))))
|
||||
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
@@ -39,56 +89,55 @@
|
||||
::save
|
||||
[with-user with-is-admin? (forms/triggers-loading ::vendor-form) (forms/in-form ::vendor-form)]
|
||||
(fn [{:keys [user is-admin?] {{:keys [name hidden print-as terms invoice-reminder-schedule primary-contact automatically-paid-when-due schedule-payment-dom secondary-contact address default-account terms-overrides account-overrides id legal-entity-tin legal-entity-tin-type legal-entity-first-name legal-entity-last-name legal-entity-middle-name legal-entity-1099-type] :as data} :data} :db} _]
|
||||
(when (s/valid? ::entity/vendor data)
|
||||
(let [query [:upsert-vendor
|
||||
{:vendor (cond-> {:id id
|
||||
:name name
|
||||
:print-as print-as
|
||||
:terms (or (str->int terms)
|
||||
(let [query [:upsert-vendor
|
||||
{:vendor (cond-> {:id id
|
||||
:name name
|
||||
:print-as print-as
|
||||
:terms (or terms
|
||||
nil)
|
||||
:default-account-id (:id default-account)
|
||||
:address address
|
||||
:primary-contact primary-contact
|
||||
:secondary-contact secondary-contact
|
||||
:invoice-reminder-schedule invoice-reminder-schedule}
|
||||
is-admin? (assoc :hidden hidden
|
||||
:terms-overrides (mapv
|
||||
(fn [{:keys [client terms id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:terms (or (str->int terms) 0)})
|
||||
terms-overrides)
|
||||
:account-overrides (mapv
|
||||
(fn [{:keys [client account id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:account-id (:id account)})
|
||||
account-overrides)
|
||||
:schedule-payment-dom (mapv
|
||||
(fn [{:keys [client dom id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:dom (or (str->int dom)
|
||||
0)})
|
||||
schedule-payment-dom)
|
||||
:automatically-paid-when-due (mapv
|
||||
(comp :id :client)
|
||||
automatically-paid-when-due)
|
||||
:legal-entity-first-name legal-entity-first-name
|
||||
:legal-entity-middle-name legal-entity-middle-name
|
||||
:legal-entity-last-name legal-entity-last-name
|
||||
:legal-entity-tin legal-entity-tin
|
||||
:legal-entity-tin-type (some-> legal-entity-tin-type clojure.core/name not-empty keyword)
|
||||
:legal-entity-1099-type (some-> legal-entity-1099-type clojure.core/name not-empty keyword)
|
||||
))}
|
||||
common/default-read]]
|
||||
{ :graphql
|
||||
{:token user
|
||||
:owns-state {:single ::vendor-form}
|
||||
:query-obj {:venia/operation
|
||||
{:operation/type :mutation
|
||||
:operation/name "UpsertVendor"} :venia/queries [{:query/data query}]}
|
||||
:on-success [::save-complete]}}))))
|
||||
:default-account-id (:id default-account)
|
||||
:address address
|
||||
:primary-contact primary-contact
|
||||
:secondary-contact secondary-contact
|
||||
:invoice-reminder-schedule invoice-reminder-schedule}
|
||||
is-admin? (assoc :hidden hidden
|
||||
:terms-overrides (mapv
|
||||
(fn [{:keys [client terms id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:terms (or (str->int terms) 0)})
|
||||
terms-overrides)
|
||||
:account-overrides (mapv
|
||||
(fn [{:keys [client account id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:account-id (:id account)})
|
||||
account-overrides)
|
||||
:schedule-payment-dom (mapv
|
||||
(fn [{:keys [client dom id]}]
|
||||
{:id id
|
||||
:client-id (:id client)
|
||||
:dom (or (str->int dom)
|
||||
0)})
|
||||
schedule-payment-dom)
|
||||
:automatically-paid-when-due (mapv
|
||||
(comp :id :client)
|
||||
automatically-paid-when-due)
|
||||
:legal-entity-first-name legal-entity-first-name
|
||||
:legal-entity-middle-name legal-entity-middle-name
|
||||
:legal-entity-last-name legal-entity-last-name
|
||||
:legal-entity-tin legal-entity-tin
|
||||
:legal-entity-tin-type (some-> legal-entity-tin-type clojure.core/name not-empty keyword)
|
||||
:legal-entity-1099-type (some-> legal-entity-1099-type clojure.core/name not-empty keyword)
|
||||
))}
|
||||
common/default-read]]
|
||||
{ :graphql
|
||||
{:token user
|
||||
:owns-state {:single ::vendor-form}
|
||||
:query-obj {:venia/operation
|
||||
{:operation/type :mutation
|
||||
:operation/name "UpsertVendor"} :venia/queries [{:query/data query}]}
|
||||
:on-success [::save-complete]}})))
|
||||
|
||||
(defn pull-left []
|
||||
(into [:div {:style {:position "relative"
|
||||
@@ -103,10 +152,8 @@
|
||||
[form-builder/vertical-control {:is-small? true}
|
||||
"Name"
|
||||
[:div.control.has-icons-left
|
||||
[form-builder/raw-field
|
||||
[:input.input.is-expanded {:type "text"
|
||||
:field :name
|
||||
:spec ::contact/name}]]
|
||||
[form-builder/raw-field-v2 {:field :name}
|
||||
[:input.input.is-expanded {:type "text"}]]
|
||||
[:span.icon.is-small.is-left
|
||||
[:i.fa.fa-user]]]]
|
||||
[form-builder/vertical-control {:is-small? true}
|
||||
@@ -115,137 +162,118 @@
|
||||
[:div.control.has-icons-left
|
||||
[:span.icon.is-small.is-left
|
||||
[:i.fa.fa-envelope]]
|
||||
[form-builder/raw-field
|
||||
[:input.input {:type "email"
|
||||
:field :email
|
||||
:spec ::contact/email}]]]]
|
||||
[form-builder/raw-field-v2 {:field :email}
|
||||
[:input.input {:type "email"}]]]]
|
||||
[form-builder/vertical-control {:is-small? true}
|
||||
"Phone"
|
||||
[:div.control.has-icons-left
|
||||
[form-builder/raw-field
|
||||
[:input.input {:type "phone"
|
||||
:field :phone
|
||||
:spec ::contact/phone}]]
|
||||
[form-builder/raw-field-v2 {:field :phone}
|
||||
[:input.input {:type "phone"}]]
|
||||
[:span.icon.is-small.is-left
|
||||
[:i.fa.fa-phone]]]]]]])
|
||||
|
||||
|
||||
|
||||
(defn form-content [{:keys [data]}]
|
||||
(let [is-admin? @(re-frame/subscribe [::subs/is-admin?])
|
||||
clients @(re-frame/subscribe [::subs/clients])]
|
||||
clients @(re-frame/subscribe [::subs/client-refs])]
|
||||
[form-builder/builder {:submit-event [::save]
|
||||
:can-submit [::can-submit]
|
||||
:id ::vendor-form}
|
||||
[form-builder/field
|
||||
[:span "Name " [:span.has-text-danger "*"]]
|
||||
[:input.input {:type "text"
|
||||
:auto-focus true
|
||||
:field :name
|
||||
:spec ::entity/name}]]
|
||||
:id ::vendor-form
|
||||
:schema schema}
|
||||
[form-builder/field-v2 {:field :name
|
||||
:required true}
|
||||
"Name"
|
||||
[:input.input {:auto-focus true}]]
|
||||
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :print-as}
|
||||
"Print Checks As"
|
||||
[:input.input {:type "text"
|
||||
:field :print-as
|
||||
:spec ::entity/print-as}]]
|
||||
[:input.input]]
|
||||
(when is-admin?
|
||||
[:div.field
|
||||
[:label.checkbox
|
||||
[form-builder/raw-field
|
||||
[:input {:type "checkbox"
|
||||
:field [:hidden]
|
||||
:spec ::entity/hidden}]]
|
||||
" Hidden"]])
|
||||
[form-builder/raw-field-v2 {:field :hidden}
|
||||
[com/checkbox {:label "Hidden"}]])
|
||||
|
||||
[form-builder/section {:title "Terms"}
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :terms}
|
||||
"Terms"
|
||||
[:input.input {:type "number"
|
||||
:step "1"
|
||||
:style {:width "4em"}
|
||||
:field [:terms]
|
||||
:size 3
|
||||
:spec ::entity/terms}]]
|
||||
[number-input ]]
|
||||
(when is-admin?
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field [:terms-overrides]}
|
||||
"Overrides"
|
||||
[multi-field {:type "multi-field"
|
||||
:field [:terms-overrides]
|
||||
:template [[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}
|
||||
:type "typeahead-v3"
|
||||
:field [:client]}]
|
||||
[:input.input {:type "number"
|
||||
:step "1"
|
||||
:style {:width "4em"}
|
||||
:field [:terms]
|
||||
:size 3
|
||||
:spec ::entity/terms}]]}]])
|
||||
]
|
||||
[multi-field-v2 {:template [[form-builder/raw-field-v2 {:field [:client]}
|
||||
[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}
|
||||
:type "typeahead-v3"
|
||||
}]]
|
||||
[form-builder/raw-field-v2 {:field :terms}
|
||||
[number-input]]]
|
||||
:schema [:sequential terms-override-schema]
|
||||
:key-fn :id
|
||||
:next-key (random-uuid)
|
||||
:new-text "New Terms Override"}]])]
|
||||
|
||||
(when is-admin?
|
||||
[form-builder/section {:title "Schedule payment when due"}
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field [:automatically-paid-when-due]}
|
||||
"Client"
|
||||
[multi-field {:type "multi-field"
|
||||
:field [:automatically-paid-when-due]
|
||||
:template [[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}
|
||||
:type "typeahead-v3"
|
||||
:field [:client]}]]}]]])
|
||||
[multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client}
|
||||
[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}}]]]
|
||||
:schema [:sequential automatically-paid-schema]
|
||||
:key-fn :id
|
||||
:next-key (random-uuid)
|
||||
:new-text "Schedule another client"}]]])
|
||||
|
||||
(when is-admin?
|
||||
[form-builder/section {:title "Schedule payment on day of month"}
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field [:schedule-payment-dom]}
|
||||
"Overrides"
|
||||
[multi-field {:type "multi-field"
|
||||
:field [:schedule-payment-dom]
|
||||
:template [[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}
|
||||
:type "typeahead-v3"
|
||||
:field [:client]}]
|
||||
[:input.input {:type "number"
|
||||
:step "1"
|
||||
:style {:width "4em"}
|
||||
:field [:dom]
|
||||
:size 3
|
||||
:spec ::entity/terms}]]}]]])
|
||||
[multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client}
|
||||
[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "13em"}}]]
|
||||
[form-builder/raw-field-v2 {:field :dom}
|
||||
[number-input]]]
|
||||
:schema [:sequential schedule-payment-dom-schema]
|
||||
:key-fn :id
|
||||
:next-key (random-uuid)
|
||||
:new-text "Schedule another client"}]]])
|
||||
[form-builder/section {:title "Expense Accounts"}
|
||||
[form-builder/field
|
||||
"Default *"
|
||||
[form-builder/field-v2 {:field :default-account
|
||||
:required? true}
|
||||
"Default"
|
||||
[search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_account
|
||||
{:query i}
|
||||
[:name :id]])
|
||||
:type "typeahead-v3"
|
||||
:style {:width "19em"}
|
||||
:field [:default-account]}]]
|
||||
:style {:width "19em"}}]]
|
||||
|
||||
(when is-admin?
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field [:account-overrides]}
|
||||
"Overrides"
|
||||
[multi-field {:type "multi-field"
|
||||
:field [:account-overrides]
|
||||
:template (fn [entity]
|
||||
[[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "19em"}
|
||||
:type "typeahead-v3"
|
||||
:field [:client]}]
|
||||
[search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_account
|
||||
{:query i
|
||||
:client_id (:id (:client entity))}
|
||||
[:name :id]])
|
||||
:type "typeahead-v3"
|
||||
:style {:width "15em"}
|
||||
:field [:account]}]])}]])]
|
||||
[multi-field-v2 {:template (fn [entity]
|
||||
[[form-builder/raw-field-v2 {:field :client}
|
||||
[typeahead-v3 {:entities clients
|
||||
:entity->text :name
|
||||
:style {:width "19em"}
|
||||
}]]
|
||||
[form-builder/raw-field-v2 {:field :account}
|
||||
[search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_account
|
||||
{:query i
|
||||
:client_id (:id (:client entity))}
|
||||
[:name :id]])
|
||||
:style {:width "15em"}}]]])
|
||||
:schema [:sequential account-override-schema]
|
||||
:key-fn :id
|
||||
:next-key (random-uuid)
|
||||
:new-text "Add override"}]])]
|
||||
|
||||
[form-builder/with-scope {:scope [:address ]}
|
||||
[form-builder/section {:title "Address"}
|
||||
[:div {:style {:width "30em"}}
|
||||
[form-builder/section {:title "Address"}
|
||||
[:div {:style {:width "30em"}}
|
||||
[form-builder/raw-field-v2 {:field :address}
|
||||
[address2-field]]]]
|
||||
|
||||
[form-builder/section {:title "Contact"}
|
||||
@@ -261,55 +289,40 @@
|
||||
"Name"
|
||||
[left-stack
|
||||
[:div.control
|
||||
[form-builder/raw-field
|
||||
[form-builder/raw-field-v2 {:field :legal-entity-first-name}
|
||||
[:input.input {:type "text"
|
||||
:placeholder "First Name"
|
||||
:field [:legal-entity-first-name]
|
||||
:spec ::contact/name}]]]
|
||||
:placeholder "First Name"}]]]
|
||||
|
||||
[:div.control
|
||||
[form-builder/raw-field
|
||||
[form-builder/raw-field-v2 {:field :legal-entity-middle-name}
|
||||
[:input.input {:type "text"
|
||||
:placeholder "Middle Name"
|
||||
:field [:legal-entity-middle-name]
|
||||
:spec ::contact/name}]]]
|
||||
:placeholder "Middle Name"}]]]
|
||||
|
||||
[:div.control
|
||||
[form-builder/raw-field
|
||||
[form-builder/raw-field-v2 {:field :legal-entity-last-name}
|
||||
[:input.input {:type "text"
|
||||
:placeholder "Last Name"
|
||||
:field [:legal-entity-last-name]
|
||||
:spec ::contact/name}]]]]]
|
||||
:placeholder "Last Name"}]]]]]
|
||||
[form-builder/vertical-control
|
||||
"TIN"
|
||||
[left-stack
|
||||
[form-builder/raw-field
|
||||
[form-builder/raw-field-v2 {:field :legal-entity-tin}
|
||||
[:input.input {:type "text"
|
||||
:placeholder "SSN or EIN"
|
||||
:field [:legal-entity-tin]
|
||||
:size "12"
|
||||
:spec ::contact/name}]]
|
||||
}]]
|
||||
|
||||
[:div.control
|
||||
[:div.select
|
||||
[form-builder/raw-field
|
||||
[:select {:type "select"
|
||||
:field [:legal-entity-tin-type]}
|
||||
[:option {:value nil} ""]
|
||||
[:option {:value "ein"} "EIN"]
|
||||
[:option {:value "ssn"} "SSN"]]]]]]]
|
||||
[form-builder/raw-field-v2 {:field :legal-entity-tin-type}
|
||||
[com/select-field {:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]
|
||||
:allow-nil? true}]]]]]
|
||||
|
||||
[form-builder/vertical-control
|
||||
[form-builder/field-v2 {:field :legal-entity-1099-type}
|
||||
"1099 Type"
|
||||
[:div.control
|
||||
[:div.select
|
||||
[form-builder/raw-field
|
||||
[:select {:type "select"
|
||||
:field [:legal-entity-1099-type]}
|
||||
[:option {:value nil} ""]
|
||||
[:option {:value "none"} "Don't 1099"]
|
||||
[:option {:value "misc"} "Misc"]
|
||||
[:option {:value "landlord"} "Landlord"]]]]]]])
|
||||
[com/select-field {:options [["none" "Don't 1099"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]
|
||||
:allow-nil? true}]]])
|
||||
[form-builder/hidden-submit-button]]))
|
||||
|
||||
(defn vendor-dialog [ ]
|
||||
@@ -342,15 +355,15 @@
|
||||
[form-builder/builder {:submit-event [::vendor-selected]
|
||||
:can-submit [::can-submit-select-vendor-form]
|
||||
:id ::select-vendor-form}
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :vendor
|
||||
:required? true}
|
||||
"Vendor to edit"
|
||||
[search-backed-typeahead {:search-query (fn [i]
|
||||
[:search_vendor
|
||||
{:query i}
|
||||
[:name :id]])
|
||||
:type "typeahead-v3"
|
||||
:auto-focus true
|
||||
:field [:vendor]}]]
|
||||
:style {:width "20em"}
|
||||
:auto-focus true}]]
|
||||
[form-builder/hidden-submit-button]])
|
||||
|
||||
|
||||
@@ -360,6 +373,7 @@
|
||||
(fn [{:keys [db]} [_ vendor]]
|
||||
{:db (-> db (forms/start-form ::vendor-form (-> vendor
|
||||
(update :automatically-paid-when-due #(mapv (fn [apwd]
|
||||
apwd
|
||||
{:id (:id apwd)
|
||||
:client apwd})
|
||||
%))
|
||||
|
||||
@@ -595,12 +595,11 @@
|
||||
:placeholder "Manager"
|
||||
:field [:description]}]]}]]
|
||||
|
||||
[form-builder/with-scope {:scope [:address ]}
|
||||
[:div.field
|
||||
[:label.label "Address"]
|
||||
[:div.control
|
||||
[:div {:style {:width "30em"}}
|
||||
[address2-field]]]]]])
|
||||
[form-builder/vertical-control
|
||||
"Address"
|
||||
[:div {:style {:width "30em"}}
|
||||
[form-builder/raw-field-v2 {:field :address}
|
||||
[address2-field]]]]])
|
||||
|
||||
(defn matching-section []
|
||||
[form-builder/section {:title "Matching"}
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
(ns auto-ap.views.pages.admin.users
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as str]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.entities.clients :as entity]
|
||||
[auto-ap.views.components.address :refer [address-field]]
|
||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.pages.admin.users.table :as table]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.utils :refer [login-url dispatch-value-change bind-field horizontal-field dispatch-event]]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.utils :refer [by replace-by]]
|
||||
[cljs.reader :as edn]
|
||||
[auto-ap.routes :as routes]
|
||||
[bidi.bidi :as bidi]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.views.pages.admin.users.form :as form]
|
||||
[auto-ap.effects.forward :as forward]))
|
||||
|
||||
|
||||
(:require
|
||||
[auto-ap.effects.forward :as forward]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.utils :refer [replace-by]]
|
||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.pages.admin.users.form :as form]
|
||||
[auto-ap.views.pages.admin.users.table :as table]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::params
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
(ns auto-ap.views.pages.admin.yodlee2
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[auto-ap.forms :as forms]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as str]
|
||||
[cljs-time.format :as f]
|
||||
[cljs-time.core :as time]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.events :as events]
|
||||
[auto-ap.entities.clients :as entity]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.address :refer [address-field]]
|
||||
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field str->date date->str with-user]]
|
||||
[auto-ap.views.components.modal :as modal]
|
||||
[auto-ap.status :as status]
|
||||
[cljs.reader :as edn]
|
||||
[auto-ap.routes :as routes]
|
||||
[bidi.bidi :as bidi]
|
||||
[auto-ap.views.pages.admin.yodlee2.table :as table]
|
||||
[auto-ap.views.pages.admin.yodlee2.form :as form]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.effects.forward :as forward]))
|
||||
(:require
|
||||
[auto-ap.effects.forward :as forward]
|
||||
[auto-ap.status :as status]
|
||||
[auto-ap.subs :as subs]
|
||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||
[auto-ap.views.components.grid :as grid]
|
||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||
[auto-ap.views.pages.admin.yodlee2.table :as table]
|
||||
[auto-ap.views.utils :refer [dispatch-event]]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::authentication
|
||||
|
||||
@@ -157,13 +157,13 @@
|
||||
(for [child children]
|
||||
^{:key (:key (meta child))}
|
||||
[transition
|
||||
{:timeout 300
|
||||
{:timeout 200
|
||||
:exit true
|
||||
:in true #_ (= current-stack- (:key (meta child)))}
|
||||
(clj->js (fn [state]
|
||||
(r/as-element
|
||||
[:div {:style {
|
||||
:transition "opacity 300ms ease-in-out"
|
||||
:transition "opacity 150ms ease-in-out"
|
||||
:opacity (cond
|
||||
(= "entered" state)
|
||||
1.0
|
||||
@@ -264,17 +264,19 @@
|
||||
[:span.icon [:span.icon-remove]]]])
|
||||
]])]))))
|
||||
|
||||
|
||||
|
||||
(defmethod do-bind "select" [dom {:keys [field allow-nil? subscription event class spec] :as keys} & rest]
|
||||
(let [field (if (keyword? field) [field] field)
|
||||
event (if (keyword? event) [event] event)
|
||||
keys (assoc keys
|
||||
:on-change (dispatch-value-change (conj event field))
|
||||
keys (assoc keys
|
||||
:on-change (dispatch-value-change (conj event field))
|
||||
|
||||
:value (or (get-in subscription field) "")
|
||||
:class (str class
|
||||
(when (and spec (not (s/valid? spec (get-in subscription field))))
|
||||
" is-danger")))
|
||||
keys (dissoc keys :field :subscription :event :spec)
|
||||
:value (or (get-in subscription field) "")
|
||||
:class (str class
|
||||
(when (and spec (not (s/valid? spec (get-in subscription field))))
|
||||
" is-danger")))
|
||||
keys (dissoc keys :field :subscription :event :spec)
|
||||
options (if allow-nil?
|
||||
(with-keys (conj rest [:option {:value nil}]))
|
||||
(with-keys rest))]
|
||||
|
||||
Reference in New Issue
Block a user