Generate whole sidebar in cljs; change icon to back arrow based on context

This commit is contained in:
Jeremy Dormitzer 2018-01-30 23:04:35 -07:00
parent a7c6f88581
commit 1865b70f73
No known key found for this signature in database
GPG Key ID: 04F17C0F5A32C320
3 changed files with 122 additions and 101 deletions

View File

@ -9,16 +9,7 @@
<script src="js/generated/out/cljs_base.js"></script>
</head>
<body>
<div id="sidebar">
<div class="sidebarHeader">
<img class="headerIcon" src="icons/icon48.png" width="16px" height="16px">
<span class="body30 headerTitle">Looped In</span>
<button class="iconButton" id="closeSidebar">
<img src="icons/stop-16.svg" width="16px" height="16px">
</button>
</div>
<div id="sidebarContent"></div>
</div>
<div id="sidebar"></div>
<script src="js/generated/sidebar.js"></script>
</body>
</html>

View File

@ -24,6 +24,9 @@
(dom/appendChild el child)
el)
(defn sidebar-content [& body]
(apply dom/createDom "div" (clj->js {:id "sidebarContent"}) body))
(defn comments-indicator [num-comments]
(let [text (caption30 (str num-comments " comment" (when (not= num-comments 1) "s")))]
(dom/createDom "div"
@ -105,6 +108,22 @@
(for [i (range 1 6)]
(dom/createDom "div" (str "rect" i)))))
(defn sidebar-header [icon-src]
(dom/createDom "div" "sidebarHeader"
(dom/createDom "img"
(clj->js {:class "headerIcon"
:src icon-src
:width "16px"
:height "16px"}))
(dom/createDom "span" "body30 headerTitle" "Looped In")
(dom/createDom "button"
(clj->js {:class "iconButton"
:id "closeSidebar"})
(dom/createDom "img"
(clj->js {:src "icons/stop-16.svg"
:width "16px"
:height "16px"})))))
(defn with-classes [el & classes]
(doseq [class (filter #(not (string/blank? %)) classes)]
(classes/add el class))

View File

@ -76,117 +76,129 @@
[dispatch-message state]
(log/debug state)
(cond
(:loading state) (components/loader)
(:item state) (let [current-item (get-in-item
(:item state)
(:depth state))]
(cons
(case (:type current-item)
"story" (components/card
(:loading state) (list (components/sidebar-header "icons/icon48.png")
(components/sidebar-content (components/loader)))
(:item state) (list
(components/sidebar-header "icons/back-16.svg")
(apply
components/sidebar-content
(let [current-item (get-in-item
(:item state)
(:depth state))]
(cons
(case (:type current-item)
"story" (components/card
(dom/createDom
"div"
"storyHeader"
(components/body30 (:title current-item))
(components/item-link (:id current-item)))
(components/story-caption (:points current-item)
(:author current-item)
(* (:created_at_i current-item) 1000)))
"comment" (components/card
(dom/createDom
"div"
"commentHeader"
(components/comment-caption (:author current-item)
(* (:created_at_i current-item)
1000))
(components/item-link (:id current-item)))
(components/comment-text (:text current-item))))
(map-indexed (fn [index child]
(-> (components/card
(dom/createDom
"div"
"commentHeader"
(components/comment-caption
(:author child)
(* (:created_at_i child) 1000))
(components/item-link (:id child)))
(components/comment-text (:text child))
(-> (components/replies-indicator (count (:children child)))
((fn [indicator]
(if (> (count (:children child)) 0)
(-> indicator
(components/with-classes "clickable")
(components/with-listener
"click"
(fn [e]
(dispatch-message
{:type :enq-depth
:index index}))))
indicator)))))
(components/with-classes "child")
((fn [card]
(if (> (count (:children child)) 0)
(components/with-classes card "clickable")
card)))))
(->> (:children current-item)
(filter #(contains? % :text))
(sort-by #(count (:children %)) #(compare %2 %1))))))))
(:hits state) (list
(components/sidebar-header "icons/icon48.png")
(apply
components/sidebar-content
(map (fn [hit]
(-> (components/card
(dom/createDom
"div"
"storyHeader"
(components/body30 (:title current-item))
(components/item-link (:id current-item)))
(components/story-caption (:points current-item)
(:author current-item)
(* (:created_at_i current-item) 1000)))
"comment" (components/card
(dom/createDom
"div"
"commentHeader"
(components/comment-caption (:author current-item)
(* (:created_at_i current-item) 1000))
(components/item-link (:id current-item)))
(components/comment-text (:text current-item))))
(map-indexed (fn [index child]
(-> (components/card
(dom/createDom
"div"
"commentHeader"
(components/comment-caption
(:author child)
(* (:created_at_i child) 1000))
(components/item-link (:id child)))
(components/comment-text (:text child))
(-> (components/replies-indicator (count (:children child)))
((fn [indicator]
(if (> (count (:children child)) 0)
(-> indicator
(components/with-classes "clickable")
(components/with-listener
"click"
(fn [e]
(dispatch-message
{:type :enq-depth
:index index}))))
indicator)))))
(components/with-classes "child")
((fn [card]
(if (> (count (:children child)) 0)
(components/with-classes card "clickable")
card)))))
(->> (:children current-item)
(filter #(contains? % :text))
(sort-by #(count (:children %)) #(compare %2 %1))))))
(:hits state) (map (fn [hit]
(-> (components/card
(dom/createDom
"div"
"storyHeader"
(components/body30 (:title hit))
(components/item-link (:objectID hit)))
(components/story-caption (:points hit)
(:author hit)
(* (:created_at_i hit) 1000))
(-> (components/comments-indicator (:num_comments hit))
((fn [indicator]
(if (> (:num_comments hit) 0)
(-> indicator
(components/with-classes "clickable")
(components/with-listener
"click"
(fn [e]
(dispatch-message {:type :loading :loading true})
(go
(-> (fetch-item (:objectID hit))
(<!)
((fn [item]
(dispatch-message
{:type :got-item :item item}))))))))
indicator)))))
((fn [card]
(if (> (:num_comments hit) 0)
(components/with-classes card "clickable")
card)))))
(:hits state))
#_(let [current-item (get-in-items (:items state) (:depth state))]
(if (> (count current-item) 1)
(map #(components/card (:title %)) current-item)
()))))
(components/body30 (:title hit))
(components/item-link (:objectID hit)))
(components/story-caption (:points hit)
(:author hit)
(* (:created_at_i hit) 1000))
(-> (components/comments-indicator (:num_comments hit))
((fn [indicator]
(if (> (:num_comments hit) 0)
(-> indicator
(components/with-classes "clickable")
(components/with-listener
"click"
(fn [e]
(dispatch-message {:type :loading :loading true})
(go
(-> (fetch-item (:objectID hit))
(<!)
((fn [item]
(dispatch-message
{:type :got-item :item item}))))))))
indicator)))))
((fn [card]
(if (> (:num_comments hit) 0)
(components/with-classes card "clickable")
card)))))
(:hits state))))))
(defn render
"Renders the new DOM
This is where clever diffing algorithms would go if this was React"
[$sidebar-dom]
(let [$container (dom/getElement "sidebarContent")]
(let [$container (dom/getElement "sidebar")]
(dom/removeChildren $container)
(.scrollTo js/window 0 0)
(if (seqable? $sidebar-dom)
(apply dom/append $container $sidebar-dom)
(dom/append $container $sidebar-dom))))
(defn handle-close-button [e]
(.postMessage js/window.parent (clj->js {:type "closeSidebar"}) "*"))
(defn handle-events
"Registers event listeners"
[state]
(events/listen (dom/getElement "closeSidebar") "click" handle-close-button))
(defn run-render-loop
"Runs the model-update-view loop"
[state]
(let [dispatch-message (fn [msg]
(let [new-state (update-state msg state)]
(run-render-loop new-state)))]
(render (view dispatch-message state))))
(defn handle-close-button [e]
(.postMessage js/window.parent (clj->js {:type "closeSidebar"}) "*"))
(render (view dispatch-message state))
(handle-events state)))
(defn fetch-hits
"Fetch hits in the Algolia API matching the URL"
@ -202,7 +214,6 @@
(defn init
"Initializes the sidebar"
[]
(events/listen (dom/getElement "closeSidebar") "click" handle-close-button)
(let [initial-state (update-state {:type :loading :loading true} (model))]
(run-render-loop initial-state)
(go (-> (fetch-hits)