Graph.purs 4.51 KB
Newer Older
arturo's avatar
arturo committed
1
module Gargantext.Components.Nodes.Corpus.Graph
arturo's avatar
arturo committed
2
  ( node
arturo's avatar
arturo committed
3 4 5 6 7
  ) where

import Gargantext.Prelude

import DOM.Simple (document, querySelector)
arturo's avatar
arturo committed
8 9 10
import Data.Int as I
import Data.Maybe (Maybe(..), isJust, maybe)
import Data.Sequence as Seq
arturo's avatar
arturo committed
11 12
import Data.Tuple (Tuple(..))
import Data.Tuple.Nested ((/\))
arturo's avatar
arturo committed
13
import Gargantext.Components.App.Store as AppStore
arturo's avatar
arturo committed
14
import Gargantext.Components.Bootstrap as B
arturo's avatar
arturo committed
15
import Gargantext.Components.GraphExplorer.API as GraphAPI
arturo's avatar
arturo committed
16
import Gargantext.Components.GraphExplorer.Layout (convert, layout)
arturo's avatar
arturo committed
17
import Gargantext.Components.GraphExplorer.Store as GraphStore
arturo's avatar
arturo committed
18
import Gargantext.Components.GraphExplorer.Types as GET
arturo's avatar
arturo committed
19
import Gargantext.Config.REST (logRESTError)
20
import Gargantext.Hooks.FirstEffect (useFirstEffect')
arturo's avatar
arturo committed
21
import Gargantext.Hooks.Loader (useLoaderEffect)
arturo's avatar
arturo committed
22
import Gargantext.Hooks.Session (useSession)
arturo's avatar
arturo committed
23
import Gargantext.Hooks.Sigmax as Sigmax
arturo's avatar
arturo committed
24
import Gargantext.Hooks.Sigmax.Types as SigmaxT
25
import Gargantext.Utils (getter)
arturo's avatar
arturo committed
26
import Gargantext.Utils.Range as Range
arturo's avatar
arturo committed
27 28
import Gargantext.Utils.Reactix as R2
import Reactix as R
arturo's avatar
arturo committed
29
import Record as Record
arturo's avatar
arturo committed
30 31

type Props =
arturo's avatar
arturo committed
32
  ( graphId   :: GET.GraphId
arturo's avatar
arturo committed
33 34 35 36 37
  )

here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Corpus.Graph"

arturo's avatar
arturo committed
38 39
node :: R2.Leaf ( key :: String | Props )
node = R2.leaf nodeCpt
arturo's avatar
arturo committed
40

arturo's avatar
arturo committed
41 42
nodeCpt :: R.Component ( key :: String | Props )
nodeCpt = here.component "node" cpt where
arturo's avatar
arturo committed
43
  cpt { graphId } _ = do
arturo's avatar
arturo committed
44 45
    -- | States
    -- |
arturo's avatar
arturo committed
46 47 48 49 50
    { graphVersion
    } <- AppStore.use

    session <- useSession

arturo's avatar
arturo committed
51
    graphVersion'   <- R2.useLive' graphVersion
arturo's avatar
arturo committed
52
    state' /\ state <- R2.useBox' Nothing
53 54 55 56 57
    cache' /\ cache <- R2.useBox' (GET.defaultCacheParams :: GET.CacheParams)

    -- | Computed
    -- |
    let errorHandler = logRESTError here "[explorerLayout]"
arturo's avatar
arturo committed
58 59 60

    -- | Hooks
    -- |
61 62 63 64 65

    -- load Local Storage cache (if exists)
    useFirstEffect' $
      R2.loadLocalStorageState R2.graphParamsKey cache

arturo's avatar
arturo committed
66 67
    useLoaderEffect
      { errorHandler
arturo's avatar
arturo committed
68
      , loader: GraphAPI.getNodes session graphVersion'
arturo's avatar
arturo committed
69 70 71 72
      , path: graphId
      , state
      }

arturo's avatar
arturo committed
73 74
    -- @XXX: reset "main-page__main-route" wrapper margin
    --       see Gargantext.Components.Router) (@TODO?)
