Write upload handler
This commit is contained in:
parent
13fad6756e
commit
9fa17f6f6c
3 changed files with 68 additions and 12 deletions
3
deps.edn
3
deps.edn
|
|
@ -10,7 +10,8 @@
|
||||||
;; clojurescript build tool and dependencies (see also shadow-cljs.edn)
|
;; clojurescript build tool and dependencies (see also shadow-cljs.edn)
|
||||||
{:cljs {:extra-deps {thheller/shadow-cljs {:mvn/version "2.8.109"}
|
{:cljs {:extra-deps {thheller/shadow-cljs {:mvn/version "2.8.109"}
|
||||||
appliedscience/js-interop {:mvn/version "0.2.5"}
|
appliedscience/js-interop {:mvn/version "0.2.5"}
|
||||||
reagent {:mvn/version "1.0.0-alpha1"}}}
|
reagent {:mvn/version "1.0.0-alpha1"}
|
||||||
|
cljs-http {:mvn/version "0.1.46"}}}
|
||||||
|
|
||||||
;; packaging the server as a standalone jar for production
|
;; packaging the server as a standalone jar for production
|
||||||
:uberjar {:extra-deps {luchiniatwork/cambada {:mvn/version "1.0.2"}}
|
:uberjar {:extra-deps {luchiniatwork/cambada {:mvn/version "1.0.2"}}
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@
|
||||||
|
|
||||||
(def rfc3339 (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ssXXX"))
|
(def rfc3339 (java.text.SimpleDateFormat. "yyyy-MM-dd'T'HH:mm:ssXXX"))
|
||||||
|
|
||||||
(defn upload! [file id]
|
(defn upload! [file predictions]
|
||||||
(let [now (.format rfc3339 (java.util.Date.))
|
(let [now (.format rfc3339 (java.util.Date.))
|
||||||
uuid (java.util.UUID/randomUUID)
|
uuid (java.util.UUID/randomUUID)
|
||||||
ext (re-find #"\.[\w]+$" (-> file :filename))]
|
ext (re-find #"\.[\w]+$" (-> file :filename))
|
||||||
(io/copy (-> file :tempfile)
|
filename (str "uploads/" now "--" uuid)]
|
||||||
(io/file (str "uploads/" id "--" now "--" uuid ext)))))
|
(io/copy (-> file :tempfile) (io/file (str filename ext)))
|
||||||
|
(spit (str filename ".json") predictions)))
|
||||||
|
|
||||||
(def app
|
(def app
|
||||||
(ring/ring-handler
|
(ring/ring-handler
|
||||||
|
|
@ -22,10 +23,10 @@
|
||||||
[["/upload"
|
[["/upload"
|
||||||
;; TODO: Verify params
|
;; TODO: Verify params
|
||||||
{:post (fn [req]
|
{:post (fn [req]
|
||||||
(let [{:keys [file friend]} (-> req :params)]
|
(let [{:keys [snapshot predictions]} (-> req :params)]
|
||||||
(upload! file friend)
|
(upload! snapshot predictions)
|
||||||
{:status 201
|
{:status 201
|
||||||
:body (str "Thanks, " friend)}))}]]
|
:body (str "Thanks :)")}))}]]
|
||||||
["/*" (ring/create-resource-handler)])))
|
["/*" (ring/create-resource-handler)])))
|
||||||
|
|
||||||
(defonce server (atom nil))
|
(defonce server (atom nil))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
(ns heyarne.all-my-friends.views
|
(ns heyarne.all-my-friends.views
|
||||||
(:require [reagent.core :as r]
|
(:require [reagent.core :as r]
|
||||||
|
[cljs-http.client :as http]
|
||||||
|
[cljs.core.async :refer [<! go]]
|
||||||
[heyarne.all-my-friends.facemesh :refer [webcam-facemesh]]
|
[heyarne.all-my-friends.facemesh :refer [webcam-facemesh]]
|
||||||
[heyarne.all-my-friends.visualize :as vis]))
|
[heyarne.all-my-friends.visualize :as vis]))
|
||||||
|
|
||||||
|
|
@ -7,13 +9,41 @@
|
||||||
|
|
||||||
(defonce state (r/atom {:status :welcome-message}))
|
(defonce state (r/atom {:status :welcome-message}))
|
||||||
|
|
||||||
|
(declare dispatch)
|
||||||
|
|
||||||
(def events
|
(def events
|
||||||
{:welcome/continue (fn [db _]
|
{:welcome/continue (fn [db _]
|
||||||
(assoc db :status :running))
|
(assoc db :status :running))
|
||||||
:running/snapshot (fn [db result]
|
:running/snapshot (fn [db result]
|
||||||
(assoc-in db [:snapshots :current] result))
|
(assoc-in db [:snapshots :current] result))
|
||||||
:running/discard-snapshot (fn [db _]
|
:running/discard-snapshot (fn [db _]
|
||||||
(update db :snapshots dissoc :current))})
|
(update db :snapshots dissoc :current))
|
||||||
|
:upload/post (fn [db post-body]
|
||||||
|
;; TODO: This is a bit dirty compared to the others because it
|
||||||
|
;; shoehorns http requests and database changes together
|
||||||
|
(let [req (http/post "/upload" {:multipart-params post-body})]
|
||||||
|
(println "request started")
|
||||||
|
(go (let [{:keys [success body error-text] :as res} (<! req)]
|
||||||
|
(prn res)
|
||||||
|
(if success
|
||||||
|
(dispatch [:upload/done (:message body)])
|
||||||
|
(dispatch [:upload/error error-text]))
|
||||||
|
(println "request finished")))
|
||||||
|
(assoc db :in-progress? true)))
|
||||||
|
:upload/error (fn [db message]
|
||||||
|
(dispatch [:message/show {:message message, :type :error}])
|
||||||
|
(dissoc db :in-progress?))
|
||||||
|
:upload/done (fn [db _]
|
||||||
|
(dispatch [:message/show {:message "Tippi toppi!", :type :success}])
|
||||||
|
(dissoc db :in-progress?))
|
||||||
|
:message/show (fn [db {:keys [message type]}]
|
||||||
|
(let [message-id (* (Math/random) (js/Date.now))]
|
||||||
|
(when (= type :success)
|
||||||
|
(js/window.setTimeout #(dispatch [:message/hide message-id]) 2500))
|
||||||
|
(assoc-in db [:messages message-id] {:type type
|
||||||
|
:message message})))
|
||||||
|
:message/hide (fn [db message-id]
|
||||||
|
(update db :messages dissoc message-id))})
|
||||||
|
|
||||||
(defn dispatch [[event data]]
|
(defn dispatch [[event data]]
|
||||||
(when-let [handler (events event)]
|
(when-let [handler (events event)]
|
||||||
|
|
@ -39,6 +69,14 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
|
||||||
(.drawImage ctx video-elem 0 0 (.-width canvas) (.-height canvas))
|
(.drawImage ctx video-elem 0 0 (.-width canvas) (.-height canvas))
|
||||||
(.getImageData ctx 0 0 (.-width canvas) (.-height canvas))))
|
(.getImageData ctx 0 0 (.-width canvas) (.-height canvas))))
|
||||||
|
|
||||||
|
(defn image-data->blob [img-data cb]
|
||||||
|
(let [canvas (js/document.createElement "canvas")
|
||||||
|
ctx (.getContext canvas "2d")]
|
||||||
|
(set! (.-width canvas) (.-width img-data))
|
||||||
|
(set! (.-height canvas) (.-height img-data))
|
||||||
|
(.putImageData ctx img-data 0 0)
|
||||||
|
(.toBlob canvas cb "image/png")))
|
||||||
|
|
||||||
(defn preview [{{:keys [video predictions]} :snapshot}]
|
(defn preview [{{:keys [video predictions]} :snapshot}]
|
||||||
(let [canvas (js/document.createElement "canvas")
|
(let [canvas (js/document.createElement "canvas")
|
||||||
ctx (.getContext canvas "2d")]
|
ctx (.getContext canvas "2d")]
|
||||||
|
|
@ -55,9 +93,20 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
|
||||||
[:div#snapshot-preview.container
|
[:div#snapshot-preview.container
|
||||||
[:p compliment]
|
[:p compliment]
|
||||||
[preview {:snapshot current-snapshot}]
|
[preview {:snapshot current-snapshot}]
|
||||||
[:button {:on-click #(println "submit")} "Abschicken"]
|
[:button {:on-click #(image-data->blob (:video current-snapshot)
|
||||||
|
(fn [blob]
|
||||||
|
(dispatch
|
||||||
|
[:upload/post {:snapshot blob
|
||||||
|
:predictions (js/JSON.stringify (:predictions current-snapshot))}])))}
|
||||||
|
"Abschicken"]
|
||||||
[:button {:on-click #(dispatch [:running/discard-snapshot])} "Lieber noch eins"]]))
|
[:button {:on-click #(dispatch [:running/discard-snapshot])} "Lieber noch eins"]]))
|
||||||
|
|
||||||
|
(defn notifications [{:keys [messages]}]
|
||||||
|
[:ul.notifications
|
||||||
|
(for [[id {:keys [type message]}] messages]
|
||||||
|
^{:key id} [:li.message {:class (name type)
|
||||||
|
:on-click #(dispatch [:message/hide id])} message])])
|
||||||
|
|
||||||
(defn running [{:keys [on-faces-detected halt?]}]
|
(defn running [{:keys [on-faces-detected halt?]}]
|
||||||
(let [result (atom {:video nil
|
(let [result (atom {:video nil
|
||||||
:predictions nil})]
|
:predictions nil})]
|
||||||
|
|
@ -75,15 +124,20 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
|
||||||
(defn app []
|
(defn app []
|
||||||
(let [state @state
|
(let [state @state
|
||||||
status (:status state)
|
status (:status state)
|
||||||
current-snapshot (get-in state [:snapshots :current])]
|
messages (:messages state)
|
||||||
|
current-snapshot (get-in state [:snapshots :current])
|
||||||
|
uploading? (some? (get-in state [:http/requests "/upload"]))]
|
||||||
|
(prn messages)
|
||||||
[:<>
|
[:<>
|
||||||
[welcome-message {:hidden? (not= :welcome-message status)}]
|
[welcome-message {:hidden? (not= :welcome-message status)}]
|
||||||
|
[notifications {:messages messages}]
|
||||||
|
(when uploading?
|
||||||
|
[:p "Bild wird hochgeladen"])
|
||||||
(when current-snapshot
|
(when current-snapshot
|
||||||
[snapshot {:current-snapshot current-snapshot}])
|
[snapshot {:current-snapshot current-snapshot}])
|
||||||
(case status
|
(case status
|
||||||
:permission-rejected [:div "Sad :("]
|
:permission-rejected [:div "Sad :("]
|
||||||
:running [running {:on-faces-detected vis/draw-sketch
|
:running [running {:on-faces-detected vis/draw-sketch
|
||||||
:halt? (some? current-snapshot)}]
|
:halt? (some? current-snapshot)}]
|
||||||
|
|
||||||
;; default
|
;; default
|
||||||
nil)]))
|
nil)]))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue