Series.purs 6.84 KB
Newer Older
Sudhir Kumar's avatar
Sudhir Kumar committed
1
module Gargantext.Components.Charts.Options.Series where
2

3
import Prelude (class Show, bind, map, pure, show, ($), (+), (<<<), (<>))
4 5 6

import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson, (.:), (~>), (:=))
import Data.Argonaut.Core (jsonEmptyObject)
7
import Data.Array (foldl)
8
import Data.Maybe (Maybe(..), maybe)
9
import Record.Unsafe (unsafeSet)
10
import Unsafe.Coerce (unsafeCoerce)
11

12
import Gargantext.Types (class Optional)
13 14
import Gargantext.Components.Charts.Options.Font (ItemStyle, Tooltip)
import Gargantext.Components.Charts.Options.Data (DataD1, DataD2)
15

16 17
newtype SeriesType = SeriesType String

18 19
type SeriesName = String

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

data Chart = Line
           | Bar | PictorialBar
           | Pie
           | Scatter | EffectScatter
           | Radar
           | Trees
           | Sunburst
           | Boxplot
           | Candlestick
           | Heatmap
           | Map
           | Parallel
           | Lines
           | Graph
           | Sankey
           | Funnel
           | Gauge
           | ThemeRiver
-- Trees

instance showChart :: Show Chart where
42
  show Bar      = "bar"
43
  show EffectScatter = "effectScatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-effect
44 45
  show Funnel   = "funnel"
  show Heatmap  = "heatmap"
46 47 48
  show Line     = "line"
  show Pie      = "pie"
  show Sankey   = "sankey"
49
  show Scatter  = "scatter"            -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple
50 51
  show Sunburst = "sunburst"
  show _        = "not implemented yet: should throw error here"
52

53
seriesType :: Chart -> SeriesType
54 55
seriesType = SeriesType <<< show

56

57 58 59 60 61 62 63 64 65 66 67 68
-- | Scatter Dimension 2 data
type OptionalSeries =
  ( name       :: String
  , symbolSize :: Number
  , itemStyle  :: ItemStyle
    -- ^ Graphic style of, *emphasis* is the style when it is highlighted, like being hovered by mouse, or highlighted via legend connect.
    --   https://ecomfe.github.io/echarts-doc/public/en/option.html#series-scatter.itemStyle
  , tooltip    :: Tooltip

  -- many more...
  )

69
data Series
70

71
unsafeSeries :: forall o. Record o -> Series
72 73
unsafeSeries = unsafeCoerce

74
type RequiredSeriesD1 o =
75
  { "type" :: SeriesType
76
  , "data" :: Array DataD1
77
  | o
78
  }
79

80
seriesD1 :: forall o. Optional o OptionalSeries => RequiredSeriesD1 o -> Series
81 82
seriesD1 = unsafeSeries

83 84
seriesFunnelD1 :: forall o. Optional o OptionalSeries => Record o -> Array DataD1 -> Series
seriesFunnelD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesType Funnel) o))
85

86 87
seriesBarD1 :: forall o. Optional o OptionalSeries => Record o -> Array DataD1 -> Series
seriesBarD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesType Bar) o))
88

89 90
seriesPieD1 :: forall o. Optional o OptionalSeries => Record o -> Array DataD1 -> Series
seriesPieD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesType Pie) o))
91

92 93
type RequiredSeriesD2 o =
  { "data" :: Array DataD2
94
  , "type" :: SeriesType
95
  | o
96
  }
97

98
seriesD2 :: forall o. Optional o OptionalSeries => RequiredSeriesD2 o -> Series
99
seriesD2 = unsafeSeries
100

101
seriesScatterD2 :: forall o. Optional o OptionalSeries => Record o -> Array DataD2 -> Series
102
seriesScatterD2 o ds =
103
  unsafeCoerce (unsafeSet "data" ds (unsafeSet "type" (seriesType Scatter) o))
104 105 106 107 108

type Node = { name :: String}
type Link = { source :: String
            , target :: String
            , value  :: Number
109
            }
