Skip to content

Instantly share code, notes, and snippets.

@dmohs
Created June 27, 2016 16:56
Show Gist options
  • Save dmohs/4cd40e44ed0e528103b390a288fa720e to your computer and use it in GitHub Desktop.
Save dmohs/4cd40e44ed0e528103b390a288fa720e to your computer and use it in GitHub Desktop.
Status component
(ns com.mohsdev.groceries.status
(:require
[com.mohsdev.groceries.server :as server]
[com.mohsdev.groceries.utils :as utils :refer [rlog jslog cljslog]]
[com.mohsdev.groceries.env :as env]
[dmohs.react :as react]
)
)
(def red "#b00")
(defn- update-state [request state]
(swap! state assoc :show? (or (:running? request) (:error-code request) (:expanded? @state))
:in-progress? (:running? request)
:error-code (:error-code request)
:pending-count (count @server/request-queue)))
(react/defc StatusControl
{:render
(fn [{:keys [state]}]
[:div {:style (merge {:position "fixed" :bottom "0.3em" :padding "0.5ex"
:minWidth "5ex" :minHeight "3ex"
:fontSize "smaller"}
(when-not (:show? @state) {:display "none"})
(if (:expanded? @state)
{:width "96%" :maxWidth "50ex" :boxSizing "border-box" :right "2%"
:backgroundColor "rgba(255, 255, 255, 0.9)"
:border "1px solid #d90" :borderRadius 4}
{:right 0 :cursor "pointer"}))
:onClick (when-not (:expanded? @state)
(fn [e] (swap! state update-in [:expanded?] not)))}
[:div {:style (merge {:fontSize "80%"}
(if (:expanded? @state)
{:float "right"}
{:position "absolute" :bottom "0.5ex" :right "0.5ex"}))}
[:span {:style {:display (when-not (:error-code @state) "none")
:marginRight "0.7ex"
:fontWeight "bold"
:backgroundColor red :color "#eee" :padding "0 0.9ex"
:borderRadius "1ex"}}
"!"]
[:span {:style {:display (when-not (> (:pending-count @state) 1) "none")
:marginRight "0.5ex"}}
(:pending-count @state)]
[:img {:src (str env/version-string "/spinner.gif")
:style (merge {:height "1.5em" :verticalAlign "bottom"}
(when-not (:in-progress? @state) {:display "none"}))}]
[:span {:style (merge {:fontWeight "bold" :fontSize "150%" :padding "0 0.5ex"
:cursor "pointer"}
(when-not (:expanded? @state) {:display "none"}))
:onClick (fn [e] (swap! state assoc :expanded? false))}
"×"]]
[:div {:style (merge {} (when-not (:expanded? @state) {:display "none"}))}
[:div {}
"There " (if (= (:pending-count @state) 1) "is" "are")
" "
(if (zero? (:pending-count @state)) "no" (:pending-count @state))
" operation"
(if (= (:pending-count @state) 1) " " "s ")
(if (:in-progress? @state) "in progress" "pending") "."]
[:div {:style {:color red :display (when-not (:error-code @state) "none")}}
"The last operation failed"
(case (:error-code @state)
:network " (network connection failure)"
"")
"." (when (:in-progress? @state) " Retrying...")]
(when-not (:in-progress? @state)
[:div {:style {:marginTop "0.5ex"
:display (when (zero? (:pending-count @state)) "none")}}
[:button {:onClick (fn [e] (server/start-request-processing))}
"Try Again"]])
]
])
:component-did-mount
(fn [{:keys [state]}]
(add-watch server/current-request ::current-request
(fn [k r os ns]
(if (and (not (:running? os)) (:running? ns))
(js/setTimeout (fn [] (update-state @server/current-request state)) 500)
(update-state ns state))))
(add-watch server/request-queue ::pending-count
(fn [k r os ns]
(when (zero? (count ns))
(update-state @server/current-request state))))
(update-state @server/current-request state))})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment