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

122 lines
6.3 KiB
Clojure

(ns com.fulcrologic.rad.rendering.semantic-ui.blob-field
(:require
[com.fulcrologic.fulcro.components :as comp :refer [defsc]]
#?@(:cljs [[com.fulcrologic.fulcro.dom :as dom :refer [div input]]
[goog.object :as gobj]
[com.fulcrologic.fulcro.networking.file-upload :as file-upload]]
:clj [[com.fulcrologic.fulcro.dom-server :as dom :refer [div input]]])
[com.fulcrologic.rad.form :as form]
[com.fulcrologic.rad.attributes :as attr]
[taoensso.timbre :as log]
[com.fulcrologic.rad.ui-validation :as validation]
[com.fulcrologic.rad.blob :as blob]
[com.fulcrologic.rad.options-util :refer [?! narrow-keyword]]
[com.fulcrologic.rad.rendering.semantic-ui.components :refer [ui-wrapped-dropdown]]
[com.fulcrologic.rad.rendering.semantic-ui.field :refer [render-field-factory]]
[com.fulcrologic.fulcro.algorithms.form-state :as fs]))
(defn evt->js-files [evt]
#?(:cljs
(let [js-file-list (.. evt -target -files)]
(map (fn [file-idx]
(let [js-file (.item js-file-list file-idx)
name (.-name js-file)]
js-file))
(range (.-length js-file-list))))))
#_(defsc ImageUploadField [this
{::form/keys [form-instance] :as env}
{::blob/keys [accept-file-types]
::attr/keys [qualified-key] :as attribute}]
{:initLocalState (fn [this]
#?(:cljs
{:save-ref (fn [r] (gobj/set this "fileinput" r))
:on-click (fn [evt] (when-let [i (gobj/get this "fileinput")]
(.click i)))
:on-change (fn [evt]
(let [env (comp/props this)
attribute (comp/get-computed this)
file (-> evt evt->js-files first)]
(blob/upload-file! env attribute file)))}))}
(let [props (comp/props form-instance)
url-key (narrow-keyword qualified-key "url")
current-sha (get props qualified-key)
url (get props url-key)
has-current-value? (seq current-sha)
{:keys [save-ref on-change on-click]} (comp/get-state this)
upload-complete? false
label (form/field-label env attribute)
valid? (and upload-complete? has-current-value?)]
(div :.field {:key (str qualified-key)}
(dom/label label)
(div :.ui.tiny.image
(dom/img {:src url :width "100"
:onClick on-click})
(dom/input (cond-> {:id (str qualified-key)
:ref save-ref
:style {:position "absolute"
:opacity 0
:top 0
:right 0}
:onChange on-change
:type "file"}
accept-file-types (assoc :allow (?! accept-file-types))))))))
#_(def ui-image-upload-field (comp/computed-factory ImageUploadField
{:keyfn (fn [props] (some-> props comp/get-computed ::attr/qualified-key))}))
#_(defn render-image-upload [env attribute]
(ui-image-upload-field env attribute))
(defsc FileUploadField [this
{::form/keys [form-instance master-form] :as env}
{::blob/keys [accept-file-types can-change?]
::attr/keys [qualified-key] :as attribute}]
{:componentDidMount (fn [this]
(comment "TRIGGER UPLOAD IF CONFIG SAYS TO?"))
:initLocalState (fn [this]
#?(:cljs
{:save-ref (fn [r] (gobj/set this "fileinput" r))
:on-click (fn [evt] (when-let [i (gobj/get this "fileinput")]
(.click i)))
:on-change (fn [evt]
(let [env (comp/props this)
attribute (comp/get-computed this)
file (-> evt evt->js-files first)]
(blob/upload-file! this attribute file {:file-ident []})))}))}
(let [props (comp/props form-instance)
read-only? (or
(form/read-only? master-form attribute)
(form/read-only? form-instance attribute))
can-change? (if read-only? false (?! can-change? env attribute))
url-key (blob/url-key qualified-key)
name-key (blob/filename-key qualified-key)
current-sha (get props qualified-key)
url (get props url-key)
filename (get props name-key)
pct (blob/upload-percentage props qualified-key)
has-current-value? (seq current-sha)
{:keys [save-ref on-change on-click]} (comp/get-state this)
dirty? (if read-only? false (fs/dirty? props qualified-key))
label (form/field-label env attribute)
invalid? (if read-only? false (validation/invalid-attribute-value? env attribute))
validation-message (when invalid? (validation/validation-error-message env attribute))]
(div :.field {:key (str qualified-key)}
(dom/label label)
(cond
(blob/blob-downloadable? props qualified-key)
(dom/a {:href (str url "?filename=" filename)} "Download")
(blob/uploading? props qualified-key)
(dom/div :.ui.small.blue.progress
(div :.bar {:style {:transitionDuration "300ms"
:display "block"
:width pct}}
(div :.progress pct)))))))
(def ui-file-upload-field (comp/computed-factory FileUploadField
{:keyfn (fn [props] (some-> props comp/get-computed ::attr/qualified-key))}))
(defn render-file-upload [env attribute]
(ui-file-upload-field env attribute))