Skip to content

Commit

Permalink
[nested-grid] Polish docs
Browse files Browse the repository at this point in the history
  • Loading branch information
kimo-k committed Mar 22, 2024
1 parent 5af0003 commit 60d0594
Showing 1 changed file with 133 additions and 90 deletions.
223 changes: 133 additions & 90 deletions src/re_demo/nested_grid.cljs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(ns re-demo.nested-grid
(:require [re-com.core :as rc :refer [at h-box v-box box gap line label p p-span hyperlink-href]]
[reagent.core :as r]
[re-com.nested-grid :as nested-grid :refer [nested-grid nested-grid-args-desc nested-grid-parts-desc]]
[re-demo.utils :refer [source-reference panel-title title2 title3 args-table parts-table github-hyperlink status-text new-in-version]]))
(:require
[clojure.string :as str]
[re-com.core :as rc :refer [at h-box v-box box gap line label p p-span hyperlink-href]]
[reagent.core :as r]
[re-com.nested-grid :as nested-grid :refer [nested-grid nested-grid-args-desc nested-grid-parts-desc]]
[re-demo.utils :refer [source-reference panel-title title2 title3 args-table parts-table github-hyperlink status-text new-in-version]]))

(def arg-style {:style {:display "inline-block"
:font-weight "bold"
Expand Down Expand Up @@ -39,7 +41,7 @@
"darkyellow" "gold"})

(defn mix-colors [color1 color2]
(name (get-in color-mixer [color1 color2])))
(name (get-in color-mixer [(keyword color1) (keyword color2)])))

(mix-colors :red :yellow)

