Skip to content

Instantly share code, notes, and snippets.

@suseek
Forked from anonymous/upload.cljs
Created April 15, 2018 11:47

Revisions

  1. @invalid-email-address Anonymous created this gist Apr 29, 2015.
    116 changes: 116 additions & 0 deletions upload.cljs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    (defn upload! [owner]
    (let [form (om/get-node owner "upload-form")
    io (goog.net.IframeIo.)]
    (goog.events.listen
    io goog.net.EventType.COMPLETE #(js/console.log "COMPLETE"))
    (goog.events.listen
    io goog.net.EventType.SUCCESS (fn [_]
    (put!
    (om/get-state owner :reset-file-drop)
    true)
    (->> io
    .getResponseJson
    js->clj
    (map-keys keyword)
    (swap! app-state update-in
    [:attachments] conj))))
    (goog.events.listen
    io goog.net.EventType.ERROR #(js/console.log "ERROR"))
    (goog.events.listen
    io goog.net.EventType.TIMEOUT #(js/console.log "TIMEOUT"))
    (.sendFromForm io form)))

    (defn FileDrop [{:keys [on-change reset-ch] :as props} owner]
    (reify
    om/IDisplayName (display-name [_] "FileDrop")
    om/IDidMount
    (did-mount [_]
    (goog.events.listen
    (goog.events.FileDropHandler. js/document)
    goog.events.FileDropHandler.EventType.DROP
    #(set!
    (.-files (om/get-state owner :holder))
    (.. % getBrowserEvent -dataTransfer -files)))
    (go-loop []
    (when (<! reset-ch)
    (let [holder (goog.dom.createDom "input" #js {:type "file"})]
    (goog.events.listen
    holder goog.events.EventType.CHANGE
    #(om/set-state! owner :file
    (-> % .-target .-files (.item 0) .-name)))
    (om/set-state! owner {:holder holder :file nil}))
    (recur)))
    (put! reset-ch true))
    om/IDidUpdate
    (did-update [_ _ prev-state]
    (set! (.-files (om/get-node owner "input"))
    (.-files (om/get-state owner :holder)))
    (let [file (om/get-state owner :file)]
    (when (and on-change (not= file (:file prev-state)))
    (on-change file))))
    om/IRenderState
    (render-state [_ {:keys [file holder]}]
    (html [:div
    [:div {:on-click #(.click holder)}
    [:h3.text-center.dropzone
    (or file (:placeholder props)
    "Drop file here or click to upload")]]
    [:input.hidden
    {:ref "input" :type "file" :name (:name props)}]]))))

    (defn UploadData [_ owner]
    (reify
    om/IDisplayName (display-name [_] "UploadData")
    om/IInitState
    (init-state [_]
    {:reset-file-drop (chan)})
    om/IRenderState
    (render-state [_ {:keys [file filename reset-file-drop]}]
    (let [attachments (observe-path owner [:attachments])
    upload-form (observe-path owner [:upload_form])
    uff (:fields upload-form)]
    (html [:div.UploadData
    [:form#upload-form
    {:ref "upload-form"
    :method "POST"
    :action (:url upload-form)
    :enc-type "multipart/form-data"}
    [:input {:type "hidden"
    :name "csrfmiddlewaretoken"
    :value (get-in uff [:csrfmiddlewaretoken :initial])
    #_(.get (goog.net.Cookies. js/document) "csrftoken")}]
    [:input {:type "hidden"
    :name "document"
    :value (get-in uff [:document :initial])}]
    [:div.form-group
    [:label "Filename"]
    [:input.form-control
    {:type "text"
    :name "name"
    :value filename
    :on-change #(om/set-state! owner :filename
    (.. % -target -value))}]]
    (om/build FileDrop
    {:name "file"
    :reset-ch reset-file-drop
    :on-change (fn [name]
    (om/set-state-nr! owner :file name)
    (when (or (= filename file)
    (blank? filename))
    (om/set-state!
    owner :filename name)))})]
    [:button.btn.btn-primary
    {:on-click #(upload! owner)
    :disabled (when-not (not-any? blank? [file filename]) "disabled")}
    "Upload"]
    [:h3 "Uploaded files"]
    [:div
    [:table.table.table-hover
    [:thead
    [:tr [:th "Id"] [:th "Name"] [:th "Created"]]]
    [:tbody
    (for [a attachments]
    [:tr
    [:td (:id a)]
    [:td [:a {:href (:file a)} (:name a)]]
    [:td (-> a :created js/Date. .toDateString)]])]]]])))))