more progress for client fdorm.
This commit is contained in:
@@ -44,19 +44,21 @@
|
||||
(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]))
|
||||
(let [data-sub (or data-sub [::forms/form id])
|
||||
change-event (when-not on-change
|
||||
(or change-event [::forms/change id]))
|
||||
{: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)
|
||||
true)
|
||||
problems (when schema
|
||||
(m/explain schema data))]
|
||||
data (or value data)
|
||||
status @(re-frame/subscribe [::status/single id])
|
||||
can-submit (if can-submit @(re-frame/subscribe can-submit)
|
||||
true)
|
||||
;; TODO ONLY validate on blur
|
||||
problems (when schema
|
||||
|
||||
(m/explain schema data))]
|
||||
(r/create-element Provider #js {:value #js {:can-submit can-submit
|
||||
:error-messages (or error-messages
|
||||
nil)
|
||||
nil)
|
||||
:on-change on-change
|
||||
:change-event change-event
|
||||
:blur-event [::forms/visited id]
|
||||
@@ -155,14 +157,14 @@
|
||||
["visited" "attempted-submit?" "problems" "error-messages"]
|
||||
(fn [visited attempted-submit? problems error-messages]
|
||||
(consume FormScopeConsumer
|
||||
["form-scope"]
|
||||
(fn [form-scope]
|
||||
["scope"]
|
||||
(fn [scope]
|
||||
(let [full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
(into scope field)
|
||||
|
||||
field
|
||||
(conj form-scope field)
|
||||
(conj scope field)
|
||||
|
||||
:else
|
||||
nil)
|
||||
@@ -181,43 +183,43 @@
|
||||
["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]
|
||||
["scope"]
|
||||
(fn [scope]
|
||||
(update child 1 (fn [child-props]
|
||||
(let [
|
||||
full-field-path (cond
|
||||
(sequential? field)
|
||||
(into form-scope field)
|
||||
(let [
|
||||
full-field-path (cond
|
||||
(sequential? field)
|
||||
(into scope field)
|
||||
|
||||
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"
|
||||
field
|
||||
(conj 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/create-element FormScopeProvider #js {:value #js {:scope scope}}
|
||||
(r/as-element (into [:<>]
|
||||
(r/children (r/current-component))))))
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
(def money (m/schema [float? {:error/message "Invalid money"}]))
|
||||
(def not-empty-string (m/schema [:re {:error/message "Required"} #"\S+"]))
|
||||
(def code-string (m/schema [:re #"[A-Z0-9\-]+"]))
|
||||
(def keyword (m/schema [:fn (fn [d]
|
||||
(keyword? d))]))
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns auto-ap.views.components
|
||||
(:require [reagent.core :as r]
|
||||
[clojure.string :as str]))
|
||||
[clojure.string :as str]
|
||||
[auto-ap.views.components.multi :as multi]))
|
||||
|
||||
|
||||
(defn checkbox [{:keys [on-change
|
||||
@@ -32,3 +33,5 @@
|
||||
[:option {:value nil}])
|
||||
(for [[k v] options]
|
||||
^{:key k} [:option {:value k} v])]]])
|
||||
|
||||
(def multi-field-v2 multi/multi-field-v2)
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
[: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)]]
|
||||
:let [extant? (boolean (key-fn override))
|
||||
is-disabled? (boolean (and (= false allow-change?)
|
||||
extant?))]]
|
||||
|
||||
^{:key (or (key-fn override)
|
||||
(::key override))}
|
||||
@@ -31,25 +31,31 @@
|
||||
(::key override))}
|
||||
[:div.level {:style {:margin-bottom "0.25em"}}
|
||||
[:div.level-left {:style {:padding "0.5em 1em"}
|
||||
:class (when-not (key-fn override)
|
||||
:class (when-not extant?
|
||||
"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]]]])]]]))
|
||||
[:fieldset.level-left {:disabled is-disabled?
|
||||
:style {:padding "0.5em 1em"}
|
||||
:class (when-not extant?
|
||||
"has-background-info-light")}
|
||||
(for [[idx template] (map vector (range ) template)]
|
||||
^{:key idx}
|
||||
[:div.level-item
|
||||
template])
|
||||
(when-not (and disable-remove?
|
||||
extant?)
|
||||
[: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"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[react-signature-canvas]
|
||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
||||
[auto-ap.views.components.level :refer [left-stack]]
|
||||
[auto-ap.views.components :as com]
|
||||
[auto-ap.views.components.typeahead.vendor
|
||||
:refer [search-backed-typeahead]]
|
||||
[auto-ap.views.utils
|
||||
@@ -24,10 +25,25 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as r]
|
||||
[react-signature-canvas]
|
||||
[vimsical.re-frame.cofx.inject :as inject]))
|
||||
[vimsical.re-frame.cofx.inject :as inject]
|
||||
[auto-ap.schema :as schema]
|
||||
[auto-ap.views.components :as com]
|
||||
[malli.core :as m]))
|
||||
|
||||
(def signature-canvas (r/adapt-react-class (.-default react-signature-canvas)))
|
||||
|
||||
(def location-schema (m/schema [:map
|
||||
[:location schema/not-empty-string]]))
|
||||
(def email-schema [:map
|
||||
[:email schema/not-empty-string]
|
||||
[:description schema/not-empty-string]])
|
||||
|
||||
(def client-schema [:map
|
||||
[:name schema/not-empty-string]
|
||||
[:code schema/code-string]
|
||||
[:locations [:sequential location-schema]]
|
||||
[:emails [:sequential email-schema]]])
|
||||
|
||||
(defn upload-replacement-button [{:keys [on-change]} text]
|
||||
(let [button (atom nil)]
|
||||
(r/create-class {:display-name "Upload button"
|
||||
@@ -109,7 +125,8 @@
|
||||
{:id (:id new-client-data),
|
||||
:name (:name new-client-data)
|
||||
:code (:code new-client-data) ;; TODO add validation can't change
|
||||
:emails (:emails new-client-data)
|
||||
:emails (map #(select-keys % [:id :email :description])
|
||||
(:emails new-client-data))
|
||||
:square-auth-token (:square-auth-token new-client-data)
|
||||
:square-locations (map
|
||||
(fn [x]
|
||||
@@ -193,13 +210,15 @@
|
||||
{:id (:id sl)
|
||||
:square-location sl
|
||||
:client-location (:client-location sl)}))))
|
||||
(update :locations #(mapv (fn [l] {:location l}) %))
|
||||
(update :locations #(mapv (fn [l] {:location l
|
||||
:id (random-uuid)}) %))
|
||||
(update :matches #(mapv (fn [l] {:match l}) %))
|
||||
(update :bank-accounts
|
||||
(fn [bas]
|
||||
(mapv (fn [ba]
|
||||
(update ba :locations (fn [ls]
|
||||
(map (fn [l] {:location l})
|
||||
(map (fn [l] {:location l
|
||||
:id (random-uuid)})
|
||||
ls))))
|
||||
bas))))))}))
|
||||
|
||||
@@ -535,57 +554,54 @@
|
||||
(defn general-section []
|
||||
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||
[form-builder/section {:title "General"}
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :name}
|
||||
"Name"
|
||||
[:input.input {:type "text"
|
||||
:style {:width "20em"}
|
||||
:field [:name]
|
||||
:spec ::entity/name}]]
|
||||
[form-builder/field
|
||||
:style {:width "20em"}}]]
|
||||
[form-builder/field-v2 {:field :code}
|
||||
"Client code"
|
||||
[:input.input {:type "code"
|
||||
:style {:width "5em"}
|
||||
:field :code
|
||||
:disabled (boolean (:id new-client))
|
||||
:spec ::entity/code}]]
|
||||
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :locations}
|
||||
"Locations"
|
||||
[multi-field {:type "multi-field"
|
||||
:field :locations
|
||||
:allow-change? false
|
||||
:template [[:input.input {:field [:location]
|
||||
:max-length 2
|
||||
:style { :width "4em"}}]]}]]
|
||||
[com/multi-field-v2 {:allow-change? false
|
||||
:template [[form-builder/raw-field-v2 {:field :location}
|
||||
[:input.input {:max-length 2
|
||||
:style { :width "4em"}}]]]
|
||||
:disable-remove? true
|
||||
:key-fn :id
|
||||
:schema [:sequential location-schema]
|
||||
:next-key (random-uuid)}]]
|
||||
|
||||
[:div.field
|
||||
[:label.label "Signature"]
|
||||
[form-builder/vertical-control
|
||||
"Signature"
|
||||
[signature {:signature-file (:signature-file new-client)
|
||||
:signature-data (:signature-data new-client)
|
||||
:on-change (fn [uri]
|
||||
(re-frame/dispatch [::forms/change ::form [:signature-data] uri]))}]]
|
||||
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :locked-until}
|
||||
"Locked Until"
|
||||
[date-picker {:type "date"
|
||||
:output :cljs-date
|
||||
:field [:locked-until]
|
||||
:style {:width "15em"}}]]]))
|
||||
[date-picker {:output :cljs-date
|
||||
:style {:width "15em"}}]]]))
|
||||
|
||||
(defn contacts-section []
|
||||
[form-builder/section {:title "Contacts"}
|
||||
|
||||
[form-builder/field
|
||||
[form-builder/field-v2 {:field :emails}
|
||||
"Emails (address/description)"
|
||||
[multi-field {:type "multi-field"
|
||||
:field :emails
|
||||
:template [[:input.input {:type "email"
|
||||
:field [:email]
|
||||
:placeholder "tom@myspace.com"
|
||||
:spec ::entity/email}]
|
||||
[:input.input {:type "text"
|
||||
:placeholder "Manager"
|
||||
:field [:description]}]]}]]
|
||||
[com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :email}
|
||||
[:input.input {:type "email"
|
||||
:placeholder "tom@myspace.com"}]]
|
||||
[form-builder/raw-field-v2 {:field :description}
|
||||
[:input.input {:type "text"
|
||||
:placeholder "Manager"}]]]
|
||||
:key-fn :id
|
||||
:schema [:sequential email-schema]
|
||||
:next-key (random-uuid)}]]
|
||||
|
||||
[form-builder/vertical-control
|
||||
"Address"
|
||||
@@ -735,6 +751,7 @@
|
||||
:step "0.01"}]]
|
||||
:disable-remove? true}]]])
|
||||
|
||||
|
||||
(defn form-content []
|
||||
(let [_ @(re-frame/subscribe [::client])
|
||||
{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||
@@ -743,7 +760,8 @@
|
||||
"new")}
|
||||
[form-builder/builder {:submit-event [::save-new-client ]
|
||||
:id ::form
|
||||
:fullwidth? false}
|
||||
:fullwidth? false
|
||||
:schema client-schema}
|
||||
|
||||
[general-section]
|
||||
[contacts-section]
|
||||
|
||||
Reference in New Issue
Block a user