110

111 112 113 114 115 116 117 118 119 120 121 122 123 124
-- | Sankey Chart
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=sankey-simple
type RequiredSankey o =
  { "data" :: Array Node
  , links  :: Array Link
  | o
  }

type OptionalSankey =
  ( layout :: String
  )

seriesSankey :: forall o. Optional o OptionalSankey => RequiredSankey o -> Series
seriesSankey o = unsafeSeries ((unsafeCoerce o) { "type" = seriesType Sankey })
125

126 127 128 129 130 131 132 133 134 135 136 137 138 139
-- | * Trees Chart
-- All these Trees are hierarchical Trees structure (or diagram)
-- https://en.wikipedia.org/wiki/Tree_structure

-- Tree types
data Trees = TreeLine | TreeRadial | TreeMap

instance showTrees :: Show Trees where
  show TreeLine    = "tree"           -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial
  show TreeRadial  = "tree"           -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple
  show TreeMap     = "treemap"        -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple


-- TreeLine is a 1-Dimension horizontal hierchical Tree
140

141 142 143 144 145 146 147
-- TreeRadial is 1-Dimension radial (as circle) Tree with no surface meaning
-- https://en.wikipedia.org/wiki/Radial_tree
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial

-- TreeMap is a is 2-Dimension Tree with surface meaning
-- TreeMap example implementation:
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple
148

149 150
type RequiredTree o =
  { "type" :: SeriesType
151
  , "data" :: Array TreeNode
152 153 154 155 156 157 158 159 160
  | o
  }

type OptionalTree =
  ( layout :: String
  )

seriesTree :: forall o. Optional o OptionalTree => RequiredTree o -> Series
seriesTree = unsafeSeries
161

162
mkTree :: Trees -> Array TreeNode -> Series
163
mkTree t ts = seriesTree { "type" : SeriesType (show t)
164
                         , "data" : map (toJsTree Nothing) ts
165 166
                         , layout : layout
                         }
167 168 169 170 171 172
              where
                layout = case t of
                           TreeRadial -> "radial"
                           _          -> "none"

-- ** Data Structure of the Trees
173 174 175 176 177 178 179 180 181 182 183 184 185
data TreeData = Array TreeNode


treeValue :: TreeNode -> Int
treeValue (TreeNode x) = foldl (+) 0 $ [x.value] <> map treeValue x.children

toJsTree :: Maybe String -> TreeNode -> TreeNode
toJsTree maybeSurname (TreeNode x) =
  unsafeCoerce { name : name
               , value : foldl (+) 0 $ [x.value] <> map treeValue x.children
               , children : (map (toJsTree (Just name)) x.children)
               }
    where
186
      name = maybe "" (\x' -> x' <> ">") maybeSurname  <> x.name
187

188 189 190 191 192
data TreeNode = TreeNode {
    name     :: String
  , value    :: Int
  , children :: Array TreeNode
  }
193

194 195 196
instance decodeTreeNode :: DecodeJson TreeNode where
  decodeJson json = do
    obj <- decodeJson json
197
    children <- obj .: "children"
198 199
    name <- obj .: "label"
    value <- obj .: "value"
200
    pure $ TreeNode { children, name, value }
201 202 203
instance encodeTreeNode :: EncodeJson TreeNode where
  encodeJson (TreeNode { children, name, value }) =
       "children" := encodeJson children
204
    ~> "label"    := encodeJson name
205 206
    ~> "value"    := encodeJson value
    ~> jsonEmptyObject
207 208

treeNode :: String -> Int -> Array TreeNode -> TreeNode
209
treeNode n v ts = TreeNode {name : n, value:v, children:ts}
210

211 212
treeLeaf :: String -> Int -> TreeNode
treeLeaf n v = TreeNode { name : n, value : v, children : []}
213 214


215
-- | TODO
216 217 218
-- https://ecomfe.github.io/echarts-examples/public/data/asset/data/life-expectancy-table.json
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter3D-dataset&gl=1