arturo's avatar
arturo committed
75 76 77 78 79 80 81
    R.useLayoutEffect1 [] do
      let mEl = querySelector document ".main-page__main-route"
      -- Mount
      mEl >>= maybe R.nothing (flip R2.addClass ["p-0"])
      -- Unmount
      pure $
        mEl >>= maybe R.nothing (flip R2.removeClass ["p-0"])
arturo's avatar
arturo committed
82 83 84 85 86

    -- | Render
    -- |
    pure $

arturo's avatar
arturo committed
87 88 89 90
      B.cloak
      { isDisplayed: isJust state'
      , idlingPhaseDuration: Just 150
      , cloakSlot:
arturo's avatar
arturo committed
91 92 93
          B.preloader
          {}

arturo's avatar
arturo committed
94
      , defaultSlot:
95 96 97 98 99 100 101 102 103 104 105 106
          R2.fromMaybe state' \loaded ->
            let
              GET.HyperdataGraph { graph: hyperdataGraph } = loaded
              Tuple mMetaData graph = convert hyperdataGraph
            in
              hydrateStore
              { graph
              , hyperdataGraph: loaded
              , mMetaData
              , graphId
              , cacheParams: cache'
              }
arturo's avatar
arturo committed
107
      }
arturo's avatar
arturo committed
108 109 110

--------------------------------------------------------

arturo's avatar
arturo committed
111
type HydrateStoreProps =
arturo's avatar
arturo committed
112
  ( mMetaData       :: Maybe GET.MetaData
arturo's avatar
arturo committed
113 114 115
  , graph           :: SigmaxT.SGraph
  , hyperdataGraph  :: GET.HyperdataGraph
  , graphId         :: GET.GraphId
116
  , cacheParams     :: GET.CacheParams
arturo's avatar
arturo committed
117 118
  )

arturo's avatar
arturo committed
119 120
hydrateStore:: R2.Leaf HydrateStoreProps
hydrateStore = R2.leaf hydrateStoreCpt
arturo's avatar
arturo committed
121

arturo's avatar
arturo committed
122 123 124
hydrateStoreCpt :: R.Component HydrateStoreProps
hydrateStoreCpt = here.component "hydrateStore" cpt where
  cpt { mMetaData
arturo's avatar
arturo committed
125 126 127
      , graph
      , graphId
      , hyperdataGraph
128
      , cacheParams
arturo's avatar
arturo committed
129 130 131 132 133 134
      } _ = do
    -- | Computed
    -- |
    let
      startForceAtlas = maybe true
        (\(GET.MetaData { startForceAtlas: sfa }) -> sfa) mMetaData
arturo's avatar
arturo committed
135

arturo's avatar
arturo committed
136 137 138 139
      forceAtlasState
        = if startForceAtlas
          then SigmaxT.InitialRunning
          else SigmaxT.InitialStopped
arturo's avatar
arturo committed
140

arturo's avatar
arturo committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
    -- | Hooks
    -- |

    sigmaRef <- Sigmax.initSigma >>= R.useRef

    -- Hydrate GraphStore
    (state :: Record GraphStore.State) <- pure $
      -- Data
      { graph
      , graphId
      , mMetaData
      , hyperdataGraph
      -- Controls
      , startForceAtlas
      , forceAtlasState
      , edgeWeight:  Range.Closed
          { min: 0.0
          , max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph
          }
160 161 162
      -- (cache options)
      , expandSelection: getter _.expandSelection cacheParams
      , expandNeighborhood: getter _.expandNeighborhood cacheParams
arturo's avatar
arturo committed
163 164
      -- (default options)
      } `Record.merge` GraphStore.options
arturo's avatar
arturo committed
165

arturo's avatar
arturo committed
166 167 168
    -- | Render
    -- |
    pure $
arturo's avatar
arturo committed
169

arturo's avatar
arturo committed
170 171 172 173
      GraphStore.provide
      state
      [
        layout
arturo's avatar
arturo committed
174
        { sigmaRef }
arturo's avatar
arturo committed
175
      ]