Minor refactoring to simplify consumer. May be better to use macro.
This commit is contained in:
@@ -30,13 +30,15 @@
|
||||
([db form data]
|
||||
(start-form db form data nil))
|
||||
([db form data complete-listener]
|
||||
(assoc-in db [::forms form] {:error nil
|
||||
:active? true
|
||||
:id (random-uuid)
|
||||
:visited #{}
|
||||
:status nil
|
||||
:data data
|
||||
:complete-listener complete-listener})))
|
||||
(-> db
|
||||
(assoc-in [::forms form] {:error nil
|
||||
:active? true
|
||||
:id (random-uuid)
|
||||
:visited #{}
|
||||
:status nil
|
||||
:data data
|
||||
:complete-listener complete-listener})
|
||||
(assoc-in [::status/status form] nil))))
|
||||
|
||||
(defn triggers-saved [form data-key]
|
||||
(i/->interceptor
|
||||
|
||||
@@ -34,13 +34,20 @@
|
||||
(get-in field-path)
|
||||
first))
|
||||
|
||||
(defn consume [consumer-component fields f]
|
||||
[:> consumer-component {}
|
||||
(fn [consumed]
|
||||
(r/as-element
|
||||
(apply f (for [field fields]
|
||||
(aget consumed field)))))])
|
||||
|
||||
(defn builder [{:keys [value on-change can-submit data-sub error-messages change-event submit-event id fullwidth? schema validation-error-string]}]
|
||||
(when (and change-event on-change)
|
||||
(throw "Either the form is to be managed by ::forms, or it should have value and on-change passed in"))
|
||||
(let [data-sub (or data-sub [::forms/form id])
|
||||
change-event (when-not on-change
|
||||
(or change-event [::forms/change id]))
|
||||
{:keys [data error visited attempted-submit?] form-key :id} @(re-frame/subscribe data-sub)
|
||||
{:keys [data visited attempted-submit?] form-key :id} @(re-frame/subscribe data-sub)
|
||||
data (or value data)
|
||||
status @(re-frame/subscribe [::status/single id])
|
||||
can-submit (if can-submit @(re-frame/subscribe can-submit)
|
||||
@@ -57,7 +64,7 @@
|
||||
:submit-event submit-event
|
||||
:problems problems
|
||||
:attempted-submit? attempted-submit?
|
||||
:error error
|
||||
:error (-> status :error first :message)
|
||||
:status status
|
||||
:id id
|
||||
:data data
|
||||
@@ -144,75 +151,71 @@
|
||||
(conj path))))
|
||||
|
||||
(defn raw-error-v2 [{:keys [field]}]
|
||||
[:> Consumer {}
|
||||
(fn [consume-form]
|
||||
(r/as-element
|
||||
[:> FormScopeConsumer {}
|
||||
(fn [form-scope]
|
||||
(r/as-element
|
||||
(let [full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
(consume Consumer
|
||||
["visited" "attempted-submit?" "problems" "error-messages"]
|
||||
(fn [visited attempted-submit? problems error-messages]
|
||||
(consume FormScopeConsumer
|
||||
["form-scope"]
|
||||
(fn [form-scope]
|
||||
(let [full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
|
||||
field
|
||||
(conj form-scope field)
|
||||
field
|
||||
(conj form-scope field)
|
||||
|
||||
:else
|
||||
nil)
|
||||
visited? (get (aget consume-form "visited") full-field-path)
|
||||
attempted-submit? (aget consume-form "attempted-submit?")]
|
||||
(when-let [error-message (and
|
||||
(or visited? attempted-submit?)
|
||||
(spec-error-message (aget consume-form "problems") full-field-path (aget consume-form "error-messages")))]
|
||||
[:div
|
||||
[:p.help.has-text-danger error-message]]))))]))])
|
||||
:else
|
||||
nil)
|
||||
visited? (get visited full-field-path)]
|
||||
(when-let [error-message (and
|
||||
(or visited? attempted-submit?)
|
||||
(spec-error-message problems full-field-path error-messages))]
|
||||
[:div
|
||||
[:p.help.has-text-danger error-message]])))))))
|
||||
|
||||
(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]
|
||||
(r/as-element
|
||||
[:> FormScopeConsumer {}
|
||||
(fn [form-scope]
|
||||
(r/as-element
|
||||
(update child 1 (fn [child-props]
|
||||
(let [
|
||||
full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
(consume Consumer
|
||||
["visited" "attempted-submit?" "data" "on-change" "change-event" "blur-event" "problems"]
|
||||
(fn [visited attempted-submit? data on-change change-event blur-event problems]
|
||||
(consume FormScopeConsumer
|
||||
["form-scope"]
|
||||
(fn [form-scope]
|
||||
(update child 1 (fn [child-props]
|
||||
(let [
|
||||
full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
|
||||
field
|
||||
(conj form-scope field)
|
||||
|
||||
:else
|
||||
nil)
|
||||
visited? (get (aget consume-form "visited") full-field-path)
|
||||
attempted-submit? (aget consume-form "attempted-submit?")
|
||||
value (get-in (aget consume-form "data") full-field-path)
|
||||
on-change (aget consume-form "on-change")]
|
||||
(-> child-props
|
||||
(assoc :on-change
|
||||
(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]
|
||||
(str class
|
||||
(cond
|
||||
(and (not visited?) (not attempted-submit?))
|
||||
""
|
||||
(not (valid-field? (aget consume-form "problems") full-field-path))
|
||||
" is-danger"
|
||||
|
||||
value
|
||||
"is-success"
|
||||
field
|
||||
(conj form-scope field)
|
||||
|
||||
:else
|
||||
""))))))))))]))]))
|
||||
nil)
|
||||
visited? (get visited full-field-path)
|
||||
value (get-in data full-field-path)]
|
||||
(-> child-props
|
||||
(assoc :on-change
|
||||
(if on-change
|
||||
(partial form-change-handler data full-field-path on-change)
|
||||
(partial change-handler full-field-path change-event))
|
||||
:on-blur (partial blur-handler full-field-path blur-event)
|
||||
:value value)
|
||||
(update :class (fn [class]
|
||||
(str class
|
||||
(cond
|
||||
(and (not visited?) (not attempted-submit?))
|
||||
""
|
||||
(not (valid-field? problems full-field-path))
|
||||
" is-danger"
|
||||
|
||||
value
|
||||
"is-success"
|
||||
|
||||
:else
|
||||
""))))))))))))))
|
||||
(defn with-scope [{:keys [scope]}]
|
||||
(r/create-element FormScopeProvider #js {:value scope}
|
||||
(r/as-element (into [:<>]
|
||||
@@ -220,17 +223,17 @@
|
||||
|
||||
(defn vertical-control [{:keys [is-small? required?]}]
|
||||
(let [[label & children] (r/children (r/current-component))]
|
||||
[:> Consumer {}
|
||||
(fn [consume]
|
||||
(r/as-element
|
||||
[:div.field
|
||||
(if (aget consume "fullwidth?")
|
||||
[:p.help label]
|
||||
[:label.label
|
||||
(if required?
|
||||
[:span label [:span.has-text-danger " *"]]
|
||||
label)])
|
||||
(into [:div.control ] children)]))]))
|
||||
(consume Consumer
|
||||
["fullwidth?"]
|
||||
(fn [fullwidth?]
|
||||
[:div.field
|
||||
(if fullwidth?
|
||||
[:p.help label]
|
||||
[:label.label
|
||||
(if required?
|
||||
[:span label [:span.has-text-danger " *"]]
|
||||
label)])
|
||||
(into [:div.control ] children)]))))
|
||||
|
||||
(defn field []
|
||||
(let [props (r/props (r/current-component))
|
||||
@@ -251,20 +254,20 @@
|
||||
(defn field-v2 []
|
||||
(let [props (r/props (r/current-component))
|
||||
[label child] (r/children (r/current-component))]
|
||||
[:> Consumer {}
|
||||
(fn [consume]
|
||||
(r/as-element
|
||||
[:div.field
|
||||
(when label
|
||||
(if (aget consume "fullwidth?")
|
||||
[:p.help label]
|
||||
[:label.label
|
||||
(if (:required? props)
|
||||
[:span label [:span.has-text-danger " *"]]
|
||||
label)]))
|
||||
[:div.control [raw-field-v2 props child]]
|
||||
[:div
|
||||
[raw-error-v2 {:field (:field props)}]]]))]))
|
||||
(consume Consumer
|
||||
["fullwidth?"]
|
||||
(fn [fullwidth?]
|
||||
[:div.field
|
||||
(when label
|
||||
(if fullwidth?
|
||||
[:p.help label]
|
||||
[:label.label
|
||||
(if (:required? props)
|
||||
[:span label [:span.has-text-danger " *"]]
|
||||
label)]))
|
||||
[:div.control [raw-field-v2 props child]]
|
||||
[:div
|
||||
[raw-error-v2 {:field (:field props)}]]]))))
|
||||
|
||||
(defn horizontal-control []
|
||||
(let [[label & children] (r/children (r/current-component))]
|
||||
@@ -292,34 +295,27 @@
|
||||
|
||||
(defn submit-button [{:keys [class]}]
|
||||
(let [[child] (r/children (r/current-component))]
|
||||
[:> Consumer {}
|
||||
(fn [consume]
|
||||
(let [status (aget consume "status")
|
||||
can-submit (aget consume "can-submit")
|
||||
fullwidth? (aget consume "fullwidth?")]
|
||||
(r/as-element
|
||||
[:button.button.is-medium.is-primary {:disabled (or (status/disabled-for status)
|
||||
(not can-submit))
|
||||
:class (cond-> (or class [])
|
||||
(status/class-for status) (conj (status/class-for status))
|
||||
fullwidth? (conj "is-fullwidth")) }
|
||||
child])))]))
|
||||
(consume
|
||||
Consumer
|
||||
["status" "can-submit" "fullwidth?"]
|
||||
(fn [status can-submit fullwidth?]
|
||||
[:button.button.is-medium.is-primary {:disabled (or (status/disabled-for status)
|
||||
(not can-submit))
|
||||
:class (cond-> (or class [])
|
||||
(status/class-for status) (into (status/class-for status))
|
||||
fullwidth? (conj "is-fullwidth")) }
|
||||
child]))))
|
||||
|
||||
(defn hidden-submit-button []
|
||||
[:> Consumer {}
|
||||
(fn [consume]
|
||||
(let [status (aget consume "status")
|
||||
can-submit (aget consume "can-submit")]
|
||||
(r/as-element
|
||||
[:div {:style {:display "none"}}
|
||||
[:button.button.is-medium.is-primary {:disabled (or (status/disabled-for status)
|
||||
(not can-submit))}]])))])
|
||||
(consume Consumer ["status" "can-submit"]
|
||||
(fn [status can-submit]
|
||||
[:div {:style {:display "none"}}
|
||||
[:button.button.is-medium.is-primary {:disabled (or (status/disabled-for status)
|
||||
(not can-submit))}]])))
|
||||
|
||||
(defn error-notification []
|
||||
(let [[child] (r/children (r/current-component))]
|
||||
[:> Consumer {}
|
||||
(fn [consume]
|
||||
(r/as-element
|
||||
(when-let [error (aget consume "error")]
|
||||
^{:key error}
|
||||
[:div.has-text-danger.animated.fadeInUp {} error])))]))
|
||||
(consume Consumer ["error"]
|
||||
(fn [error]
|
||||
(when error
|
||||
^{:key error}
|
||||
[:div.has-text-danger.animated.fadeInUp {} error]))))
|
||||
|
||||
@@ -117,7 +117,6 @@
|
||||
::error
|
||||
[(re-frame/path [::status]) ]
|
||||
(fn [db [_ single error]]
|
||||
(println "STATUS" single error)
|
||||
(assoc db single {:state :error
|
||||
:info nil
|
||||
:error error})))
|
||||
|
||||
@@ -101,14 +101,6 @@
|
||||
[upload-replacement-button {:on-change on-change} "Upload signature"]]]))
|
||||
])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::can-submit
|
||||
:<- [::new-client-request]
|
||||
(fn [_ _]
|
||||
true
|
||||
|
||||
#_(s/valid? ::entity/client r)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::new-client-request
|
||||
:<- [::forms/form ::form]
|
||||
@@ -749,8 +741,7 @@
|
||||
|
||||
^{:key (or (:id new-client)
|
||||
"new")}
|
||||
[form-builder/builder {:can-submit [::can-submit]
|
||||
:submit-event [::save-new-client ]
|
||||
[form-builder/builder {:submit-event [::save-new-client ]
|
||||
:id ::form
|
||||
:fullwidth? false}
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
(- (:total (:original data)) (:outstanding-balance (:original data))))
|
||||
account-total (reduce + 0 (map :amount (:expense-accounts data)))]
|
||||
(and
|
||||
(m/validate schema data)
|
||||
(or (not min-total) (>= (:total data) min-total))
|
||||
(or (not (:id data))
|
||||
(dollars= (Math/abs (:total data)) (Math/abs account-total)))))))
|
||||
@@ -440,6 +439,7 @@
|
||||
(list
|
||||
^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::save-requested [::add-and-print id :check]])} "Print checks from " name]
|
||||
^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::save-requested [::add-and-print id :debit]])} "Debit from " name]))))]]])
|
||||
|
||||
[:div.column
|
||||
[form-builder/submit-button {:class ["is-fullwidth"]}
|
||||
"Save"]]]])])
|
||||
|
||||
Reference in New Issue
Block a user