Skip to content

Instantly share code, notes, and snippets.

@kwrooijen
Created April 6, 2020 17:21
Show Gist options
  • Save kwrooijen/f9d196afce631ae28261530bc9a0a860 to your computer and use it in GitHub Desktop.
Save kwrooijen/f9d196afce631ae28261530bc9a0a860 to your computer and use it in GitHub Desktop.
(ns dnd.core
(:require
[reagent.core :as r]
[reagent.dom :as d]))
(def default-persons
[{:person/name "Kevin"
:person/age 29
:person/active? true}
{:person/name "Foo"
:person/age 99
:person/active? false}
{:person/name "Bar"
:person/age 20
:person/active? true}])
(def default-headers
[{:header/key :person/active?
:header/name "Active?"}
{:header/key :person/name
:header/name "Name"}
{:header/key :person/age
:header/name "Age"}])
(def state (r/atom
{:persons default-persons
:headers default-headers
:drag-hover nil
:dragging nil}))
(defn header-index-of [key]
(reduce (fn [acc {k :header/key}]
(if (= k key)
(reduced acc)
(inc acc)))
0
(:headers @state)))
(defn column-order []
(mapv :header/key (:headers @state)))
(defn on-drag-fn [key e]
(swap! state assoc :dragging key))
(defn on-drop-fn [key e]
(let [dragging (:dragging @state)
target-index (header-index-of key)
h (first (filter (comp #{dragging} :header/key) (:headers @state)))]
(swap! state dissoc :dragging key)
(when-not (= key dragging)
(swap! state update :headers #(remove (comp #{dragging} :header/key) %))
(let [[a b] (split-at target-index (:headers @state))]
(swap! state assoc :headers (vec (concat a [h] b)))))))
(defn person-column [v]
[:td.border-gray-200.border-b.border-1.px-8.py-2 (str v)])
(defn header-column [{:header/keys [key name]}]
[:th.border-gray-200.mx-1.px-8.border-b.border-1.py-2.text-white.bg-dark.cursor-pointer
{:draggable true
:class [(when (= key (:drag-hover @state)) :bg-blue-600)]
:on-drag-end #(swap! state assoc
:dragging nil
:drag-hover nil)
:on-drag-over (fn []
(js/event.preventDefault)
(swap! state assoc :drag-hover key))
:on-drag-leave #(swap! state assoc :drag-hover nil)
:on-drag (partial on-drag-fn key)
:on-drop (partial on-drop-fn key)}
name])
(defn person-row [person]
[:tr
(doall
(for [header-key (column-order)]
^{:key header-key}
[person-column (get person header-key)]))])
(defn person-table []
[:table.border-collapse
[:thead
[:tr
(doall
(for [{:header/keys [key] :as header} (:headers @state) ]
^{:key key}
[header-column header]))]]
[:tbody
(doall
(for [person (:persons @state) ]
^{:key (:person/name person)}
[person-row person]))]])
(defn home-page []
[:div.bg-gray-100
[:div.flex.items-center.justify-center.h-screen
[:div.bg-white.p-8
{:style {:width "400px" :height "400px"}}
[person-table]]]])
(defn mount-root []
(d/render [home-page] (.getElementById js/document "app")))
(defn ^:export init! []
(mount-root))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment