From 7b9fbc95ce595d928814751175f4dd1fcf544620 Mon Sep 17 00:00:00 2001 From: Kimo Knowles Date: Fri, 22 Mar 2024 01:40:34 +0100 Subject: [PATCH] [nested-grid] Polish docs --- src/re_demo/nested_grid.cljs | 159 +++++++++++++++++++---------------- 1 file changed, 88 insertions(+), 71 deletions(-) diff --git a/src/re_demo/nested_grid.cljs b/src/re_demo/nested_grid.cljs index af58233e..2942e7cd 100644 --- a/src/re_demo/nested_grid.cljs +++ b/src/re_demo/nested_grid.cljs @@ -39,7 +39,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) @@ -53,16 +53,16 @@ " contains a single " [:code "column"] " 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)))]) @@ -133,7 +133,7 @@ (def lookup-table [["🚓" "🛵" "🚲" "🛻" "🚚"] ["🍐" "🍎" "🍌" "🥝" "🍇"] - ["🐈" "🐕" "🐟" "🐎" "🧸"]]) + ["🐕" "🐎" "🧸" "🐈" "🐟"]]) (def add {:operator + :label "Addition"}) (def multiply {:operator * :label "Multiplication"}) @@ -164,89 +164,61 @@ :row-header-width 30 :cell (fn [{:keys [column-path row-path]}] (pr-str (concat column-path 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]]"] + :cell (comp str seq (juxt :column-path :row-path))] + [:pre "[nested-grid + :columns [:a [:a1 :a2] :b [:b1 :b2]] + :rows [:x [:x1 :x2] :y [:y1 :y2]] + :cell cell-fn]"] + [p "Here, " [:code ":columns"] "is a nested " [:i "configuration"] " of " [:code "header"] " values."] [p "That means each vertical partition you see is defined by a " [:code ":column-path"] "(not simply a " [:code "column"] "). " "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 "Headers are Richly Declarative"] + [p "A " [:code ":column-path"] " is a vector of " [:code "header"] " values."] + [p "Anything can be a " [:code "header"] " value, " + [:i "except"] " a " [:code "list"] " or " [:code "vector"] " (those express " [:i "configuration"] ")."] + [p "So far, we've looked at simple " [:code "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"] "."] + [p + " to build a multi-modal view of its source data."] [title3 "Header Cells are Functions"] [p "Just like " [:code ":cell"] ", the " [:code ":column-header"] " and " [:code ":row-header"] " props " "are functions of paths."] [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 "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 @@ -285,7 +257,7 @@ [v-box :src (at) :children - [[title2 "Demo #1"] + [[title2 "Demo #1: Flat Headers"] [gap :src (at) :size "15px"] @@ -298,7 +270,7 @@ :src (at) :size "40px"] [line :src (at)] - [title2 "Demo #2"] + [title2 "Demo #2: Nested Headers"] [gap :src (at) :size "15px"] @@ -306,5 +278,50 @@ [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]]])))