Commit 89d1033b authored by arturo's avatar arturo

>>> continue (store)

parent b8befd87
...@@ -6,7 +6,6 @@ import Gargantext.Prelude ...@@ -6,7 +6,6 @@ import Gargantext.Prelude
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Set as Set import Data.Set as Set
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
import Gargantext.Components.GraphExplorer.Sidebar.Types as GEST
import Gargantext.Components.Lang as Lang import Gargantext.Components.Lang as Lang
import Gargantext.Components.Nodes.Lists.Types as ListsT import Gargantext.Components.Nodes.Lists.Types as ListsT
import Gargantext.Components.Nodes.Texts.Types as TextsT import Gargantext.Components.Nodes.Texts.Types as TextsT
...@@ -36,7 +35,6 @@ type App = ...@@ -36,7 +35,6 @@ type App =
, showCorpus :: Boolean , showCorpus :: Boolean
, showLogin :: Boolean , showLogin :: Boolean
, showTree :: Boolean , showTree :: Boolean
, sidePanelGraph :: Maybe (Record GEST.SidePanel)
, sidePanelLists :: Maybe (Record ListsT.SidePanel) , sidePanelLists :: Maybe (Record ListsT.SidePanel)
, sidePanelTexts :: Maybe (Record TextsT.SidePanel) , sidePanelTexts :: Maybe (Record TextsT.SidePanel)
, sidePanelState :: SidePanelState , sidePanelState :: SidePanelState
...@@ -63,7 +61,6 @@ emptyApp = ...@@ -63,7 +61,6 @@ emptyApp =
, showCorpus : false , showCorpus : false
, showLogin : false , showLogin : false
, showTree : true , showTree : true
, sidePanelGraph : GEST.initialSidePanel
, sidePanelLists : ListsT.initialSidePanel , sidePanelLists : ListsT.initialSidePanel
, sidePanelTexts : TextsT.initialSidePanel , sidePanelTexts : TextsT.initialSidePanel
, sidePanelState : InitialClosed , sidePanelState : InitialClosed
...@@ -89,7 +86,6 @@ type Boxes = ...@@ -89,7 +86,6 @@ type Boxes =
, showCorpus :: T.Box Boolean , showCorpus :: T.Box Boolean
, showLogin :: T.Box Boolean , showLogin :: T.Box Boolean
, showTree :: T.Box Boolean , showTree :: T.Box Boolean
, sidePanelGraph :: T.Box (Maybe (Record GEST.SidePanel))
, sidePanelLists :: T.Box (Maybe (Record ListsT.SidePanel)) , sidePanelLists :: T.Box (Maybe (Record ListsT.SidePanel))
, sidePanelTexts :: T.Box (Maybe (Record TextsT.SidePanel)) , sidePanelTexts :: T.Box (Maybe (Record TextsT.SidePanel))
, sidePanelState :: T.Box SidePanelState , sidePanelState :: T.Box SidePanelState
......
...@@ -7,7 +7,7 @@ import Data.Array as A ...@@ -7,7 +7,7 @@ import Data.Array as A
import Data.FoldableWithIndex (foldMapWithIndex) import Data.FoldableWithIndex (foldMapWithIndex)
import Data.Int (toNumber) import Data.Int (toNumber)
import Data.Map as Map import Data.Map as Map
import Data.Maybe (Maybe(..), fromJust, maybe) import Data.Maybe (Maybe(..), fromJust)
import Data.Nullable (null, Nullable) import Data.Nullable (null, Nullable)
import Data.Sequence as Seq import Data.Sequence as Seq
import Data.Set as Set import Data.Set as Set
...@@ -16,13 +16,13 @@ import Gargantext.Components.App.Data (Boxes) ...@@ -16,13 +16,13 @@ import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphExplorer.Resources as Graph import Gargantext.Components.GraphExplorer.Resources as Graph
import Gargantext.Components.GraphExplorer.Sidebar as GES import Gargantext.Components.GraphExplorer.Sidebar as GES
import Gargantext.Components.GraphExplorer.Sidebar.Types as GEST import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Toolbar.Controls (Controls)
import Gargantext.Components.GraphExplorer.Toolbar.Controls as Controls import Gargantext.Components.GraphExplorer.Toolbar.Controls as Controls
import Gargantext.Components.GraphExplorer.TopBar as GETB import Gargantext.Components.GraphExplorer.TopBar as GETB
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Config (defaultFrontends) import Gargantext.Config (defaultFrontends)
import Gargantext.Data.Louvain as Louvain import Gargantext.Data.Louvain as Louvain
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxT import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Sessions (Session) import Gargantext.Sessions (Session)
import Gargantext.Types as GT import Gargantext.Types as GT
...@@ -30,71 +30,63 @@ import Gargantext.Types as Types ...@@ -30,71 +30,63 @@ import Gargantext.Types as Types
import Gargantext.Utils ((?)) import Gargantext.Utils ((?))
import Gargantext.Utils.Range as Range import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Math as Math import Math as Math
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Layout"
type Props = type Props =
( mMetaData' :: Maybe GET.MetaData ( session :: Session
, graph :: SigmaxT.SGraph
, hyperdataGraph :: GET.HyperdataGraph
, session :: Session
, boxes :: Boxes , boxes :: Boxes
, sigmaRef :: R.Ref Sigmax.Sigma
, graphId :: GET.GraphId , graphId :: GET.GraphId
, controls :: Record Controls
) )
here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Layout"
layout :: R2.Leaf Props layout :: R2.Leaf Props
layout = R2.leaf layoutCpt layout = R2.leaf layoutCpt
layoutCpt :: R.Memo Props layoutCpt :: R.Memo Props
layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
cpt props@{ boxes cpt props@{ boxes
, graph
, mMetaData'
, graphId
, session , session
, hyperdataGraph , sigmaRef
, controls , graphId
} _ = do } _ = do
-- Computed -- | Computed
----------------- -- |
let let
topBarPortalKey = "portal-topbar::" <> show graphId topBarPortalKey = "portal-topbar::" <> show graphId
-- States -- | States
----------------- -- |
{ mMetaData: mMetaDataBox { showSidebar
, showSidebar
, showDoc , showDoc
} <- GEST.focusedSidePanel boxes.sidePanelGraph , mMetaData
, showControls
} <- Stores.useStore GraphStore.context
_graphVersion' <- T.useLive T.unequal boxes.graphVersion
showSidebar' <- R2.useLive' showSidebar showSidebar' <- R2.useLive' showSidebar
showDoc' <- R2.useLive' showDoc showDoc' <- R2.useLive' showDoc
mMetaData' <- R2.useLive' mMetaData
showControls' <- R2.useLive' showControls
-- _dataRef <- R.useRef graph -- _dataRef <- R.useRef graph
graphRef <- R.useRef null graphRef <- R.useRef null
-- Hooks -- | Hooks
----------------- -- |
mTopBarHost <- R.unsafeHooksEffect $ R2.getElementById "portal-topbar" mTopBarHost <- R.unsafeHooksEffect $ R2.getElementById "portal-topbar"
showControls' <- R2.useLive' controls.showControls
-- graphVersionRef <- R.useRef graphVersion' -- graphVersionRef <- R.useRef graphVersion'
-- R.useEffect' $ do -- R.useEffect' $ do
...@@ -116,8 +108,8 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -116,8 +108,8 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
-- T.write_ Graph.Init controls.graphStage -- T.write_ Graph.Init controls.graphStage
-- T.write_ Types.InitialClosed controls.sidePanelState -- T.write_ Types.InitialClosed controls.sidePanelState
-- Render -- | Render
----------------- -- |
pure $ pure $
...@@ -130,7 +122,7 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -130,7 +122,7 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
R2.fragmentWithKey topBarPortalKey R2.fragmentWithKey topBarPortalKey
[ [
GETB.topBar GETB.topBar
{ sidePanelGraph: props.boxes.sidePanelGraph } {}
] ]
] ]
, ,
...@@ -173,8 +165,6 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -173,8 +165,6 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
GES.sidebar GES.sidebar
{ boxes { boxes
, frontends: defaultFrontends , frontends: defaultFrontends
, graph
, graphId
, metaData , metaData
, session , session
} }
...@@ -190,7 +180,11 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -190,7 +180,11 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
, style: { display: showControls' ? "block" $ "none" } , style: { display: showControls' ? "block" $ "none" }
} }
[ [
Controls.controls controls [] Controls.controls
{ reloadForest: boxes.reloadForest
, session
, sigmaRef
}
] ]
, ,
-- Content -- Content
...@@ -201,11 +195,8 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -201,11 +195,8 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
[ [
graphView graphView
{ boxes: props.boxes { boxes: props.boxes
, controls
, elRef: graphRef , elRef: graphRef
, graph , sigmaRef
, hyperdataGraph
, mMetaData: mMetaDataBox
} }
] ]
] ]
...@@ -214,70 +205,84 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where ...@@ -214,70 +205,84 @@ layoutCpt = R.memo' $ here.component "explorerWriteGraph" cpt where
type GraphProps = type GraphProps =
( boxes :: Boxes ( boxes :: Boxes
, controls :: Record Controls.Controls
, elRef :: R.Ref (Nullable Element) , elRef :: R.Ref (Nullable Element)
, graph :: SigmaxT.SGraph , sigmaRef :: R.Ref Sigmax.Sigma
, hyperdataGraph :: GET.HyperdataGraph
, mMetaData :: T.Box (Maybe GET.MetaData)
) )
graphView :: R2.Leaf GraphProps graphView :: R2.Leaf GraphProps
graphView = R2.leaf graphViewCpt graphView = R2.leaf graphViewCpt
graphViewCpt :: R.Memo GraphProps graphViewCpt :: R.Memo GraphProps
graphViewCpt = R.memo' $ here.component "graphView" cpt graphViewCpt = R.memo' $ here.component "graphView" cpt where
where
cpt { boxes cpt { boxes
, controls
, elRef , elRef
, sigmaRef
} _ = do
-- | States
-- |
{ edgeConfluence
, edgeWeight
, multiSelectEnabled
, nodeSize
, removedNodeIds
, selectedNodeIds
, showEdges
, showLouvain
, hyperdataGraph
, graph , graph
, hyperdataGraph: GET.HyperdataGraph { mCamera } } <- Stores.useStore GraphStore.context
, mMetaData } _ = do
edgeConfluence' <- T.useLive T.unequal controls.edgeConfluence edgeConfluence' <- R2.useLive' edgeConfluence
edgeWeight' <- T.useLive T.unequal controls.edgeWeight edgeWeight' <- R2.useLive' edgeWeight
mMetaData' <- T.useLive T.unequal mMetaData multiSelectEnabled' <- R2.useLive' multiSelectEnabled
multiSelectEnabled' <- T.useLive T.unequal controls.multiSelectEnabled nodeSize' <- R2.useLive' nodeSize
nodeSize' <- T.useLive T.unequal controls.nodeSize removedNodeIds' <- R2.useLive' removedNodeIds
removedNodeIds' <- T.useLive T.unequal controls.removedNodeIds selectedNodeIds' <- R2.useLive' selectedNodeIds
selectedNodeIds' <- T.useLive T.unequal controls.selectedNodeIds showEdges' <- R2.useLive' showEdges
showEdges' <- T.useLive T.unequal controls.showEdges showLouvain' <- R2.useLive' showLouvain
showLouvain' <- T.useLive T.unequal controls.showLouvain hyperdataGraph' <- R2.useLive' hyperdataGraph
graph' <- R2.useLive' graph
multiSelectEnabledRef <- R.useRef multiSelectEnabled' multiSelectEnabledRef <- R.useRef multiSelectEnabled'
-- | Computed
-- |
-- TODO Cache this? -- TODO Cache this?
let louvainGraph = let louvainGraph =
if showLouvain' then if showLouvain' then
let louvain = Louvain.louvain unit in let louvain = Louvain.louvain unit in
let cluster = Louvain.init louvain (SigmaxT.louvainNodes graph) (SigmaxT.louvainEdges graph) in let cluster = Louvain.init louvain (SigmaxT.louvainNodes graph') (SigmaxT.louvainEdges graph') in
SigmaxT.louvainGraph graph cluster SigmaxT.louvainGraph graph' cluster
else else
graph graph'
let transformedGraph = transformGraph louvainGraph { edgeConfluence' let transformedGraph = transformGraph louvainGraph { edgeConfluence'
, edgeWeight' , edgeWeight'
, nodeSize' , nodeSize'
, removedNodeIds' , removedNodeIds'
, selectedNodeIds' , selectedNodeIds'
, showEdges' } , showEdges' }
let startForceAtlas = maybe true (\(GET.MetaData { startForceAtlas: sfa }) -> sfa) mMetaData'
let mCamera' (GET.HyperdataGraph { mCamera }) = mCamera
-- | Hooks
-- |
R.useEffect1' multiSelectEnabled' $ do R.useEffect1' multiSelectEnabled' $ do
R.setRef multiSelectEnabledRef multiSelectEnabled' R.setRef multiSelectEnabledRef multiSelectEnabled'
-- | Render
-- |
pure $ pure $
Graph.graph Graph.drawGraph
{ boxes { boxes
, elRef , elRef
, forceAtlas2Settings: Graph.forceAtlas2Settings , forceAtlas2Settings: Graph.forceAtlas2Settings
, graph , mCamera: mCamera' hyperdataGraph'
, mCamera
, multiSelectEnabledRef , multiSelectEnabledRef
, selectedNodeIds: controls.selectedNodeIds , sigmaRef
, showEdges: controls.showEdges
, sigmaRef: controls.sigmaRef
, sigmaSettings: Graph.sigmaSettings , sigmaSettings: Graph.sigmaSettings
, stage: controls.graphStage
, startForceAtlas
, transformedGraph , transformedGraph
} }
......
module Gargantext.Components.GraphExplorer.Resources module Gargantext.Components.GraphExplorer.Resources
-- ( graph, graphCpt ( drawGraph
-- , sigmaSettings, SigmaSettings, SigmaOptionalSettings , sigmaSettings, SigmaSettings--, SigmaOptionalSettings
-- , forceAtlas2Settings, ForceAtlas2Settings, ForceAtlas2OptionalSettings , forceAtlas2Settings, ForceAtlas2Settings--, ForceAtlas2OptionalSettings
-- ) )
where where
import Gargantext.Prelude import Gargantext.Prelude
...@@ -10,10 +10,10 @@ import Gargantext.Prelude ...@@ -10,10 +10,10 @@ import Gargantext.Prelude
import DOM.Simple (window) import DOM.Simple (window)
import DOM.Simple.Types (Element) import DOM.Simple.Types (Element)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable) import Data.Nullable (Nullable)
import Gargantext.Components.App.Data (Boxes) import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.Themes (darksterTheme) import Gargantext.Components.Themes (darksterTheme)
import Gargantext.Components.Themes as Themes import Gargantext.Components.Themes as Themes
...@@ -21,6 +21,7 @@ import Gargantext.Hooks.Sigmax as Sigmax ...@@ -21,6 +21,7 @@ import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as RH import Reactix.DOM.HTML as RH
import Record (merge) import Record (merge)
...@@ -30,41 +31,53 @@ import Toestand as T ...@@ -30,41 +31,53 @@ import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.Graph" here = R2.here "Gargantext.Components.Graph"
data Stage = Init | Ready | Cleanup
derive instance Generic Stage _
derive instance Eq Stage
type Props sigma forceatlas2 = type Props sigma forceatlas2 =
( boxes :: Boxes ( boxes :: Boxes
, elRef :: R.Ref (Nullable Element) , elRef :: R.Ref (Nullable Element)
, forceAtlas2Settings :: forceatlas2 , forceAtlas2Settings :: forceatlas2
, graph :: SigmaxTypes.SGraph
, mCamera :: Maybe GET.Camera , mCamera :: Maybe GET.Camera
, multiSelectEnabledRef :: R.Ref Boolean , multiSelectEnabledRef :: R.Ref Boolean
, selectedNodeIds :: T.Box SigmaxTypes.NodeIds
, showEdges :: T.Box SigmaxTypes.ShowEdgesState
, sigmaRef :: R.Ref Sigmax.Sigma , sigmaRef :: R.Ref Sigmax.Sigma
, sigmaSettings :: sigma , sigmaSettings :: sigma
, stage :: T.Box Stage
, startForceAtlas :: Boolean
, transformedGraph :: SigmaxTypes.SGraph , transformedGraph :: SigmaxTypes.SGraph
) )
graph :: forall s fa2. R2.Leaf (Props s fa2) drawGraph :: forall s fa2. R2.Leaf (Props s fa2)
graph = R2.leaf graphCpt drawGraph = R2.leaf drawGraphCpt
graphCpt :: forall s fa2. R.Memo (Props s fa2) drawGraphCpt :: forall s fa2. R.Memo (Props s fa2)
graphCpt = R.memo' $ here.component "graph" cpt where drawGraphCpt = R.memo' $ here.component "graph" cpt where
-- | Component
-- |
cpt props@{ elRef cpt props@{ elRef
, showEdges
, sigmaRef , sigmaRef
, stage } _ = do } _ = do
showEdges' <- T.useLive T.unequal showEdges
stage' <- T.useLive T.unequal stage
stageHooks (Record.merge { showEdges', stage' } props) { showEdges
, graphStage
, graph
, startForceAtlas
, selectedNodeIds
} <- Stores.useStore GraphStore.context
showEdges' <- R2.useLive' showEdges
graphStage' <- R2.useLive' graphStage
graph' <- R2.useLive' graph
startForceAtlas' <- R2.useLive' startForceAtlas
stageHooks
-- @WIP: record merge
(
Record.merge
{ showEdges'
, graphStage'
, selectedNodeIds
, graphStage
, startForceAtlas'
, graph'
}
props
)
R.useEffectOnce $ do R.useEffectOnce $ do
pure $ do pure $ do
...@@ -82,16 +95,18 @@ graphCpt = R.memo' $ here.component "graph" cpt where ...@@ -82,16 +95,18 @@ graphCpt = R.memo' $ here.component "graph" cpt where
Nothing -> RH.div {} [] Nothing -> RH.div {} []
Just el -> R.createPortal [] el Just el -> R.createPortal [] el
-- | Stage Hooks
-- |
stageHooks { elRef stageHooks { elRef
, mCamera , mCamera
, multiSelectEnabledRef , multiSelectEnabledRef
, selectedNodeIds , selectedNodeIds
, forceAtlas2Settings: fa2 , forceAtlas2Settings: fa2
, graph: graph' , graph'
, sigmaRef , sigmaRef
, stage , graphStage
, stage': Init , graphStage': GET.Init
, startForceAtlas , startForceAtlas'
, boxes , boxes
} = do } = do
R.useEffectOnce' $ do R.useEffectOnce' $ do
...@@ -125,7 +140,7 @@ graphCpt = R.memo' $ here.component "graph" cpt where ...@@ -125,7 +140,7 @@ graphCpt = R.memo' $ here.component "graph" cpt where
Sigmax.setEdges sig false Sigmax.setEdges sig false
-- here.log2 "[graph] startForceAtlas" startForceAtlas -- here.log2 "[graph] startForceAtlas" startForceAtlas
if startForceAtlas then if startForceAtlas' then
Sigma.startForceAtlas2 sig fa2 Sigma.startForceAtlas2 sig fa2
else else
Sigma.stopForceAtlas2 sig Sigma.stopForceAtlas2 sig
...@@ -147,12 +162,12 @@ graphCpt = R.memo' $ here.component "graph" cpt where ...@@ -147,12 +162,12 @@ graphCpt = R.memo' $ here.component "graph" cpt where
Just _sig -> do Just _sig -> do
pure unit pure unit
T.write Ready stage T.write GET.Ready graphStage
stageHooks { showEdges' stageHooks { showEdges'
, sigmaRef , sigmaRef
, stage': Ready , graphStage': GET.Ready
, transformedGraph , transformedGraph
} = do } = do
let tEdgesMap = SigmaxTypes.edgesGraphMap transformedGraph let tEdgesMap = SigmaxTypes.edgesGraphMap transformedGraph
......
module Gargantext.Components.GraphExplorer.Sidebar module Gargantext.Components.GraphExplorer.Sidebar
( Props, sidebar ( sidebar
, Common
) where ) where
import Gargantext.Prelude import Gargantext.Prelude
...@@ -25,7 +24,7 @@ import Gargantext.Components.Bootstrap as B ...@@ -25,7 +24,7 @@ import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), Variant(..)) import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), Variant(..))
import Gargantext.Components.GraphExplorer.Sidebar.DocList (docList) import Gargantext.Components.GraphExplorer.Sidebar.DocList (docList)
import Gargantext.Components.GraphExplorer.Sidebar.Legend as Legend import Gargantext.Components.GraphExplorer.Sidebar.Legend as Legend
import Gargantext.Components.GraphExplorer.Sidebar.Types as GEST import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.Lang (Lang(..)) import Gargantext.Components.Lang (Lang(..))
import Gargantext.Components.NgramsTable.Core as NTC import Gargantext.Components.NgramsTable.Core as NTC
...@@ -39,42 +38,36 @@ import Gargantext.Sessions (Session) ...@@ -39,42 +38,36 @@ import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType, FrontendError(..), NodeID, TabSubType(..), TabType(..), TermList(..), ListId, modeTabType) import Gargantext.Types (CTabNgramType, FrontendError(..), NodeID, TabSubType(..), TabType(..), TermList(..), ListId, modeTabType)
import Gargantext.Utils (nbsp) import Gargantext.Utils (nbsp)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Math as Math import Math as Math
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Record as Record import Record as Record
import Record.Extra as RX
import Toestand as T import Toestand as T
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Sidebar" here = R2.here "Gargantext.Components.GraphExplorer.Sidebar"
type Common = type Props =
( boxes :: Boxes ( boxes :: Boxes
, graphId :: NodeID
, metaData :: GET.MetaData , metaData :: GET.MetaData
, session :: Session , session :: Session
) , frontends :: Frontends
type Props =
( frontends :: Frontends
, graph :: SigmaxT.SGraph
| Common
) )
sidebar :: R2.Leaf Props sidebar :: R2.Leaf Props
sidebar = R2.leaf sidebarCpt sidebar = R2.leaf sidebarCpt
sidebarCpt :: R.Component Props sidebarCpt :: R.Component Props
sidebarCpt = here.component "sidebar" cpt sidebarCpt = here.component "sidebar" cpt where
where cpt props _ = do
cpt props@{ boxes: { sidePanelGraph } } _ = do
-- States -- States
{ sideTab { sideTab
} <- GEST.focusedSidePanel sidePanelGraph } <- Stores.useStore GraphStore.context
sideTab' <- T.useLive T.unequal sideTab sideTab' <- R2.useLive' sideTab
-- Computed -- Computed
let let
...@@ -84,8 +77,6 @@ sidebarCpt = here.component "sidebar" cpt ...@@ -84,8 +77,6 @@ sidebarCpt = here.component "sidebar" cpt
, GET.SideTabCommunity , GET.SideTabCommunity
] ]
sideTabProps = (RX.pick props :: Record Props)
-- Render -- Render
pure $ pure $
...@@ -100,15 +91,16 @@ sidebarCpt = here.component "sidebar" cpt ...@@ -100,15 +91,16 @@ sidebarCpt = here.component "sidebar" cpt
} }
, ,
case sideTab' of case sideTab' of
GET.SideTabLegend -> sideTabLegend sideTabProps GET.SideTabLegend -> sideTabLegend props
GET.SideTabData -> sideTabData sideTabProps GET.SideTabData -> sideTabData props
GET.SideTabCommunity -> sideTabCommunity sideTabProps GET.SideTabCommunity -> sideTabCommunity props
] ]
------------------------------------------------------------ ------------------------------------------------------------
sideTabLegend :: R2.Leaf Props sideTabLegend :: R2.Leaf Props
sideTabLegend = R2.leaf sideTabLegendCpt sideTabLegend = R2.leaf sideTabLegendCpt
sideTabLegendCpt :: R.Component Props sideTabLegendCpt :: R.Component Props
sideTabLegendCpt = here.component "sideTabLegend" cpt sideTabLegendCpt = here.component "sideTabLegend" cpt
where where
...@@ -129,16 +121,18 @@ sideTabLegendCpt = here.component "sideTabLegend" cpt ...@@ -129,16 +121,18 @@ sideTabLegendCpt = here.component "sideTabLegend" cpt
sideTabData :: R2.Leaf Props sideTabData :: R2.Leaf Props
sideTabData = R2.leaf sideTabDataCpt sideTabData = R2.leaf sideTabDataCpt
sideTabDataCpt :: R.Component Props sideTabDataCpt :: R.Component Props
sideTabDataCpt = here.component "sideTabData" cpt sideTabDataCpt = here.component "sideTabData" cpt where
where cpt props _ = do
cpt props@{ boxes: { sidePanelGraph } } _ = do
-- States -- States
{ selectedNodeIds { selectedNodeIds
, showDoc , showDoc
} <- GEST.focusedSidePanel sidePanelGraph , graph
} <- Stores.useStore GraphStore.context
selectedNodeIds' <- T.useLive T.unequal selectedNodeIds selectedNodeIds' <- R2.useLive' selectedNodeIds
graph' <- R2.useLive' graph
-- Computed -- Computed
let let
...@@ -167,20 +161,20 @@ sideTabDataCpt = here.component "sideTabData" cpt ...@@ -167,20 +161,20 @@ sideTabDataCpt = here.component "sideTabData" cpt
R.fragment R.fragment
[ [
selectedNodes $ selectedNodes $
{ nodesMap: SigmaxT.nodesGraphMap props.graph { nodesMap: SigmaxT.nodesGraphMap graph'
} `Record.merge` props } `Record.merge` props
, ,
sideBarTabSeparator sideBarTabSeparator
, ,
neighborhood neighborhood
props {}
, ,
sideBarTabSeparator sideBarTabSeparator
, ,
docListWrapper docListWrapper
{ frontends: props.frontends { frontends: props.frontends
, metaData: props.metaData , metaData: props.metaData
, nodesMap: SigmaxT.nodesGraphMap props.graph , nodesMap: SigmaxT.nodesGraphMap graph'
, searchType: SearchDoc , searchType: SearchDoc
, selectedNodeIds: selectedNodeIds' , selectedNodeIds: selectedNodeIds'
, session: props.session , session: props.session
...@@ -193,16 +187,18 @@ sideTabDataCpt = here.component "sideTabData" cpt ...@@ -193,16 +187,18 @@ sideTabDataCpt = here.component "sideTabData" cpt
sideTabCommunity :: R2.Leaf Props sideTabCommunity :: R2.Leaf Props
sideTabCommunity = R2.leaf sideTabCommunityCpt sideTabCommunity = R2.leaf sideTabCommunityCpt
sideTabCommunityCpt :: R.Component Props sideTabCommunityCpt :: R.Component Props
sideTabCommunityCpt = here.component "sideTabCommunity" cpt sideTabCommunityCpt = here.component "sideTabCommunity" cpt where
where cpt props@{ frontends } _ = do
cpt props@{ boxes: { sidePanelGraph }
, frontends } _ = do
-- States -- States
{ selectedNodeIds { selectedNodeIds
, showDoc , showDoc
} <- GEST.focusedSidePanel sidePanelGraph , graph
selectedNodeIds' <- T.useLive T.unequal selectedNodeIds } <- Stores.useStore GraphStore.context
selectedNodeIds' <- R2.useLive' selectedNodeIds
graph' <- R2.useLive' graph
-- Computed -- Computed
let let
...@@ -231,20 +227,20 @@ sideTabCommunityCpt = here.component "sideTabCommunity" cpt ...@@ -231,20 +227,20 @@ sideTabCommunityCpt = here.component "sideTabCommunity" cpt
R.fragment R.fragment
[ [
selectedNodes $ selectedNodes $
{ nodesMap: SigmaxT.nodesGraphMap props.graph { nodesMap: SigmaxT.nodesGraphMap graph'
} `Record.merge` props } `Record.merge` props
, ,
sideBarTabSeparator sideBarTabSeparator
, ,
neighborhood neighborhood
props {}
, ,
sideBarTabSeparator sideBarTabSeparator
, ,
docListWrapper docListWrapper
{ frontends { frontends
, metaData: props.metaData , metaData: props.metaData
, nodesMap: SigmaxT.nodesGraphMap props.graph , nodesMap: SigmaxT.nodesGraphMap graph'
, searchType: SearchContact , searchType: SearchContact
, selectedNodeIds: selectedNodeIds' , selectedNodeIds: selectedNodeIds'
, session: props.session , session: props.session
...@@ -275,18 +271,17 @@ type SelectedNodesProps = ...@@ -275,18 +271,17 @@ type SelectedNodesProps =
selectedNodes :: R2.Leaf SelectedNodesProps selectedNodes :: R2.Leaf SelectedNodesProps
selectedNodes = R2.leaf selectedNodesCpt selectedNodes = R2.leaf selectedNodesCpt
selectedNodesCpt :: R.Component SelectedNodesProps selectedNodesCpt :: R.Component SelectedNodesProps
selectedNodesCpt = here.component "selectedNodes" cpt where selectedNodesCpt = here.component "selectedNodes" cpt where
cpt props@{ boxes: { sidePanelGraph } cpt props _ = do
, graph
, nodesMap } _ = do
-- States -- States
{ selectedNodeIds } <- GEST.focusedSidePanel sidePanelGraph { selectedNodeIds
selectedNodeIds' <- T.useLive T.unequal selectedNodeIds , graph
} <- Stores.useStore GraphStore.context
-- Computed selectedNodeIds' <- R2.useLive' selectedNodeIds
let graph' <- R2.useLive' graph
commonProps = RX.pick props :: Record Common
-- Behaviors -- Behaviors
let let
...@@ -309,7 +304,7 @@ selectedNodesCpt = here.component "selectedNodes" cpt where ...@@ -309,7 +304,7 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
{} $ {} $
Seq.toUnfoldable $ Seq.toUnfoldable $
flip Seq.map (badges graph selectedNodeIds') \node -> flip Seq.map (badges graph' selectedNodeIds') \node ->
H.li H.li
{ className: "graph-selected-nodes__item" } { className: "graph-selected-nodes__item" }
...@@ -334,18 +329,16 @@ selectedNodesCpt = here.component "selectedNodes" cpt where ...@@ -334,18 +329,16 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
} }
[ [
updateTermButton updateTermButton
( commonProps `Record.merge` ( props `Record.merge`
{ variant: ButtonVariant Secondary { variant: ButtonVariant Secondary
, rType: CandidateTerm , rType: CandidateTerm
, nodesMap
} }
) )
[ H.text "Move as candidate" ] [ H.text "Move as candidate" ]
, ,
updateTermButton updateTermButton
( commonProps `Record.merge` ( props `Record.merge`
{ variant: ButtonVariant Danger { variant: ButtonVariant Danger
, nodesMap
, rType: StopTerm , rType: StopTerm
} }
) )
...@@ -355,19 +348,22 @@ selectedNodesCpt = here.component "selectedNodes" cpt where ...@@ -355,19 +348,22 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
--------------------------------------------------------- ---------------------------------------------------------
neighborhood :: R2.Leaf Props neighborhood :: R2.Leaf ()
neighborhood = R2.leaf neighborhoodCpt neighborhood = R2.leaf neighborhoodCpt
neighborhoodCpt :: R.Memo Props
neighborhoodCpt :: R.Memo ()
neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
cpt { boxes: { sidePanelGraph } cpt _ _ = do
, graph
} _ = do
-- States -- States
{ selectedNodeIds } <- { selectedNodeIds
GEST.focusedSidePanel sidePanelGraph , graph
} <- Stores.useStore GraphStore.context
selectedNodeIds' <- selectedNodeIds' <-
T.useLive T.unequal selectedNodeIds R2.useLive' selectedNodeIds
graph' <-
R2.useLive' graph
showMore /\ showMoreBox <- showMore /\ showMoreBox <-
R2.useBox' false R2.useBox' false
...@@ -380,9 +376,9 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where ...@@ -380,9 +376,9 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
-- Computed -- Computed
let let
minSize = F.foldl Math.min 0.0 (Seq.map _.size (SigmaxT.graphNodes graph)) minSize = F.foldl Math.min 0.0 (Seq.map _.size (SigmaxT.graphNodes graph'))
maxSize = F.foldl Math.max 0.0 (Seq.map _.size (SigmaxT.graphNodes graph)) maxSize = F.foldl Math.max 0.0 (Seq.map _.size (SigmaxT.graphNodes graph'))
maxTruncateResult = 5 maxTruncateResult = 5
...@@ -395,7 +391,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where ...@@ -395,7 +391,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
-- Effects -- Effects
R.useEffect1' selectedNodeIds' do R.useEffect1' selectedNodeIds' do
let refreshed = neighbourBadges graph selectedNodeIds' let refreshed = neighbourBadges graph' selectedNodeIds'
let count = Seq.length refreshed let count = Seq.length refreshed
let ordered = A.sortWith (\n -> -n.size) $ Seq.toUnfoldable refreshed let ordered = A.sortWith (\n -> -n.size) $ Seq.toUnfoldable refreshed
T.write_ count termCountBox T.write_ count termCountBox
...@@ -482,26 +478,32 @@ type UpdateTermButtonProps = ...@@ -482,26 +478,32 @@ type UpdateTermButtonProps =
( variant :: ButtonVariant ( variant :: ButtonVariant
, nodesMap :: SigmaxT.NodesMap , nodesMap :: SigmaxT.NodesMap
, rType :: TermList , rType :: TermList
| Common | Props
) )
updateTermButton :: R2.Component UpdateTermButtonProps updateTermButton :: R2.Component UpdateTermButtonProps
updateTermButton = R2.component updateTermButtonCpt updateTermButton = R2.component updateTermButtonCpt
updateTermButtonCpt :: R.Component UpdateTermButtonProps updateTermButtonCpt :: R.Component UpdateTermButtonProps
updateTermButtonCpt = here.component "updateTermButton" cpt where updateTermButtonCpt = here.component "updateTermButton" cpt where
cpt { boxes: { errors cpt { boxes:
{ errors
, reloadForest , reloadForest
, sidePanelGraph } }
, variant , variant
, graphId
, metaData , metaData
, nodesMap , nodesMap
, rType , rType
, session , session
} children = do } children = do
-- States -- States
{ removedNodeIds, selectedNodeIds } <- GEST.focusedSidePanel sidePanelGraph { removedNodeIds
selectedNodeIds' <- T.useLive T.unequal selectedNodeIds , selectedNodeIds
, graphId
} <- Stores.useStore GraphStore.context
selectedNodeIds' <- R2.useLive' selectedNodeIds
graphId' <- R2.useLive' graphId
-- Behaviors -- Behaviors
let let
...@@ -509,12 +511,13 @@ updateTermButtonCpt = here.component "updateTermButton" cpt where ...@@ -509,12 +511,13 @@ updateTermButtonCpt = here.component "updateTermButton" cpt where
let nodes = mapMaybe (\id -> Map.lookup id nodesMap) let nodes = mapMaybe (\id -> Map.lookup id nodesMap)
$ Set.toUnfoldable selectedNodeIds' $ Set.toUnfoldable selectedNodeIds'
sendPatches { errors sendPatches { errors
, graphId: graphId , graphId: graphId'
, metaData: metaData , metaData: metaData
, nodes , nodes
, session: session , session: session
, termList: rType , termList: rType
, reloadForest } , reloadForest
}
T.write_ selectedNodeIds' removedNodeIds T.write_ selectedNodeIds' removedNodeIds
T.write_ SigmaxT.emptyNodeIds selectedNodeIds T.write_ SigmaxT.emptyNodeIds selectedNodeIds
......
module Gargantext.Components.GraphExplorer.Sidebar.Types where
import Gargantext.Prelude
import Data.Maybe (Maybe(..), maybe)
import Data.Set as Set
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Types as GT
import Reactix as R
import Toestand as T
type SidePanel =
(
mGraph :: Maybe SigmaxT.SGraph
, mMetaData :: Maybe GET.MetaData
, multiSelectEnabled :: Boolean
, removedNodeIds :: SigmaxT.NodeIds
, selectedNodeIds :: SigmaxT.NodeIds
, showControls :: Boolean
, sideTab :: GET.SideTab
, showSidebar :: GT.SidePanelState
, showDoc :: Maybe GT.ListId
)
initialSidePanel :: Maybe (Record SidePanel)
initialSidePanel = Nothing
focusedSidePanel :: T.Box (Maybe (Record SidePanel))
-> R.Hooks { mGraph :: T.Box (Maybe SigmaxT.SGraph)
, mMetaData :: T.Box (Maybe GET.MetaData)
, multiSelectEnabled :: T.Box Boolean
, removedNodeIds :: T.Box SigmaxT.NodeIds
, selectedNodeIds :: T.Box SigmaxT.NodeIds
, showControls :: T.Box Boolean
, sideTab :: T.Box GET.SideTab
, showSidebar :: T.Box GT.SidePanelState
, showDoc :: T.Box (Maybe GT.ListId)
}
focusedSidePanel sidePanel = do
mGraph <- T.useFocused
(maybe Nothing _.mGraph)
(\val -> maybe Nothing (\sp -> Just $ sp { mGraph = val })) sidePanel
mMetaData <- T.useFocused
(maybe Nothing _.mMetaData)
(\val -> maybe Nothing (\sp -> Just $ sp { mMetaData = val })) sidePanel
multiSelectEnabled <- T.useFocused
(maybe false _.multiSelectEnabled)
(\val -> maybe Nothing (\sp -> Just $ sp { multiSelectEnabled = val })) sidePanel
removedNodeIds <- T.useFocused
(maybe Set.empty _.removedNodeIds)
(\val -> maybe Nothing (\sp -> Just $ sp { removedNodeIds = val })) sidePanel
selectedNodeIds <- T.useFocused
(maybe Set.empty _.selectedNodeIds)
(\val -> maybe Nothing (\sp -> Just $ sp { selectedNodeIds = val })) sidePanel
showControls <- T.useFocused
(maybe false _.showControls)
(\val -> maybe Nothing (\sp -> Just $ sp { showControls = val })) sidePanel
sideTab <- T.useFocused
(maybe GET.SideTabLegend _.sideTab)
(\val -> maybe Nothing (\sp -> Just $ sp { sideTab = val })) sidePanel
showSidebar <- T.useFocused
(maybe GT.InitialClosed _.showSidebar)
(\val -> maybe Nothing (\sp -> Just $ sp { showSidebar = val })) sidePanel
showDoc <- T.useFocused
(maybe Nothing _.showDoc)
(\val -> maybe Nothing (\sp -> Just $ sp { showDoc = val }
)) sidePanel
pure $ {
mGraph
, mMetaData
, multiSelectEnabled
, removedNodeIds
, selectedNodeIds
, showControls
, sideTab
, showSidebar
, showDoc
}
module Gargantext.Components.GraphExplorer.Store
( Store
, State
, options
, context
, provide
) where
import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Data.Set as Set
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Types as GT
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Reactix as R
import Toestand as T
import Unsafe.Coerce (unsafeCoerce)
here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Store"
type Store =
-- Data
( graph :: T.Box SigmaxT.SGraph
, graphId :: T.Box GET.GraphId
, mMetaData :: T.Box (Maybe GET.MetaData)
, hyperdataGraph :: T.Box GET.HyperdataGraph
-- Layout
, showControls :: T.Box Boolean
, sideTab :: T.Box GET.SideTab
, showSidebar :: T.Box GT.SidePanelState
, showDoc :: T.Box (Maybe GT.ListId)
-- Controls
, multiSelectEnabled :: T.Box Boolean
, edgeConfluence :: T.Box Range.NumberRange
, edgeWeight :: T.Box Range.NumberRange
, forceAtlasState :: T.Box SigmaxT.ForceAtlasState
, graphStage :: T.Box GET.Stage
, nodeSize :: T.Box Range.NumberRange
, showEdges :: T.Box SigmaxT.ShowEdgesState
, showLouvain :: T.Box Boolean
, labelSize :: T.Box Number
, mouseSelectorSize :: T.Box Number
, startForceAtlas :: T.Box Boolean
-- Terms update
, removedNodeIds :: T.Box SigmaxT.NodeIds
, selectedNodeIds :: T.Box SigmaxT.NodeIds
)
type State =
-- Data
( graph :: SigmaxT.SGraph
, graphId :: GET.GraphId
, mMetaData :: Maybe GET.MetaData
, hyperdataGraph :: GET.HyperdataGraph
-- Layout
, showControls :: Boolean
, sideTab :: GET.SideTab
, showSidebar :: GT.SidePanelState
, showDoc :: Maybe GT.ListId
-- Controls
, multiSelectEnabled :: Boolean
, edgeConfluence :: Range.NumberRange
, edgeWeight :: Range.NumberRange
, forceAtlasState :: SigmaxT.ForceAtlasState
, graphStage :: GET.Stage
, nodeSize :: Range.NumberRange
, showEdges :: SigmaxT.ShowEdgesState
, showLouvain :: Boolean
, labelSize :: Number
, mouseSelectorSize :: Number
, startForceAtlas :: Boolean
-- Terms update
, removedNodeIds :: SigmaxT.NodeIds
, selectedNodeIds :: SigmaxT.NodeIds
)
options ::
{ labelSize :: Number
, mouseSelectorSize :: Number
, multiSelectEnabled :: Boolean
, removedNodeIds :: SigmaxT.NodeIds
, selectedNodeIds :: SigmaxT.NodeIds
, showControls :: Boolean
, showDoc :: Maybe GT.ListId
, showSidebar :: GT.SidePanelState
, sideTab :: GET.SideTab
, edgeConfluence :: Range.NumberRange
, graphStage :: GET.Stage
, nodeSize :: Range.NumberRange
, showLouvain :: Boolean
, showEdges :: SigmaxT.ShowEdgesState
}
options =
-- Layout
{ showControls : false
, sideTab : GET.SideTabLegend
, showSidebar : GT.InitialClosed
, showDoc : Nothing
-- Controls
, multiSelectEnabled : false
, labelSize : 14.0
, mouseSelectorSize : 15.0
, edgeConfluence : Range.Closed { min: 0.0, max: 1.0 }
, graphStage : GET.Init
, nodeSize : Range.Closed { min: 0.0, max: 100.0 }
, showLouvain : false
, showEdges : SigmaxT.EShow
-- Terms update
, removedNodeIds : Set.empty
, selectedNodeIds : Set.empty
}
context :: R.Context (Record Store)
context = R.createContext $ unsafeCoerce unit
provide :: Record State -> Array R.Element -> R.Element
provide values = Stores.provideStore here.name values context
module Gargantext.Components.GraphExplorer.Toolbar.Controls module Gargantext.Components.GraphExplorer.Toolbar.Controls
( Controls ( controls
, useGraphControls
, controls
, controlsCpt
) where ) where
import Prelude import Prelude
...@@ -15,10 +12,10 @@ import Data.Sequence as Seq ...@@ -15,10 +12,10 @@ import Data.Sequence as Seq
import Data.Set as Set import Data.Set as Set
import Effect.Timer (setTimeout) import Effect.Timer (setTimeout)
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphExplorer.Resources as Graph
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Toolbar.Buttons (centerButton, cameraButton, edgesToggleButton, louvainToggleButton, pauseForceAtlasButton, multiSelectEnabledButton) import Gargantext.Components.GraphExplorer.Toolbar.Buttons (centerButton, cameraButton, edgesToggleButton, louvainToggleButton, pauseForceAtlasButton, multiSelectEnabledButton)
import Gargantext.Components.GraphExplorer.Toolbar.RangeControl (edgeConfluenceControl, edgeWeightControl, nodeSizeControl) import Gargantext.Components.GraphExplorer.Toolbar.RangeControl (edgeConfluenceControl, edgeWeightControl, nodeSizeControl)
import Gargantext.Components.GraphExplorer.Resources as Graph
import Gargantext.Components.GraphExplorer.Sidebar.Types as GEST
import Gargantext.Components.GraphExplorer.Toolbar.SlideButton (labelSizeButton, mouseSelectorSizeButton) import Gargantext.Components.GraphExplorer.Toolbar.SlideButton (labelSizeButton, mouseSelectorSizeButton)
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
...@@ -27,6 +24,7 @@ import Gargantext.Sessions (Session) ...@@ -27,6 +24,7 @@ import Gargantext.Sessions (Session)
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils.Range as Range import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
...@@ -36,41 +34,23 @@ here :: R2.Here ...@@ -36,41 +34,23 @@ here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Toolbar.Controls" here = R2.here "Gargantext.Components.GraphExplorer.Toolbar.Controls"
type Controls = type Controls =
( edgeConfluence :: T.Box Range.NumberRange ( reloadForest :: T2.ReloadS
, edgeWeight :: T.Box Range.NumberRange
, forceAtlasState :: T.Box SigmaxT.ForceAtlasState
, graph :: SigmaxT.SGraph
, graphId :: GET.GraphId
, graphStage :: T.Box Graph.Stage
, hyperdataGraph :: GET.HyperdataGraph
, multiSelectEnabled :: T.Box Boolean
, nodeSize :: T.Box Range.NumberRange
, reloadForest :: T2.ReloadS
, removedNodeIds :: T.Box SigmaxT.NodeIds
, selectedNodeIds :: T.Box SigmaxT.NodeIds
, session :: Session , session :: Session
, showControls :: T.Box Boolean
, showEdges :: T.Box SigmaxT.ShowEdgesState
, showLouvain :: T.Box Boolean
, showSidebar :: T.Box GT.SidePanelState
, sideTab :: T.Box GET.SideTab
, sigmaRef :: R.Ref Sigmax.Sigma , sigmaRef :: R.Ref Sigmax.Sigma
) )
type LocalControls = ( labelSize :: T.Box Number, mouseSelectorSize :: T.Box Number ) controls :: R2.Leaf Controls
controls = R2.leaf controlsCpt
initialLocalControls :: R.Hooks (Record LocalControls)
initialLocalControls = do
labelSize <- T.useBox 14.0
mouseSelectorSize <- T.useBox 15.0
pure $ { labelSize, mouseSelectorSize }
controls :: R2.Component Controls controlsCpt :: R.Memo Controls
controls = R.createElement controlsCpt controlsCpt = R.memo' $ here.component "controls" cpt where
controlsCpt :: R.Component Controls cpt { reloadForest
controlsCpt = here.component "controls" cpt , session
where , sigmaRef
cpt { edgeConfluence } _ = do
-- | States
-- |
{ edgeConfluence
, edgeWeight , edgeWeight
, forceAtlasState , forceAtlasState
, graph , graph
...@@ -79,37 +59,36 @@ controlsCpt = here.component "controls" cpt ...@@ -79,37 +59,36 @@ controlsCpt = here.component "controls" cpt
, hyperdataGraph , hyperdataGraph
, multiSelectEnabled , multiSelectEnabled
, nodeSize , nodeSize
, reloadForest
, selectedNodeIds , selectedNodeIds
, session
, showEdges , showEdges
, showLouvain , showLouvain
, showSidebar , showSidebar
, sideTab , sideTab
, sigmaRef } _ = do , mouseSelectorSize
, labelSize
-- | States } <- Stores.useStore GraphStore.context
-- |
forceAtlasState' <- T.useLive T.unequal forceAtlasState forceAtlasState' <- R2.useLive' forceAtlasState
graphStage' <- T.useLive T.unequal graphStage graph' <- R2.useLive' graph
selectedNodeIds' <- T.useLive T.unequal selectedNodeIds graphId' <- R2.useLive' graphId
showSidebar' <- T.useLive T.unequal showSidebar graphStage' <- R2.useLive' graphStage
hyperdataGraph' <- R2.useLive' hyperdataGraph
selectedNodeIds' <- R2.useLive' selectedNodeIds
showSidebar' <- R2.useLive' showSidebar
localControls <- initialLocalControls
-- ref to track automatic FA pausing -- ref to track automatic FA pausing
-- If user pauses FA before auto is triggered, clear the timeoutId -- If user pauses FA before auto is triggered, clear the timeoutId
mFAPauseRef <- R.useRef Nothing mFAPauseRef <- R.useRef Nothing
-- | Effects -- | Effects
-- | -- |
-- When graph is changed, cleanup the mFAPauseRef so that forceAtlas -- When graph is changed, cleanup the mFAPauseRef so that forceAtlas
-- timeout is retriggered. -- timeout is retriggered.
R.useEffect' $ do R.useEffect' $ do
case graphStage' of case graphStage' of
Graph.Init -> R.setRef mFAPauseRef Nothing GET.Init -> R.setRef mFAPauseRef Nothing
_ -> pure unit _ -> pure unit
-- Handle case when FA is paused from outside events, eg. the automatic timer. -- Handle case when FA is paused from outside events, eg. the automatic timer.
...@@ -145,10 +124,10 @@ controlsCpt = here.component "controls" cpt ...@@ -145,10 +124,10 @@ controlsCpt = here.component "controls" cpt
pure unit pure unit
-- | Computed -- | Computed
-- | -- |
let edgesConfluenceSorted = A.sortWith (_.confluence) $ Seq.toUnfoldable $ SigmaxT.graphEdges graph let edgesConfluenceSorted = A.sortWith (_.confluence) $ Seq.toUnfoldable $ SigmaxT.graphEdges graph'
let edgeConfluenceMin = maybe 0.0 _.confluence $ A.head edgesConfluenceSorted let edgeConfluenceMin = maybe 0.0 _.confluence $ A.head edgesConfluenceSorted
let edgeConfluenceMax = maybe 100.0 _.confluence $ A.last edgesConfluenceSorted let edgeConfluenceMax = maybe 100.0 _.confluence $ A.last edgesConfluenceSorted
let edgeConfluenceRange = Range.Closed { min: edgeConfluenceMin, max: edgeConfluenceMax } let edgeConfluenceRange = Range.Closed { min: edgeConfluenceMin, max: edgeConfluenceMax }
...@@ -159,18 +138,18 @@ controlsCpt = here.component "controls" cpt ...@@ -159,18 +138,18 @@ controlsCpt = here.component "controls" cpt
--let edgeWeightRange = Range.Closed { min: edgeWeightMin, max: edgeWeightMax } --let edgeWeightRange = Range.Closed { min: edgeWeightMin, max: edgeWeightMax }
let edgeWeightRange = Range.Closed { let edgeWeightRange = Range.Closed {
min: 0.0 min: 0.0
, max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph , max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph'
} }
let nodesSorted = A.sortWith (_.size) $ Seq.toUnfoldable $ SigmaxT.graphNodes graph let nodesSorted = A.sortWith (_.size) $ Seq.toUnfoldable $ SigmaxT.graphNodes graph'
let nodeSizeMin = maybe 0.0 _.size $ A.head nodesSorted let nodeSizeMin = maybe 0.0 _.size $ A.head nodesSorted
let nodeSizeMax = maybe 100.0 _.size $ A.last nodesSorted let nodeSizeMax = maybe 100.0 _.size $ A.last nodesSorted
let nodeSizeRange = Range.Closed { min: nodeSizeMin, max: nodeSizeMax } let nodeSizeRange = Range.Closed { min: nodeSizeMin, max: nodeSizeMax }
let gap = H.span { className: "graph-toolbar__gap" } [] let gap = H.span { className: "graph-toolbar__gap" } []
-- | Render -- | Render
-- | -- |
pure $ pure $
...@@ -216,8 +195,8 @@ controlsCpt = here.component "controls" cpt ...@@ -216,8 +195,8 @@ controlsCpt = here.component "controls" cpt
gap gap
, ,
cameraButton cameraButton
{ id: graphId { id: graphId'
, hyperdataGraph: hyperdataGraph , hyperdataGraph: hyperdataGraph'
, session: session , session: session
, sigmaRef: sigmaRef , sigmaRef: sigmaRef
, reloadForest , reloadForest
...@@ -241,7 +220,7 @@ controlsCpt = here.component "controls" cpt ...@@ -241,7 +220,7 @@ controlsCpt = here.component "controls" cpt
, ,
-- toggle multi node selection -- toggle multi node selection
-- save button -- save button
mouseSelectorSizeButton sigmaRef localControls.mouseSelectorSize mouseSelectorSizeButton sigmaRef mouseSelectorSize
] ]
] ]
, ,
...@@ -275,7 +254,7 @@ controlsCpt = here.component "controls" cpt ...@@ -275,7 +254,7 @@ controlsCpt = here.component "controls" cpt
-- run demo -- run demo
-- search button -- search button
-- search topics -- search topics
labelSizeButton sigmaRef localControls.labelSize labelSizeButton sigmaRef labelSize
, ,
-- labels size: 1-4 -- labels size: 1-4
nodeSizeControl nodeSizeControl
...@@ -314,62 +293,3 @@ controlsCpt = here.component "controls" cpt ...@@ -314,62 +293,3 @@ controlsCpt = here.component "controls" cpt
-- , reloadForest: reloadForest } ] -- , reloadForest: reloadForest } ]
-- ] -- ]
-- ] -- ]
useGraphControls :: { forceAtlasS :: SigmaxT.ForceAtlasState
, graph :: SigmaxT.SGraph
, graphId :: GET.GraphId
, hyperdataGraph :: GET.HyperdataGraph
, reloadForest :: T2.ReloadS
, session :: Session
, sidePanel :: T.Box (Maybe (Record GEST.SidePanel))
}
-> R.Hooks (Record Controls)
useGraphControls { forceAtlasS
, graph
, graphId
, hyperdataGraph
, reloadForest
, session
, sidePanel
} = do
edgeConfluence <- T.useBox $ Range.Closed { min: 0.0, max: 1.0 }
edgeWeight <- T.useBox $ Range.Closed {
min: 0.0
, max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph
}
forceAtlasState <- T.useBox forceAtlasS
graphStage <- T.useBox Graph.Init
nodeSize <- T.useBox $ Range.Closed { min: 0.0, max: 100.0 }
showEdges <- T.useBox SigmaxT.EShow
showLouvain <- T.useBox false
sigma <- Sigmax.initSigma
sigmaRef <- R.useRef sigma
{ multiSelectEnabled
, removedNodeIds
, selectedNodeIds
, showControls
, sideTab
, showSidebar
} <- GEST.focusedSidePanel sidePanel
pure { edgeConfluence
, edgeWeight
, forceAtlasState
, graph
, graphId
, graphStage
, hyperdataGraph
, multiSelectEnabled
, nodeSize
, removedNodeIds
, selectedNodeIds
, session
, showControls
, showEdges
, showLouvain
, showSidebar
, sideTab
, sigmaRef
, reloadForest
}
...@@ -2,40 +2,36 @@ module Gargantext.Components.GraphExplorer.TopBar (topBar) where ...@@ -2,40 +2,36 @@ module Gargantext.Components.GraphExplorer.TopBar (topBar) where
import Gargantext.Prelude hiding (max, min) import Gargantext.Prelude hiding (max, min)
import Data.Maybe (Maybe)
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), Variant(..)) import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), Variant(..))
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Topbar.Search (nodeSearchControl) import Gargantext.Components.GraphExplorer.Topbar.Search (nodeSearchControl)
import Gargantext.Components.GraphExplorer.Sidebar.Types as GEST
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils ((?)) import Gargantext.Utils ((?))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Toestand as T import Toestand as T
type Props =
( sidePanelGraph :: T.Box (Maybe (Record GEST.SidePanel))
)
here :: R2.Here here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.TopBar" here = R2.here "Gargantext.Components.GraphExplorer.TopBar"
topBar :: R2.Leaf Props topBar :: R2.Leaf ()
topBar = R2.leaf component topBar = R2.leaf component
component :: R.Component Props component :: R.Component ()
component = here.component "topBar" cpt where component = here.component "topBar" cpt where
cpt { sidePanelGraph } _ = do cpt _ _ = do
-- States -- States
{ mGraph { graph
, multiSelectEnabled , multiSelectEnabled
, selectedNodeIds , selectedNodeIds
, showControls , showControls
, showSidebar , showSidebar
} <- GEST.focusedSidePanel sidePanelGraph } <- Stores.useStore GraphStore.context
mGraph' <- R2.useLive' mGraph graph' <- R2.useLive' graph
showControls' <- R2.useLive' showControls showControls' <- R2.useLive' showControls
showSidebar' <- R2.useLive' showSidebar showSidebar' <- R2.useLive' showSidebar
...@@ -73,10 +69,8 @@ component = here.component "topBar" cpt where ...@@ -73,10 +69,8 @@ component = here.component "topBar" cpt where
] ]
, ,
-- Search -- Search
R2.fromMaybe_ mGraph' \graph ->
nodeSearchControl nodeSearchControl
{ graph { graph: graph'
, multiSelectEnabled , multiSelectEnabled
, selectedNodeIds , selectedNodeIds
, className: "graph-topbar__search" , className: "graph-topbar__search"
......
module Gargantext.Components.GraphExplorer.Types where module Gargantext.Components.GraphExplorer.Types where
import Gargantext.Prelude
import Data.Array ((!!), length) import Data.Array ((!!), length)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Eq.Generic (genericEq) import Data.Eq.Generic (genericEq)
import Data.Maybe (Maybe(..), fromJust) import Data.Maybe (Maybe(..), fromJust)
import Data.Newtype (class Newtype) import Data.Newtype (class Newtype)
import Data.Ord
import Data.Ord.Generic (genericCompare) import Data.Ord.Generic (genericCompare)
import Data.Symbol (SProxy(..)) import Data.Symbol (SProxy(..))
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import Record as Record import Record as Record
import Simple.JSON as JSON import Simple.JSON as JSON
import Gargantext.Prelude
type GraphId = Int type GraphId = Int
newtype Node = Node { newtype Node = Node {
...@@ -164,7 +163,7 @@ instance Ord SelectedNode where compare = genericCompare ...@@ -164,7 +163,7 @@ instance Ord SelectedNode where compare = genericCompare
instance Show SelectedNode where show (SelectedNode node) = node.label instance Show SelectedNode where show (SelectedNode node) = node.label
type State = ( -- type State = (
-- corpusId :: R.State Int -- corpusId :: R.State Int
--, filePath :: R.State String --, filePath :: R.State String
--, graphData :: R.State GraphData --, graphData :: R.State GraphData
...@@ -177,7 +176,7 @@ type State = ( ...@@ -177,7 +176,7 @@ type State = (
--, sigmaGraphData :: R.State (Maybe SigmaxTypes.SGraph) --, sigmaGraphData :: R.State (Maybe SigmaxTypes.SGraph)
--, sigmaSettings :: R.State ({|Graph.SigmaSettings}) --, sigmaSettings :: R.State ({|Graph.SigmaSettings})
--treeId :: R.State (Maybe TreeId) --treeId :: R.State (Maybe TreeId)
) -- )
initialGraphData :: GraphData initialGraphData :: GraphData
initialGraphData = GraphData { initialGraphData = GraphData {
...@@ -255,3 +254,7 @@ instance JSON.ReadForeign HyperdataGraph where ...@@ -255,3 +254,7 @@ instance JSON.ReadForeign HyperdataGraph where
pure $ HyperdataGraph $ Record.rename cameraP mCameraP inst pure $ HyperdataGraph $ Record.rename cameraP mCameraP inst
instance JSON.WriteForeign HyperdataGraph where instance JSON.WriteForeign HyperdataGraph where
writeImpl (HyperdataGraph c) = JSON.writeImpl $ Record.rename mCameraP cameraP c writeImpl (HyperdataGraph c) = JSON.writeImpl $ Record.rename mCameraP cameraP c
data Stage = Init | Ready | Cleanup
derive instance Generic Stage _
derive instance Eq Stage
...@@ -5,21 +5,24 @@ module Gargantext.Components.Nodes.Corpus.Graph ...@@ -5,21 +5,24 @@ module Gargantext.Components.Nodes.Corpus.Graph
import Gargantext.Prelude import Gargantext.Prelude
import DOM.Simple (document, querySelector) import DOM.Simple (document, querySelector)
import Data.Int as I
import Data.Maybe (Maybe(..), isJust, maybe) import Data.Maybe (Maybe(..), isJust, maybe)
import Data.Set as Set import Data.Sequence as Seq
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Gargantext.Components.App.Data (Boxes) import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphExplorer.Layout (convert, layout) import Gargantext.Components.GraphExplorer.Layout (convert, layout)
import Gargantext.Components.GraphExplorer.Toolbar.Controls as Controls import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Config.REST (AffRESTError, logRESTError) import Gargantext.Config.REST (AffRESTError, logRESTError)
import Gargantext.Hooks.Loader (useLoaderEffect) import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxT import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Routes (SessionRoute(NodeAPI)) import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Sessions (Session, get) import Gargantext.Sessions (Session, get)
import Gargantext.Types as Types import Gargantext.Types as Types
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2 import Gargantext.Utils.Toestand as T2
import Reactix as R import Reactix as R
...@@ -123,18 +126,18 @@ graphLayoutCpt = here.component "explorerLayout" cpt where ...@@ -123,18 +126,18 @@ graphLayoutCpt = here.component "explorerLayout" cpt where
handler loaded@(GET.HyperdataGraph { graph: hyperdataGraph }) = handler loaded@(GET.HyperdataGraph { graph: hyperdataGraph }) =
content { graph content { graph
, hyperdataGraph: loaded , hyperdataGraph: loaded
, mMetaData' , mMetaData
, session , session
, boxes: props.boxes , boxes: props.boxes
, graphId , graphId
} }
where where
Tuple mMetaData' graph = convert hyperdataGraph Tuple mMetaData graph = convert hyperdataGraph
-------------------------------------------------------- --------------------------------------------------------
type ContentProps = type ContentProps =
( mMetaData' :: Maybe GET.MetaData ( mMetaData :: Maybe GET.MetaData
, graph :: SigmaxT.SGraph , graph :: SigmaxT.SGraph
, hyperdataGraph :: GET.HyperdataGraph , hyperdataGraph :: GET.HyperdataGraph
, session :: Session , session :: Session
...@@ -147,8 +150,8 @@ content = R2.leaf contentCpt ...@@ -147,8 +150,8 @@ content = R2.leaf contentCpt
contentCpt :: R.Component ContentProps contentCpt :: R.Component ContentProps
contentCpt = here.component "content" cpt where contentCpt = here.component "content" cpt where
cpt props@{ boxes cpt { boxes
, mMetaData' , mMetaData
, graph , graph
, graphId , graphId
, session , session
...@@ -158,48 +161,52 @@ contentCpt = here.component "content" cpt where ...@@ -158,48 +161,52 @@ contentCpt = here.component "content" cpt where
-- | -- |
let let
startForceAtlas = maybe true startForceAtlas = maybe true
(\(GET.MetaData { startForceAtlas: sfa }) -> sfa) mMetaData' (\(GET.MetaData { startForceAtlas: sfa }) -> sfa) mMetaData
forceAtlasS = if startForceAtlas forceAtlasState
= if startForceAtlas
then SigmaxT.InitialRunning then SigmaxT.InitialRunning
else SigmaxT.InitialStopped else SigmaxT.InitialStopped
-- | Hooks -- Hydrate GraphStore
-- | state :: Record GraphStore.State
state =
-- Hydrate controls -- Data
controls <- Controls.useGraphControls { graph
{ forceAtlasS
, graph
, graphId , graphId
, mMetaData
, hyperdataGraph , hyperdataGraph
, reloadForest: boxes.reloadForest -- Controls
, session , startForceAtlas
, sidePanel: boxes.sidePanelGraph , forceAtlasState
, edgeWeight: Range.Closed
{ min: 0.0
, max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph
} }
-- (default options)
-- @WIP: testing order of Record.merge
} `Record.merge` GraphStore.options
-- Hydrate Boxes -- | Hooks
R.useEffectOnce' $ -- |
flip T.write_ boxes.sidePanelGraph $ Just
{ mGraph: Just graph sigmaRef <- Sigmax.initSigma >>= R.useRef
, mMetaData: mMetaData'
, multiSelectEnabled: false
, removedNodeIds: Set.empty
, selectedNodeIds: Set.empty
, showControls: false
, sideTab: GET.SideTabLegend
, showSidebar: Types.InitialClosed
, showDoc: Nothing
}
-- | Render -- | Render
-- | -- |
pure $ pure $
layout $ GraphStore.provide
{ controls state
} `Record.merge` props [
layout
{ session
, boxes
, sigmaRef
, graphId
}
]
-------------------------------------------------------------- --------------------------------------------------------------
......
...@@ -91,6 +91,7 @@ type Module = String ...@@ -91,6 +91,7 @@ type Module = String
type Here = type Here =
{ component :: forall p. String -> R.HooksComponent p -> R.Component p { component :: forall p. String -> R.HooksComponent p -> R.Component p
, ntComponent :: forall p. String -> NTHooksComponent p -> NTComponent p , ntComponent :: forall p. String -> NTHooksComponent p -> NTComponent p
, name :: Module
| RowConsole | RowConsole
} }
...@@ -98,6 +99,7 @@ here :: Module -> Here ...@@ -98,6 +99,7 @@ here :: Module -> Here
here mod = here mod =
{ component : R.hooksComponentWithModule mod { component : R.hooksComponentWithModule mod
, ntComponent : ntHooksComponentWithModule mod , ntComponent : ntHooksComponentWithModule mod
, name : mod
, log : Console.print Console.Main mod Console.Log , log : Console.print Console.Main mod Console.Log
, log2 : Console.print2 Console.Main mod Console.Log , log2 : Console.print2 Console.Main mod Console.Log
, log3 : Console.print3 Console.Main mod Console.Log , log3 : Console.print3 Console.Main mod Console.Log
......
module Gargantext.Utils.Stores
( createStore
, provideStore
, useStore
) where
import Gargantext.Prelude
import Prim.RowList (class RowToList)
import Reactix as R
import Toestand as T
import Toestand.Records as TR
-- StoreFactory: R.Hook (Record Store) → create focus boxes, hydrate box values
-- StoreProvider: R.Hooks (Record Store) → provide context with previous boxes
-- ↓
-- StoreHook: R.Hooks (Record Store) → use context
-- | From state values to focused boxes
createStore :: forall boxes l state.
RowToList state l
=> TR.UseFocusedFields l boxes () (T.Box (Record state))
=> Record state
-> R.Hooks (Record boxes)
createStore = T.useBox >=> flip T.useFocusedFields {}
-- | Set <Store.Provider> bearing Stores as a Context
-- |
-- | (!) do not use store binds in this specific component (eg. `useStores`)
provideStore :: forall boxes l state.
RowToList state l
=> TR.UseFocusedFields l boxes () (T.Box (Record state))
=> String
-> Record state
-> R.Context (Record boxes)
-> Array R.Element
-> R.Element
provideStore name state context
= R.createElement (R.hooksComponent name cpt) {}
where
cpt _ children = do
store <- createStore state
pure $ R.provideContext context store $ children
-- | (?) As we use "React Provide API", we just want to rely on its Global
-- | Reference (and not as Mutable State thanks to "Consumer API")
-- | Hence the "unsafeCoerce" used on every provided context, avoiding
-- | unwanted computing at each import
-- |
-- | It also implies that every call to the proxy reference (made thanks to
-- | below <Store.Provider> are made AFTER first mount of this very,
-- | component, otherwise, every call will return the empty `unit`)
useStore :: forall boxes.
R.Context (Record boxes)
-> R.Hooks (Record boxes)
useStore = R.useContext
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment