|
|
|
@ -3,41 +3,82 @@
|
|
|
|
|
[hiccup.form :as hform]
|
|
|
|
|
[wanijo.framework.view :as view]))
|
|
|
|
|
|
|
|
|
|
(spec/def ::label string?)
|
|
|
|
|
(spec/def ::required boolean?)
|
|
|
|
|
(spec/def ::spec keyword?)
|
|
|
|
|
(spec/def ::options
|
|
|
|
|
(spec/coll-of (spec/tuple string? string?)))
|
|
|
|
|
(spec/def ::field
|
|
|
|
|
(spec/keys :req-un [::label
|
|
|
|
|
::required
|
|
|
|
|
::spec]
|
|
|
|
|
:opt-un [::options]))
|
|
|
|
|
(spec/def ::fields
|
|
|
|
|
(spec/and map?
|
|
|
|
|
(fn [map]
|
|
|
|
|
(every? #(spec/valid? ::field (val %)) map))
|
|
|
|
|
(fn [map]
|
|
|
|
|
(every? #(keyword? (key %)) map))))
|
|
|
|
|
(spec/def ::form
|
|
|
|
|
(spec/keys :req-un [::fields]))
|
|
|
|
|
|
|
|
|
|
(defn spec-to-errmsg [label spec-key field-value]
|
|
|
|
|
(view/flash-error
|
|
|
|
|
(map
|
|
|
|
|
(fn [prob]
|
|
|
|
|
[:p
|
|
|
|
|
"Field "
|
|
|
|
|
[:span.flash__field label]
|
|
|
|
|
" must comply to "
|
|
|
|
|
[:span.flash__pred (:pred prob)]])
|
|
|
|
|
(:clojure.spec.alpha/problems
|
|
|
|
|
(spec/explain-data spec-key field-value)))))
|
|
|
|
|
(map
|
|
|
|
|
(fn [prob]
|
|
|
|
|
[:p
|
|
|
|
|
"Field "
|
|
|
|
|
[:span.flash__field label]
|
|
|
|
|
" must comply to "
|
|
|
|
|
[:span.flash__pred (:pred prob)]])
|
|
|
|
|
(:clojure.spec.alpha/problems
|
|
|
|
|
(spec/explain-data spec-key field-value)))))
|
|
|
|
|
|
|
|
|
|
(defn field-valid? [value spec-key req]
|
|
|
|
|
(or (empty? (:form-params req))
|
|
|
|
|
(spec/valid? spec-key value)))
|
|
|
|
|
|
|
|
|
|
(defn field [form-def field req]
|
|
|
|
|
{:pre [(spec/valid? ::form form-def)]}
|
|
|
|
|
(let [field-value (get-in req [:params field])
|
|
|
|
|
field-def (get-in form-def [:fields field])
|
|
|
|
|
{:keys [label required] spec-key :spec} field-def]
|
|
|
|
|
(list
|
|
|
|
|
(when-not (field-valid? field-value spec-key req)
|
|
|
|
|
(spec-to-errmsg label spec-key field-value))
|
|
|
|
|
(hform/label field label)
|
|
|
|
|
(hform/text-field {:required (when required "required")}
|
|
|
|
|
field
|
|
|
|
|
field-value))))
|
|
|
|
|
|
|
|
|
|
(defn drop-down
|
|
|
|
|
([form-def field req]
|
|
|
|
|
{:pre [(spec/valid? ::form form-def)]}
|
|
|
|
|
(drop-down form-def
|
|
|
|
|
field
|
|
|
|
|
req
|
|
|
|
|
(get-in form-def [:fields field :options])))
|
|
|
|
|
([form-def field req options]
|
|
|
|
|
{:pre [(spec/valid? ::form form-def)]}
|
|
|
|
|
(let [field-value (get-in req [:params field])
|
|
|
|
|
field-def (get-in form-def [:fields field])
|
|
|
|
|
{:keys [label required] spec-key :spec} field-def]
|
|
|
|
|
(list
|
|
|
|
|
(when-not (field-valid? field-value spec-key req)
|
|
|
|
|
(spec-to-errmsg label spec-key field-value))
|
|
|
|
|
(hform/label field label)
|
|
|
|
|
(hform/text-field {:required (when required "required")}
|
|
|
|
|
field
|
|
|
|
|
field-value))))
|
|
|
|
|
(hform/drop-down field
|
|
|
|
|
options
|
|
|
|
|
field-value)))))
|
|
|
|
|
|
|
|
|
|
(defn valid? [form-def req]
|
|
|
|
|
{:pre [(spec/valid? ::form form-def)]}
|
|
|
|
|
(reduce-kv
|
|
|
|
|
(fn [result field value]
|
|
|
|
|
(if-let [field-spec (get-in form-def [:fields field :spec])]
|
|
|
|
|
(if (spec/valid? field-spec value)
|
|
|
|
|
true
|
|
|
|
|
(reduced false))
|
|
|
|
|
result))
|
|
|
|
|
true
|
|
|
|
|
(:params req)))
|
|
|
|
|
(fn [result field value]
|
|
|
|
|
(if-let [field-spec (get-in form-def [:fields field :spec])]
|
|
|
|
|
(if (spec/valid? field-spec value)
|
|
|
|
|
true
|
|
|
|
|
(reduced false))
|
|
|
|
|
result))
|
|
|
|
|
true
|
|
|
|
|
(:params req)))
|
|
|
|
|