80 lines
4.3 KiB
Plaintext
80 lines
4.3 KiB
Plaintext
|
(ns com.fulcrologic.rad.rendering.semantic-ui.enumerated-field
|
||
|
(:require
|
||
|
#?@(:cljs
|
||
|
[[com.fulcrologic.fulcro.dom :as dom :refer [div label input]]
|
||
|
[cljs.reader :refer [read-string]]
|
||
|
[com.fulcrologic.semantic-ui.modules.dropdown.ui-dropdown :refer [ui-dropdown]]]
|
||
|
:clj
|
||
|
[[com.fulcrologic.fulcro.dom-server :as dom :refer [div label input]]])
|
||
|
[com.fulcrologic.rad.ui-validation :as validation]
|
||
|
[com.fulcrologic.fulcro.components :as comp :refer [defsc]]
|
||
|
[com.fulcrologic.rad.options-util :refer [?!]]
|
||
|
[com.fulcrologic.rad.rendering.semantic-ui.components :refer [ui-wrapped-dropdown]]
|
||
|
[com.fulcrologic.rad.attributes :as attr]
|
||
|
[clojure.string :as str]
|
||
|
[com.fulcrologic.rad.form :as form]))
|
||
|
|
||
|
(defn enumerated-options [{::form/keys [form-instance] :as env} {::attr/keys [qualified-key] :as attribute}]
|
||
|
(let [{::attr/keys [enumerated-values]} attribute
|
||
|
enumeration-labels (merge
|
||
|
(::attr/enumerated-labels attribute)
|
||
|
(comp/component-options form-instance ::form/enumerated-labels qualified-key))]
|
||
|
;; TODO: Sorting should be something users control
|
||
|
(sort-by :text
|
||
|
(mapv (fn [k]
|
||
|
{:text (?! (get enumeration-labels k (name k)))
|
||
|
:value k}) enumerated-values))))
|
||
|
|
||
|
(defn- render-to-many [{::form/keys [form-instance] :as env} {::form/keys [field-label]
|
||
|
::attr/keys [qualified-key] :as attribute}]
|
||
|
(when (form/field-visible? form-instance attribute)
|
||
|
(let [props (comp/props form-instance)
|
||
|
read-only? (form/read-only? form-instance attribute)
|
||
|
options (enumerated-options env attribute)
|
||
|
selected-ids (set (get props qualified-key))]
|
||
|
(div :.ui.field {:key (str qualified-key)}
|
||
|
(label (or field-label (some-> qualified-key name str/capitalize)))
|
||
|
(div :.ui.middle.aligned.celled.list.big {:style {:marginTop "0"}}
|
||
|
(map (fn [{:keys [text value]}]
|
||
|
(let [checked? (contains? selected-ids value)]
|
||
|
(div :.item {:key value}
|
||
|
(div :.content {}
|
||
|
(div :.ui.toggle.checkbox {:style {:marginTop "0"}}
|
||
|
(dom/input
|
||
|
{:type "checkbox"
|
||
|
:checked checked?
|
||
|
:disabled read-only?
|
||
|
:onChange #(let [selection (if-not checked?
|
||
|
(conj (set (or selected-ids #{})) value)
|
||
|
(disj selected-ids value))]
|
||
|
(form/input-changed! env qualified-key selection))})
|
||
|
(dom/label text))))))
|
||
|
options))))))
|
||
|
|
||
|
(defn- render-to-one [{::form/keys [form-instance] :as env} {::form/keys [field-label]
|
||
|
::attr/keys [qualified-key] :as attribute}]
|
||
|
(when (form/field-visible? form-instance attribute)
|
||
|
(let [props (comp/props form-instance)
|
||
|
read-only? (form/read-only? form-instance attribute)
|
||
|
invalid? (validation/invalid-attribute-value? env attribute)
|
||
|
user-props (form/field-style-config env attribute :input/props)
|
||
|
options (enumerated-options env attribute)
|
||
|
value (get props qualified-key)]
|
||
|
(div :.ui.field {:key (str qualified-key) :classes [(when invalid? "error")]}
|
||
|
(label (str (or field-label (some-> qualified-key name str/capitalize))
|
||
|
(when invalid? " (Required)")))
|
||
|
(if read-only?
|
||
|
(let [value (first (filter #(= value (:value %)) options))]
|
||
|
(:text value))
|
||
|
(ui-wrapped-dropdown (merge
|
||
|
{:disabled read-only?
|
||
|
:options options
|
||
|
:value value
|
||
|
:onChange (fn [v] (form/input-changed! env qualified-key v))}
|
||
|
user-props)))))))
|
||
|
|
||
|
(defn render-field [env {::attr/keys [cardinality] :or {cardinality :one} :as attribute}]
|
||
|
(if (= :many cardinality)
|
||
|
(render-to-many env attribute)
|
||
|
(render-to-one env attribute)))
|