|  |  |  | @ -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))) | 
		
	
	
		
			
				
					|  |  |  | 
 |