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

3
import Prelude (class Eq, class Show, bind, map, pure, show, ($), (+), (<<<), (<>), eq)
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.Generic.Rep (class Generic)
9
import Data.Maybe (Maybe(..), maybe)
10
import Record.Unsafe (unsafeSet)
11
import Unsafe.Coerce (unsafeCoerce)
12

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

17 18
newtype SeriesType = SeriesType String

19 20
type SeriesName = String

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

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

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

57

58 59 60 61 62 63 64 65 66 67 68 69
-- | 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...
  )

70
data Series
71

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

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

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

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

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

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

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

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

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

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

112 113 114 115 116 117 118 119 120 121 122 123 124 125
-- | 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 })
126

127 128 129 130 131 132 133 134 135 136 137 138 139 140
-- | * 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
141

142 143 144 145 146 147 148
-- 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
149

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

type OptionalTree =
  ( layout :: String
  )

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

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

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

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

195 196 197
derive instance genericTreeNode :: Generic TreeNode _
instance eqTreeNode :: Eq TreeNode where
  eq (TreeNode n1) (TreeNode n2) = eq n1 n2
198 199 200
instance decodeTreeNode :: DecodeJson TreeNode where
  decodeJson json = do
    obj <- decodeJson json
201
    children <- obj .: "children"
202 203
    name <- obj .: "label"
    value <- obj .: "value"
204
    pure $ TreeNode { children, name, value }
205 206 207
instance encodeTreeNode :: EncodeJson TreeNode where
  encodeJson (TreeNode { children, name, value }) =
       "children" := encodeJson children
208
    ~> "label"    := encodeJson name
209 210
    ~> "value"    := encodeJson value
    ~> jsonEmptyObject
211 212

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

215 216
treeLeaf :: String -> Int -> TreeNode
treeLeaf n v = TreeNode { name : n, value : v, children : []}
217 218


219
-- | TODO
220 221 222
-- 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