Skip to content

Instantly share code, notes, and snippets.

@devn
Last active September 10, 2019 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devn/6b6254013728fe2b952d71f83ed782ce to your computer and use it in GitHub Desktop.
Save devn/6b6254013728fe2b952d71f83ed782ce to your computer and use it in GitHub Desktop.
(defn ^:private item-offset-for-rule
[rule y]
(when (isa? (:type rule) ::rule/rule-group)
(let [rule-element (.getElementById js/document (:id rule))
li-elements (-> (.-children rule-element)
(aget 1)
(.-children))
num-li-elements (.-length li-elements)]
(loop [index 0]
(if (< index num-li-elements)
(let [li-element (aget li-elements index)
rect (.getBoundingClientRect li-element)
top (.-top rect)
height (.-height rect)
cut-off (+ top
(/ height
2))]
(if (< y cut-off)
index
(recur (inc index))))
index)))))
(defn rule-component [rule db]
(let [hover? (reagent/atom false)
drop-target (reagent/cursor db [:drop-target])
dragged-rule (reagent/cursor db [:dragged-rule])
active-drop-target? (reagent.atom/make-reaction
#(= rule @drop-target))
dragged? (reagent.atom/make-reaction
#(= rule @dragged-rule))
eligible-drag-target? (reagent.atom/make-reaction
#(when @dragged-rule
(rule/accepts? rule @dragged-rule)))
when-drop-target (fn [f]
(fn [e]
(when @eligible-drag-target?
(.stopPropagation e)
(f e))))
on-this-target (fn [f]
(fn [e]
(when (= (:id rule)
(.-id (.-target e)))
(.stopPropagation e)
(f e))))
disabled? (reagent.atom/make-reaction
#(rule/disabled? rule db))]
(fn rule-component* [rule db]
[:li
{:class [:card
(:type rule)
(when @disabled?
:disabled)
(when @hover?
:hover)
(when @active-drop-target?
:active-drop-target)
(when @dragged?
:dragged)]
:draggable (not @disabled?)
:on-drag-start (on-this-target
(fn [e]
(let [[effect rule] (rule/drag-effect-and-rule rule)]
(set! (.-effectAllowed (.-dataTransfer e))
effect)
(reset! dragged-rule rule)
(reset! hover? false))))
:on-drag-end (on-this-target
#(swap! db dissoc :dragged-rule :drop-target))
:on-drag-enter (when-drop-target
(fn [_]
(swap! db assoc :drop-target rule)))
:on-drag-leave (when-drop-target
(fn [e]
(let [entering (.-relatedTarget e)]
(when (or (nil? entering)
(= (.-parentNode (.-target e))
entering))
(swap! db dissoc :drop-target)))))
:on-drop (when-drop-target
(fn [e]
(let [offset (item-offset-for-rule rule (.-clientY e))]
(when (model/unassigned? db @dragged-rule)
(println "Removing" (:name @dragged-rule) "from available")
(println "Dragged rule:" (pr-str @dragged-rule))
(println "Number of availabe before:" (count (:available @db)))
(let [sorted-names (fn [db] (into (sorted-set)
(map :name (:available @db))))
sorted-names-before (sorted-names db)
_ (println sorted-names-before)
_ (reagent/rswap! db update :available disj @dragged-rule)
_ (println "Number of available after:" (count (:available @db)))
sorted-names-after (sorted-names db)
_ (println sorted-names-after)]
(println "Difference old and new available items:"
(clojure.set/difference sorted-names-before sorted-names-after)))))))
:on-drag-over (when-drop-target
(fn [e]
(println "dragging"
(:name @dragged-rule)
"over"
(:name rule))
(let [data (.-dataTransfer e)
effect (.-effectAllowed data)]
(set! (.-dropEffect data) effect))
(.preventDefault e)))
:on-mouse-over (on-this-target #(reset! hover? true))
:on-mouse-out (on-this-target #(reset! hover? false))
:id (:id rule)
:key (:id rule)
:title (rule/hover-text rule db)}
[:span (:name rule)]
(when (isa? (:type rule) ::rule/rule-group)
(into [:ul]
(map (fn [r] [rule-component r db]))
(:children rule)))])))
(defn ^:private available-items-list
[db]
[:section
[:header [:h2.h4 "Available Items"]]
(let [{:keys [available]} @db]
(if (empty? available)
[:p "No available items"]
(into [:ul.card-list]
(map (fn [r] [rule-component r db]))
available)))])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment