fulcro-rad-carbon/src/main/com/fulcrologic/rad/rendering/semantic_ui/enumerated_field.cljc

80 lines
4.3 KiB
Clojure

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