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

3 4
import Prelude (class Show, bind, map, pure, show, ($), (+), (<<<), (<>))
import Data.Argonaut (class DecodeJson, decodeJson, (.:))
5
import Data.Array (foldl)
6
import Data.Maybe (Maybe(..), maybe)
7
import Record.Unsafe (unsafeSet)
8
import Unsafe.Coerce (unsafeCoerce)
9
import Gargantext.Types (class Optional)
10 11
import Gargantext.Components.Charts.Options.Font (ItemStyle, Tooltip)
import Gargantext.Components.Charts.Options.Data (DataD1, DataD2)
12

13 14
newtype SeriesType = SeriesType String

15 16
type SeriesName = String

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

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
39
  show Bar      = "bar"
40
  show EffectScatter = "effectScatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-effect
41 42
  show Funnel   = "funnel"
  show Heatmap  = "heatmap"
43 44 45
  show Line     = "line"
  show Pie      = "pie"
  show Sankey   = "sankey"
46
  show Scatter  = "scatter"            -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple
47 48
  show Sunburst = "sunburst"
  show _        = "not implemented yet: should throw error here"
49

50
seriesType :: Chart -> SeriesType
51 52
seriesType = SeriesType <<< show

53

54 55 56 57 58 59 60 61 62 63 64 65
-- | 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...
  )

66
data Series
67

68
unsafeSeries :: forall o. Record o -> Series
69 70
unsafeSeries = unsafeCoerce

71
type RequiredSeriesD1 o =
72
  { "type" :: SeriesType
73
  , "data" :: Array DataD1
74
  | o
75
  }
76

77
seriesD1 :: forall o. Optional o OptionalSeries => RequiredSeriesD1 o -> Series
78 79
seriesD1 = unsafeSeries

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

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

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

89 90
type RequiredSeriesD2 o =
  { "data" :: Array DataD2
91
  , "type" :: SeriesType
92
  | o
93
  }
94

95
seriesD2 :: forall o. Optional o OptionalSeries => RequiredSeriesD2 o -> Series
96
seriesD2 = unsafeSeries
97

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

type Node = { name :: String}
type Link = { source :: String
            , target :: String
            , value  :: Number
106
            }
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121
-- | 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 })
122

123 124 125 126 127 128 129 130 131 132 133 134 135 136
-- | * 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
137

138 139 140 141 142 143 144
-- 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
145

146 147
type RequiredTree o =
  { "type" :: SeriesType
148
  , "data" :: Array TreeNode
149 150 151 152 153 154 155 156 157
  | o
  }

type OptionalTree =
  ( layout :: String
  )

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

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

-- ** Data Structure of the Trees
170 171 172 173 174 175 176 177 178 179 180 181 182
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
183
      name = maybe "" (\x' -> x' <> ">") maybeSurname  <> x.name
184 185 186 187

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


191 192 193
instance decodeTreeNode :: DecodeJson TreeNode where
  decodeJson json = do
    obj <- decodeJson json
194 195 196
    name <- obj .: "label"
    value <- obj .: "value"
    children <- obj .: "children"
197 198 199 200 201
    pure $ TreeNode {name, value, children}



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

204 205
treeLeaf :: String -> Int -> TreeNode
treeLeaf n v = TreeNode { name : n, value : v, children : []}
206 207


208
-- | TODO
209 210 211
-- 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