Created
April 6, 2020 17:21
-
-
Save kwrooijen/f9d196afce631ae28261530bc9a0a860 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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