Expand All @@ -48,41 +50,42 @@
:children
[[p "Here's a grid with flat columns and rows."
" The " [:code ":cell"] " function closes over some external business logic ("
[:code "mix-colors"] ") to express a string value."
[:code "mix-colors"] ") to express a string."
" Since there is only one level of nesting, " [:code "column-path"]
" contains a single " [:code "column"] " value - for instance, "
" contains a single " [:i "header value"] " - for instance, "
[:code "[:red]"] "."]
[:pre "[nested-grid
:columns [:red :yellow :blue]
:rows [:red :yellow :blue]
:columns [\"red\" \"yellow\" \"blue\"]
:rows [\"red\" \"yellow\" \"blue\"]
:cell (fn color-cell [{:keys [column-path row-path]}]
(mix-colors (last column-path)
(last row-path)))]"]]])

(defn color-demo []
[nested-grid
:columns [:red :yellow :blue]
:rows [:red :yellow :blue]
:columns ["red" "yellow" "blue"]
:rows ["red" "yellow" "blue"]
:cell (fn color-cell [{:keys [row-path column-path]}]
(mix-colors (last row-path)
(last column-path)))])

(defn color-shade-explainer []
[rc/v-box
:children
[[p "Since " [:code ":columns"] " is a vector tree with 2 levels of nesting,"
[[p "Here, " [:code ":columns"] "is a nested " [:i "configuration"] " of " [:i "header values."]]
[p "Since the " [:i "configuration"] " has 2 levels of nesting,"
" each " [:code ":column-path"] " is 2-long. For instance, "
[:code "[:medium :yellow]"] ". "]
[p [:code ":cell"] " returns a hiccup."]
[p "Calling " [:code "(color-shade-cell {:column-path [:medium :yellow] :row-path [:blue]})"]
"should return a " [:span {:style {:color "green"}} "green"] " hiccup."]

[:pre "[nested-grid
{:columns [:medium [:red :yellow :blue]
:light [:red :yellow :blue]
:dark [:red :yellow :blue]]
:rows [:red :yellow :blue]
:cell color-shade-cell}]"]]])
:columns [:medium [:red :yellow :blue]
:light [:red :yellow :blue]
:dark [:red :yellow :blue]]
:rows [:red :yellow :blue]
:cell color-shade-cell]"]]])

(defn color-shade-cell [{:keys [row-path column-path]}]
(let [[row-hue] row-path
Expand Down Expand Up @@ -133,7 +136,7 @@

(def lookup-table [["🚓" "🛵" "🚲" "🛻" "🚚"]
["🍐" "🍎" "🍌" "🥝" "🍇"]
["🐈" "🐕" "🐟" "🐎" "🧸"]])
["🐕" "🐎" "🧸" "🐈" "🐟"]])

(def add {:operator + :label "Addition"})
(def multiply {:operator * :label "Multiplication"})
Expand All @@ -157,96 +160,91 @@
[title3 "Cells are Functions"]
[p "Each cell is a " [:i "function"] " of its grid position."]
[nested-grid
:columns [:a :b :c]
:rows [:x :y :z]
:columns ["a" "b" "c"]
:rows ["x" "y" "z"]
:column-width 40
:column-header-height 25
:row-header-width 30
:cell (fn [{:keys [column-path row-path]}] (pr-str (concat column-path row-path)))]
:cell (fn [{:keys [column-path row-path]}]
(str "(" (last column-path)
", " (last row-path) ")"))]
[title3 "Headers are Nested"]
[p "You can declare a tree of nested header values. "]
[p "You can declare headers as a nested " [:i "configuration."]]
[nested-grid
:columns [:a [:a1 :a2] :b [:b1 :b2]]
:rows [:x [:x1 :x2] :y [:y1 :y2]]
:column-header-height 25
:row-header-width 30
:column-width 90
:cell (fn [{:keys [column-path row-path]}]
(pr-str (list column-path row-path)))]
[p [:code ":columns"] " is a tree of nested " [:code "column"] " values. For instance: "]
[:pre ":columns [:a [:a1 :a2] :b [:b1 :b2]]
:rows [:x [:x1 :x2] :y [:y1 :y2]]"]
[p "That means each vertical partition you see is defined by a " [:code ":column-path"]
"(not simply a " [:code "column"] "). "
:cell (comp str seq (juxt :column-path :row-path))]
[p "Each vertical partition you see is defined by a " [:code ":column-path"] "."
"For instance, " [:code "[:a :a1]"] " is the first " [:code ":column-path"] "."]
[p "Same goes for rows. For instance, " [:code "[:y :y2]"] " is the last " [:code ":row-path"] "."]
[title3 "Headers can be Richly Declarative"]

[p "A " [:code ":column-path"] " is a vector of " [:code "column"] " values."]

[p "Anything can be a " [:code "column"] " value, "
[:i "except"] " a " [:code "list"] " or " [:code "vector"] " (those express nesting)."]

[nested-grid
:columns [add [one two]
multiply [one two]
lookup [one two]]
:rows [three four]
:row-header (comp :label last :row-path)
:column-header (comp :label last :column-path)
:row-header 20
:column-header-height 25
:row-header-width 100
:parts {:cell-wrapper {:style {:text-align "center"}}}
:cell (fn [{:keys [column-path row-path]}]
(let [{:keys [operator left right]} (->> (into row-path column-path)
(apply merge))]
(operator left right)))]
[:pre "(def lookup-table [[\"🚓\" \"🛵\" \"🚲\" \"🛻\" \"🚚\"]
[\"🍐\" \"🍎\" \"🍌\" \"🥝\" \"🍇\"]
[\"🐈\" \"🐕\" \"🐟\" \"🐎\" \"🧸\"]])
(def add {:operator + :label \"Addition\"})
(def multiply {:operator * :label \"Multiplication\"})
(def lookup {:operator (fn [l r] (get-in lookup-table [l r]))
:label \"Lookup\"})
(def one {:left 1 :label \"1\"})
(def two {:left 2 :label \"2\"})
(def three {:right 3 :label \" 3 \"})
(def four {:right 4 :label \" 4 \"})
[nested-grid
:columns [add [one two]
multiply [one two]
lookup [one two]]
:rows [three four]
:column-header (comp :label last :column-path)
:row-header (comp :label last :row-path)
:cell (fn [{:keys [column-path row-path]}]
(let [{:keys [operator left right]} (->> column-path
(into row-path)
(apply merge))]
(operator left right)))]"]
[title3 "Header Cells are Functions"]
[title3 "Cells are Views of Header Paths"]
[p "Each cell is a function of its location."]
[h-box
:gap "25px"
:children
[[nested-grid
:columns [:a :b :c]
:rows [:x [:x1 :x2]
:y [:y1 :y2]]
:column-width 70
:column-header-height 25
:row-header-width 30
:cell (fn [{:keys [column-path row-path]}]
[:i (str (list column-path row-path))])]
[v-box
:children
[[gap :size "20px"]
[:pre "[nested-grid
:columns [:a :b :c]
:rows [:x [:x1 :x2]
:y [:y1 :y2]]
:cell
(fn [{:keys [column-path row-path]}]
[:i (str (list column-path row-path))])]"]]]]]
[p "Specifically, the " [:code ":cell"] " prop accepts a function "
"of two keyword arguments: " [:code ":column-path"] " and " [:code ":row-path"] "."]
[p "The function counts as a "
[:a {:href "https://github.com/reagent-project/reagent/blob/master/doc/CreatingReagentComponents.md"}
"reagent component"] ", returning either a string or a hiccup."]
[title3 "Header Cells are Views, Too"]
[p "Just like " [:code ":cell"] ", the " [:code ":column-header"] " and " [:code ":row-header"] " props "
"are functions of paths."]
"are functions of their location."]
[p "The difference is, a " [:code ":column-header"] " only has a " [:code ":column-path"]
" and a " [:code ":row-header"] " only has a " [:code ":row-path"] "."]
[title3 "Headers are Richly Declarative"]
[p "A " [:code ":column-path"] " is a vector of " [:i "header values."]]
[p "Anything can be a " [:i "header value"] ", "
[:i "except"] " a " [:code "list"] " or " [:code "vector"] " (those express " [:i "configuration"] ")."]
[p "So far, we've looked at simple " [:i "header values"] ", like " [:code ":a"] " or " [:code "\"blue\""] "."]
[p "Another common use-case is a map, like " [:code "{:id :a :label \"A\" :type :letter}"] "."
"We consider a value like this to be a " [:i "header spec"] "."]
[title3 "Nested-grid + Domain Logic = Pivot Table"]
[:i {:style {:max-width "400px"}} "A pivot table is a table of values which are aggregations of groups of individual values from a more extensive table... within one or more discrete categories. (" [:a {:href "https://en.wikipedia.org/wiki/Pivot_table"} "Wikipedia"] ")"]
[:i {:style {:max-width "400px"}}
"A pivot table is a table of values which are aggregations of groups of individual values from a more extensive table..."
"within one or more discrete categories. (" [:a {:href "https://en.wikipedia.org/wiki/Pivot_table"} "Wikipedia"] ")"]
[:br]
[p "The pivot table is our driving use-case. "
"By separating UI presentation from data presentation, we hope "
[:code "nested-grid"] " makes it simple to build robust and flexible pivot tables."]
[p "In particular, your " [:code ":cell"] " function can close over concepts like " [:i "aggregations, groups, categories, dimensions, measures,"] " etc."]
[p "In the example above, " [:code "lookup-table"] "demonstrates the concept of "
[:i "a more extensive table."]
" Your " [:code ":columns"] " and " [:code ":rows"]
" can declare the necessary domain concepts, and your " [:code ":cell"] " function can dispatch on each concept, "
"accessing various " [:i "aggregations"] " and " [:i "groupings"] " of that table."]
[p "In " [:strong "Demo #3: Header Specifications"] ", " [:code "lookup-table"] "declares "
[:i "\"a more extensive table,\""]
" and the " [:code "lookup"] [:i "column spec"] " declares how to use that table."]
[p
"More generally:" [:br]
[:ul
[:li "Your " [:code ":columns"] " and " [:code ":rows"]
" declare the necessary domain concepts, such as "
[:i "\"aggregations\""] " and " [:i "\"groups.\""]]
[:li "Your " [:code ":cell"] " function dispatches on each concept, "
"deriving these " [:i "\"aggregations\""] " and " [:i "\"groups\""] " from "
[:i "\"a more extensive table.\""]]]]
[p "We also envision building an interactive, configurable pivot table. "
"By changing the value of " [:code ":columns"] " and " [:code ":rows"] ", you can reconfigure the UI presentation, and "
"your data presentation can simply follow along. "
"This can be done either programmatically or via a dedicated user interface."]]])
"By changing " [:code ":columns"] " and " [:code ":rows"] ", you could reconfigure the UI presentation, and "
"your data presentation would simply follow along. "
"This could be done either programmatically or via a dedicated user interface."]]])

;; core holds a reference to panel, so need one level of indirection to get figwheel updates
(defn panel
Expand Down Expand Up @@ -285,7 +283,7 @@
[v-box
:src (at)
:children
[[title2 "Demo #1"]
[[title2 "Demo #1: Flat Headers"]
[gap
:src (at)
:size "15px"]
Expand All @@ -298,13 +296,58 @@
:src (at)
:size "40px"]
[line :src (at)]
[title2 "Demo #2"]
[title2 "Demo #2: Nested Headers"]
[gap
:src (at)
:size "15px"]
[color-shade-demo]
[source-reference
"for above nested-grid"
"src/re_demo/nested_grid.cljs"]
[color-shade-explainer]]]]]
[color-shade-explainer]
[title2 "Demo #3: Header Specifications"]
[nested-grid
:columns [add [one two]
multiply [one two]
lookup [one two]]
:rows [three four]
:row-header (comp :label last :row-path)
:column-header (comp :label last :column-path)
:row-header 20
:column-header-height 25
:row-header-width 100
:parts {:cell-wrapper {:style {:text-align "center"}}}
:cell (fn [{:keys [column-path row-path]}]
(let [{:keys [operator left right]} (->> (into row-path column-path)
(apply merge))]
(operator left right)))]
[source-reference
"for above nested-grid"
"src/re_demo/nested_grid.cljs"]
[p "Here, we use " [:i "header specs"] " like " [:code "multiply"]
" and " [:code "lookup"] " to build a multi-modal view of the source data."]
[:pre "(def lookup-table [[\"🚓\" \"🛵\" \"🚲\" \"🛻\" \"🚚\"]
[\"🍐\" \"🍎\" \"🍌\" \"🥝\" \"🍇\"]
[\"🐕\" \"🐎\" \"🧸\" \"🐈\" \"🐟\"]])
(def add {:label \"Addition\" :operator +})
(def multiply {:label \"Multiplication\" :operator *})
(def lookup {:label \"Lookup\"
:operator (fn [l r] (get-in lookup-table [l r]))})
(def one {:label \"1\" :left 1})
(def two {:label \"2\" :left 2})
(def three {:label \"3\" :right 3})
(def four {:label \"4\" :right 4})
[nested-grid
:columns [add [one two]
multiply [one two]
lookup [one two]]
:rows [three four]
:column-header (comp :label last :column-path)
:row-header (comp :label last :row-path)
:cell (fn [{:keys [column-path row-path]}]
(let [{:keys [operator left right]} (->> column-path
(into row-path)
(apply merge))]
(operator left right)))]"]]]]]
#_[parts-table "nested-grid" nested-grid-grid-parts-desc]]])))

0 comments on commit 60d0594

Please sign in to comment.