Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Grégoire Locqueville
purescript-gargantext
Commits
14586cea
Commit
14586cea
authored
Nov 28, 2019
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev-graph-eff-rewrite' into dev
parents
8fd75474
22367b4a
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
136 additions
and
117 deletions
+136
-117
Graph.css
dist/styles/Graph.css
+1
-1
Graph.sass
dist/styles/Graph.sass
+1
-1
FacetsTable.purs
src/Gargantext/Components/FacetsTable.purs
+15
-7
Graph.purs
src/Gargantext/Components/Graph.purs
+30
-22
GraphExplorer.purs
src/Gargantext/Components/GraphExplorer.purs
+24
-22
Controls.purs
src/Gargantext/Components/GraphExplorer/Controls.purs
+11
-5
Ends.purs
src/Gargantext/Ends.purs
+2
-0
Loader.purs
src/Gargantext/Hooks/Loader.purs
+24
-51
Types.purs
src/Gargantext/Hooks/Sigmax/Types.purs
+4
-1
Reactix.purs
src/Gargantext/Utils/Reactix.purs
+24
-7
No files found.
dist/styles/Graph.css
View file @
14586cea
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
}
}
#graph-explorer
#sp-container
{
#graph-explorer
#sp-container
{
position
:
absolute
;
position
:
absolute
;
left
:
63
%
;
left
:
70
%
;
top
:
150px
;
top
:
150px
;
z-index
:
1
;
z-index
:
1
;
border
:
1px
white
solid
;
border
:
1px
white
solid
;
...
...
dist/styles/Graph.sass
View file @
14586cea
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
#sp-container
#sp-container
position
:
absolute
position
:
absolute
left
:
63
%
left
:
70
%
top
:
150px
top
:
150px
z-index
:
1
z-index
:
1
border
:
1px
white
solid
border
:
1px
white
solid
...
...
src/Gargantext/Components/FacetsTable.purs
View file @
14586cea
...
@@ -5,15 +5,15 @@ module Gargantext.Components.FacetsTable where
...
@@ -5,15 +5,15 @@ module Gargantext.Components.FacetsTable where
import Prelude
import Prelude
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.:), (:=), (~>))
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.:), (:=), (~>))
import Data.Array (filter, (!!))
import Data.Array (
concat,
filter, (!!))
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.Tuple (fst)
import Data.Tuple (fst
, snd
)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log)
import DOM.Simple.Console (log
, log2
)
import Effect (Effect)
import Effect (Effect)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import Effect.Aff (Aff, launchAff_)
import Effect.Aff (Aff, launchAff_)
...
@@ -44,7 +44,8 @@ newtype SearchQuery = SearchQuery { query :: TextQuery }
...
@@ -44,7 +44,8 @@ newtype SearchQuery = SearchQuery { query :: TextQuery }
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery {query})
encodeJson (SearchQuery {query})
= "query" := query !! 0 -- TODO anoe
-- = "query" := query !! 0 -- TODO anoe
= "query" := concat query
~> jsonEmptyObject
~> jsonEmptyObject
newtype SearchResults = SearchResults { results :: Array Response }
newtype SearchResults = SearchResults { results :: Array Response }
...
@@ -170,6 +171,14 @@ docViewCpt = R.hooksComponent "G.C.FacetsTable.DocView" cpt
...
@@ -170,6 +171,14 @@ docViewCpt = R.hooksComponent "G.C.FacetsTable.DocView" cpt
cpt {frontends, session, nodeId, listId, query, totalRecords, chart, container} _ = do
cpt {frontends, session, nodeId, listId, query, totalRecords, chart, container} _ = do
deletions <- R.useState' initialDeletions
deletions <- R.useState' initialDeletions
path <- R.useState' $ initialPagePath {nodeId, listId, query, session}
path <- R.useState' $ initialPagePath {nodeId, listId, query, session}
R.useEffect' $ do
let ipp = initialPagePath {nodeId, listId, query, session}
if fst path == ipp then
pure unit
else
snd path $ const ipp
pure $ H.div { className: "container1" }
pure $ H.div { className: "container1" }
[ H.div { className: "row" }
[ H.div { className: "row" }
[ chart
[ chart
...
@@ -237,7 +246,6 @@ initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, que
...
@@ -237,7 +246,6 @@ initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, que
loadPage :: PagePath -> Aff (Array DocumentsView)
loadPage :: PagePath -> Aff (Array DocumentsView)
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy}} = do
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy}} = do
liftEffect $ log "loading documents page: loadPage with Offset and limit"
let p = Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy } (Just nodeId)
let p = Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy } (Just nodeId)
SearchResults res <- post session p $ SearchQuery {query}
SearchResults res <- post session p $ SearchQuery {query}
pure $ res2corpus <$> res.results
pure $ res2corpus <$> res.results
...
@@ -280,10 +288,10 @@ page :: Record PageProps -> R.Element
...
@@ -280,10 +288,10 @@ page :: Record PageProps -> R.Element
page props = R.createElement pageCpt props []
page props = R.createElement pageCpt props []
pageCpt :: R.Component PageProps
pageCpt :: R.Component PageProps
pageCpt = R.
static
Component "G.C.FacetsTable.Page" cpt
pageCpt = R.
hooks
Component "G.C.FacetsTable.Page" cpt
where
where
cpt {frontends, totalRecords, container, deletions, documents, session, path: path@({nodeId, listId, query} /\ setPath)} _ = do
cpt {frontends, totalRecords, container, deletions, documents, session, path: path@({nodeId, listId, query} /\ setPath)} _ = do
T.table { rows, container, colNames, totalRecords, params, wrapColElts
}
pure $ T.table { rows, container, colNames, totalRecords, params, wrapColElts
}
where
where
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
params = (fst path).params /\ setParams
params = (fst path).params /\ setParams
...
...
src/Gargantext/Components/Graph.purs
View file @
14586cea
...
@@ -4,31 +4,28 @@ module Gargantext.Components.Graph
...
@@ -4,31 +4,28 @@ module Gargantext.Components.Graph
-- , forceAtlas2Settings, ForceAtlas2Settings, ForceAtlas2OptionalSettings
-- , forceAtlas2Settings, ForceAtlas2Settings, ForceAtlas2OptionalSettings
-- )
-- )
where
where
import Prelude (bind,
discard, pure, ($), unit, map
)
import Prelude (bind,
const, discard, pure, ($), unit
)
import Data.Either (Either(..))
import Data.Either (Either(..))
import Data.Map as Map
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Nullable (notNull, null, Nullable)
import Data.Nullable (Nullable)
import Data.Set as Set
import Data.Tuple (fst)
import Data.Tuple (fst, snd, Tuple(..))
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import DOM.Simple (createElement, setAttr)
import DOM.Simple.Console (log, log2)
import DOM.Simple.Console (log, log2)
import DOM.Simple.Types (Element)
import DOM.Simple.Types (Element)
import Effect.Timer (setTimeout)
import FFI.Simple (delay)
import FFI.Simple (delay, (..))
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as RH
import Reactix.DOM.HTML as RH
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Utils.Reactix as R2
type OnProps = ()
type OnProps = ()
type Graph = SigmaxTypes.Graph SigmaxTypes.Node SigmaxTypes.Edge
type Graph = SigmaxTypes.Graph SigmaxTypes.Node SigmaxTypes.Edge
data Stage = Init | Ready | Cleanup
type Props sigma forceatlas2 =
type Props sigma forceatlas2 =
( elRef :: R.Ref (Nullable Element)
( elRef :: R.Ref (Nullable Element)
, forceAtlas2Settings :: forceatlas2
, forceAtlas2Settings :: forceatlas2
...
@@ -36,6 +33,7 @@ type Props sigma forceatlas2 =
...
@@ -36,6 +33,7 @@ type Props sigma forceatlas2 =
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, sigmaSettings :: sigma
, sigmaSettings :: sigma
, sigmaRef :: R.Ref Sigmax.Sigma
, sigmaRef :: R.Ref Sigmax.Sigma
, stage :: R.State Stage
)
)
graph :: forall s fa2. Record (Props s fa2) -> R.Element
graph :: forall s fa2. Record (Props s fa2) -> R.Element
...
@@ -45,14 +43,18 @@ graphCpt :: forall s fa2. R.Component (Props s fa2)
...
@@ -45,14 +43,18 @@ graphCpt :: forall s fa2. R.Component (Props s fa2)
graphCpt = R.hooksComponent "Graph" cpt
graphCpt = R.hooksComponent "Graph" cpt
where
where
cpt props _ = do
cpt props _ = do
let nodesMap = SigmaxTypes.nodesMap props.graph
stageHooks props
let selectedNodeIds = props.selectedNodeIds
R.useEffect' $ do
-- NOTE: This div is not empty after sigma initializes.
Sigmax.dependOnSigma (R.readRef props.sigmaRef) "[graphCpt] no sigma" $ \sigma ->
-- When we change state, we make it empty though.
Sigmax.markSelectedNodes sigma (fst selectedNodeIds) nodesMap
--pure $ RH.div { ref: props.elRef, style: {height: "95%"} } []
pure $ case R.readNullableRef props.elRef of
Nothing -> RH.div {} []
Just el -> R.createPortal [] el
stageHooks props@{stage: (Init /\ setStage)} = do
R.useEffectOnce $ do
R.useEffectOnce $ do
log "[graphCpt] effect once"
let rSigma = R.readRef props.sigmaRef
let rSigma = R.readRef props.sigmaRef
case Sigmax.readSigma rSigma of
case Sigmax.readSigma rSigma of
...
@@ -76,20 +78,26 @@ graphCpt = R.hooksComponent "Graph" cpt
...
@@ -76,20 +78,26 @@ graphCpt = R.hooksComponent "Graph" cpt
Sigma.startForceAtlas2 sig props.forceAtlas2Settings
Sigma.startForceAtlas2 sig props.forceAtlas2Settings
-- bind the click event only initially, when ref was empty
-- bind the click event only initially, when ref was empty
Sigmax.bindSelectedNodesClick props.sigmaRef selectedNodeIds
Sigmax.bindSelectedNodesClick props.sigmaRef
props.
selectedNodeIds
Just sig -> do
Just sig -> do
pure unit
pure unit
setStage $ const $ Ready
delay unit $ \_ -> do
delay unit $ \_ -> do
log "[
G
raphCpt] cleanup"
log "[
g
raphCpt] cleanup"
pure $ pure unit
pure $ pure unit
-- NOTE: This div is not empty after sigma initializes.
stageHooks props@{stage: (Ready /\ setStage)} = do
-- When we change state, we make it empty though.
let nodesMap = SigmaxTypes.nodesMap props.graph
--pure $ RH.div { ref: props.elRef, style: {height: "95%"} } []
pure $ case R.readNullableRef props.elRef of
-- TODO Probably this can be optimized to re-mark selected nodes only when they changed
Nothing -> RH.div {} []
R.useEffect' $ do
Just el -> R.createPortal [] el
Sigmax.dependOnSigma (R.readRef props.sigmaRef) "[graphCpt] no sigma" $ \sigma ->
Sigmax.markSelectedNodes sigma (fst props.selectedNodeIds) nodesMap
stageHooks _ = pure unit
type SigmaSettings =
type SigmaSettings =
( animationsTime :: Number
( animationsTime :: Number
...
...
src/Gargantext/Components/GraphExplorer.purs
View file @
14586cea
...
@@ -18,6 +18,7 @@ import Reactix.DOM.HTML as RH
...
@@ -18,6 +18,7 @@ import Reactix.DOM.HTML as RH
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Sigmax (Sigma)
import Gargantext.Hooks.Sigmax (Sigma)
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Components.GraphExplorer.Controls as Controls
import Gargantext.Components.GraphExplorer.Controls as Controls
import Gargantext.Components.GraphExplorer.Sidebar as Sidebar
import Gargantext.Components.GraphExplorer.Sidebar as Sidebar
...
@@ -69,12 +70,23 @@ explorerCpt :: R.Component Props
...
@@ -69,12 +70,23 @@ explorerCpt :: R.Component Props
explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
where
where
cpt {frontends, graph, graphId, mCurrentRoute, mMetaData, session, sessions, treeId} _ = do
cpt {frontends, graph, graphId, mCurrentRoute, mMetaData, session, sessions, treeId} _ = do
dataRef <- R.useRef graph
graphRef <- R.useRef null
graphRef <- R.useRef null
controls <- Controls.useGraphControls
controls <- Controls.useGraphControls
state <- useExplorerState
showLogin <- snd <$> R.useState' true
showLogin <- snd <$> R.useState' true
selectedNodeIds <- R.useState' $ Set.empty
selectedNodeIds <- R.useState' $ Set.empty
R.useEffect' $ do
case Tuple (R.readRef dataRef) graph of
Tuple Nothing Nothing -> pure unit
Tuple (Just g1) (Just g2) | SigmaxTypes.eqGraph g1 g2 -> pure unit
_ -> do
let rSigma = R.readRef controls.sigmaRef
Sigmax.cleanupSigma rSigma "explorerCpt"
R.setRef dataRef graph
snd selectedNodeIds $ const Set.empty
snd controls.graphStage $ const Graph.Init
R.useEffect' $ do
R.useEffect' $ do
if fst controls.showSidePanel == GET.InitialClosed && (not Set.isEmpty $ fst selectedNodeIds) then
if fst controls.showSidePanel == GET.InitialClosed && (not Set.isEmpty $ fst selectedNodeIds) then
snd controls.showSidePanel $ \_ -> GET.Opened
snd controls.showSidePanel $ \_ -> GET.Opened
...
@@ -94,8 +106,8 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
...
@@ -94,8 +106,8 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
]
]
, row [ Controls.controls controls ]
, row [ Controls.controls controls ]
, row [ tree {mCurrentRoute, treeId} controls showLogin
, row [ tree {mCurrentRoute, treeId} controls showLogin
, RH.div { ref: graphRef, id: "graph-view", className:
"col-md-12"
, style: {height: "95%"} } [] -- graph container
, RH.div { ref: graphRef, id: "graph-view", className:
graphClassName controls
, style: {height: "95%"} } [] -- graph container
, mGraph graphRef controls.sigmaRef {graphId, graph, selectedNodeIds}
, mGraph graphRef controls.sigmaRef {graphId, graph,
graphStage: controls.graphStage,
selectedNodeIds}
, mSidebar graph mMetaData {frontends, session, selectedNodeIds, showSidePanel: fst controls.showSidePanel}
, mSidebar graph mMetaData {frontends, session, selectedNodeIds, showSidePanel: fst controls.showSidePanel}
]
]
, row [
, row [
...
@@ -110,6 +122,11 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
...
@@ -110,6 +122,11 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
tree {mCurrentRoute: route, treeId: root} _ showLogin =
tree {mCurrentRoute: route, treeId: root} _ showLogin =
RH.div {className: "col-md-2", style: {paddingTop: "60px"}}
RH.div {className: "col-md-2", style: {paddingTop: "60px"}}
[forest {sessions, route, frontends, showLogin}]
[forest {sessions, route, frontends, showLogin}]
graphClassName :: Record Controls.Controls -> String
graphClassName {showSidePanel: (GET.Opened /\ _), showTree: (true /\ _)} = "col-md-8"
graphClassName {showTree: (true /\ _)} = "col-md-10"
graphClassName {showSidePanel: (GET.Opened /\ _)} = "col-md-10"
graphClassName _ = "col-md-12"
outer = RH.div { className: "col-md-12" }
outer = RH.div { className: "col-md-12" }
inner = RH.div { className: "container-fluid", style: { paddingTop: "90px" } }
inner = RH.div { className: "container-fluid", style: { paddingTop: "90px" } }
...
@@ -123,10 +140,11 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
...
@@ -123,10 +140,11 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
-> R.Ref Sigma
-> R.Ref Sigma
-> { graphId :: GraphId
-> { graphId :: GraphId
, graph :: Maybe Graph.Graph
, graph :: Maybe Graph.Graph
, graphStage :: R.State Graph.Stage
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds}
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds}
-> R.Element
-> R.Element
mGraph _ _ {graph: Nothing} = RH.div {} []
mGraph _ _ {graph: Nothing} = RH.div {} []
mGraph graphRef sigmaRef
{graphId, graph: Just graph, selectedNodeIds} = graphView graphRef sigmaRef {graphId, graph, selectedNodeIds
}
mGraph graphRef sigmaRef
r@{graph: Just graph} = graphView graphRef sigmaRef $ r { graph = graph
}
mSidebar :: Maybe Graph.Graph
mSidebar :: Maybe Graph.Graph
-> Maybe GET.MetaData
-> Maybe GET.MetaData
...
@@ -146,27 +164,10 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
...
@@ -146,27 +164,10 @@ explorerCpt = R.hooksComponent "G.C.GraphExplorer.explorer" cpt
, showSidePanel
, showSidePanel
}
}
useExplorerState :: R.Hooks (Record GET.State)
useExplorerState = do pure {}
{- corpusId <- R.useState' 0
cursorSize <- R.useState' 0.0
filePath <- R.useState' ""
graphData <- R.useState' initialGraphData
legendData <- R.useState' []
multiNodeSelection <- R.useState' false
selectedNodes <- R.useState' Set.empty
showControls <- R.useState' false
showSidePanel <- R.useState' false
showTree <- R.useState' false
sigmaGraphData <- R.useState' (Nothing :: Maybe Graph.Graph)
sigmaSettings <- R.useState' Graph.sigmaSettings
treeId <- R.useState' (Nothing :: Maybe TreeId) -}
--treeId : Nothing
type GraphProps = (
type GraphProps = (
graphId :: GraphId
graphId :: GraphId
, graph :: Graph.Graph
, graph :: Graph.Graph
, graphStage :: R.State Graph.Stage
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
)
)
...
@@ -184,6 +185,7 @@ graphView elRef sigmaRef props = R.createElement el props []
...
@@ -184,6 +185,7 @@ graphView elRef sigmaRef props = R.createElement el props []
, selectedNodeIds
, selectedNodeIds
, sigmaSettings: Graph.sigmaSettings
, sigmaSettings: Graph.sigmaSettings
, sigmaRef: sigmaRef
, sigmaRef: sigmaRef
, stage: props.graphStage
}
}
convert :: GET.GraphData -> Tuple (Maybe GET.MetaData) Graph.Graph
convert :: GET.GraphData -> Tuple (Maybe GET.MetaData) Graph.Graph
...
...
src/Gargantext/Components/GraphExplorer/Controls.purs
View file @
14586cea
...
@@ -11,10 +11,10 @@ module Gargantext.Components.GraphExplorer.Controls
...
@@ -11,10 +11,10 @@ module Gargantext.Components.GraphExplorer.Controls
) where
) where
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import D
OM.Simple.Console (log, log2
)
import D
ata.Tuple (fst
)
import Data.Tuple.Nested ((/\), get1)
import Data.Tuple.Nested ((/\), get1)
import Effect (Effect)
import Effect (Effect)
import Effect.Timer (
clearTimeout,
setTimeout)
import Effect.Timer (setTimeout)
import Prelude
import Prelude
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as RH
import Reactix.DOM.HTML as RH
...
@@ -26,12 +26,12 @@ import Gargantext.Components.GraphExplorer.SlideButton (cursorSizeButton, labelS
...
@@ -26,12 +26,12 @@ import Gargantext.Components.GraphExplorer.SlideButton (cursorSizeButton, labelS
import Gargantext.Components.GraphExplorer.ToggleButton (edgesToggleButton, pauseForceAtlasButton)
import Gargantext.Components.GraphExplorer.ToggleButton (edgesToggleButton, pauseForceAtlasButton)
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
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
type Controls =
type Controls =
( cursorSize :: R.State Number
( cursorSize :: R.State Number
, graphStage :: R.State Graph.Stage
, multiNodeSelect :: R.Ref Boolean
, multiNodeSelect :: R.Ref Boolean
, showControls :: R.State Boolean
, showControls :: R.State Boolean
, showSidePanel :: R.State GET.SidePanelState
, showSidePanel :: R.State GET.SidePanelState
...
@@ -76,15 +76,19 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
...
@@ -76,15 +76,19 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
localControls <- initialLocalControls
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
-- TODO: mFAPauseRef needs to be set higher up the tree
mFAPauseRef <- R.useRef Nothing
mFAPauseRef <- R.useRef Nothing
-- when graph is changed, cleanup the mFAPauseRef
R.useEffect' $ do
case fst props.graphStage of
Graph.Init -> R.setRef mFAPauseRef Nothing
_ -> pure unit
--R.useEffect $ handleForceAtlasPause props.sigmaRef localControls.pauseForceAtlas mFAPauseRef
--R.useEffect $ handleForceAtlasPause props.sigmaRef localControls.pauseForceAtlas mFAPauseRef
R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef localControls.pauseForceAtlas (get1 localControls.showEdges) mFAPauseRef
R.useEffect' $ Sigmax.handleForceAtlas2Pause props.sigmaRef localControls.pauseForceAtlas (get1 localControls.showEdges) mFAPauseRef
R.useEffectOnce' $ do
R.useEffectOnce' $ do
timeoutId <- setTimeout 2000 $ do
timeoutId <- setTimeout 2000 $ do
--R.setRef mFAPauseRef Nothing
let (toggled /\ setToggled) = localControls.pauseForceAtlas
let (toggled /\ setToggled) = localControls.pauseForceAtlas
if toggled then
if toggled then
setToggled $ const false
setToggled $ const false
...
@@ -122,6 +126,7 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
...
@@ -122,6 +126,7 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
useGraphControls :: R.Hooks (Record Controls)
useGraphControls :: R.Hooks (Record Controls)
useGraphControls = do
useGraphControls = do
cursorSize <- R.useState' 10.0
cursorSize <- R.useState' 10.0
graphStage <- R.useState' Graph.Init
multiNodeSelect <- R.useRef false
multiNodeSelect <- R.useRef false
showControls <- R.useState' false
showControls <- R.useState' false
showSidePanel <- R.useState' GET.InitialClosed
showSidePanel <- R.useState' GET.InitialClosed
...
@@ -130,6 +135,7 @@ useGraphControls = do
...
@@ -130,6 +135,7 @@ useGraphControls = do
sigmaRef <- R.useRef sigma
sigmaRef <- R.useRef sigma
pure { cursorSize
pure { cursorSize
, graphStage
, multiNodeSelect
, multiNodeSelect
, showControls
, showControls
, showSidePanel
, showSidePanel
...
...
src/Gargantext/Ends.purs
View file @
14586cea
...
@@ -99,6 +99,8 @@ instance toUrlFrontendAppRoute :: ToUrl Frontend R.AppRoute where
...
@@ -99,6 +99,8 @@ instance toUrlFrontendAppRoute :: ToUrl Frontend R.AppRoute where
-- | The currently selected App and Static configurations
-- | The currently selected App and Static configurations
newtype Frontends = Frontends { app :: Frontend, static :: Frontend }
newtype Frontends = Frontends { app :: Frontend, static :: Frontend }
derive instance eqFrontends :: Eq Frontends
instance toUrlFrontendsRoutes :: ToUrl Frontends R.AppRoute where
instance toUrlFrontendsRoutes :: ToUrl Frontends R.AppRoute where
toUrl f r = appUrl f (R.appPath r)
toUrl f r = appUrl f (R.appPath r)
...
...
src/Gargantext/Hooks/Loader.purs
View file @
14586cea
module Gargantext.Hooks.Loader where
module Gargantext.Hooks.Loader where
import Gargantext.Prelude
import Gargantext.Prelude
import Data.Maybe (Maybe(..), isNothing, maybe, maybe')
import Data.Maybe (Maybe(..), is
Just, is
Nothing, maybe, maybe')
import Data.Tuple (fst)
import Data.Tuple (fst
, Tuple(..)
)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log, log2)
import Effect.Aff (Aff)
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import FFI.Simple (delay)
import Reactix as R
import Reactix as R
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Gargantext.Components.LoadingSpinner (loadingSpinner)
import Gargantext.Components.LoadingSpinner (loadingSpinner)
useAff :: forall st.
useLoader :: forall path st. Eq path =>
Aff st -> R.Hooks (Maybe st)
path -> (path -> Aff st)
useAff loader = do
(loaded /\ setLoaded) <- R.useState' Nothing
R.useEffect1 loader $ do
if isNothing loaded then
R2.affEffect "G.H.Loader.useAff" $
loader >>= (liftEffect <<< setLoaded <<< const <<< Just)
else pure R.nothing
pure loaded
useLoader :: forall path st.
path -> (path -> Aff st) -> (st -> R.Element) -> R.Hooks R.Element
useLoader path loader render
= maybe' (\_ -> loadingSpinner {}) render
<$> (useAff =<< R.useMemo2 path loader (\_ -> loader path))
useLoader2 :: forall path st.
R.State path -> (path -> Aff st)
-> (st -> R.Element) -> R.Hooks R.Element
-> (st -> R.Element) -> R.Hooks R.Element
useLoader
2
path loader render = do
useLoader path loader render = do
state <- R.useState' Nothing
state <- R.useState' Nothing
useLoaderEffect
2
path state loader
useLoaderEffect path state loader
pure $ maybe (loadingSpinner {}) render (fst state)
pure $ maybe (loadingSpinner {}) render (fst state)
useLoaderEffect :: forall state.
useLoaderEffect :: forall st path. Eq path =>
Aff state -> R.State (Maybe state) -> R.Hooks Unit
path -> R.State (Maybe st)
useLoaderEffect loader (state /\ setState) = do
R.useEffect2 state loader $ do
if isNothing state then
R2.affEffect "G.H.Loader.useLoader" $ loader >>= (liftEffect <<< setState <<< const <<< Just)
else pure R.nothing
useLoaderEffect' :: forall state.
Aff state -> R.Hooks (R.State (Maybe state))
useLoaderEffect' aff = do
state <- R.useState' Nothing
useLoaderEffect aff state
pure state
useLoaderEffect2 :: forall st path.
R.State path -> R.State (Maybe st)
-> (path -> Aff st) -> R.Hooks Unit
-> (path -> Aff st) -> R.Hooks Unit
useLoaderEffect2 path state loader = do
useLoaderEffect path state@(state' /\ setState) loader = do
aff <- useRepointer path loader
oPath <- R.useRef path
useLoaderEffect aff state
R.useEffect' $ do
useRepointer :: forall path st.
if (R.readRef oPath == path) && (isJust state') then
R.State path -> (path -> Aff st) -> R.Hooks (Aff st)
pure $ pure unit
useRepointer path@(path' /\ _) loader = R.useMemo2 loader path' (\_ -> loader path')
else do
R.setRef oPath path
R2.affEffect "G.H.Loader.useLoaderEffect2" $ do
l <- loader path
liftEffect $ setState $ const $ Just l
src/Gargantext/Hooks/Sigmax/Types.purs
View file @
14586cea
module Gargantext.Hooks.Sigmax.Types where
module Gargantext.Hooks.Sigmax.Types where
import Prelude (map, ($))
import Prelude (map, ($)
, (&&), (==)
)
import Data.Map as Map
import Data.Map as Map
import Data.Sequence (Seq)
import Data.Sequence (Seq)
import Data.Set as Set
import Data.Set as Set
...
@@ -35,3 +35,6 @@ nodesMap :: Graph Node Edge -> NodesMap
...
@@ -35,3 +35,6 @@ nodesMap :: Graph Node Edge -> NodesMap
nodesMap graph = do
nodesMap graph = do
let (Graph {nodes}) = graph
let (Graph {nodes}) = graph
Map.fromFoldable $ map (\n -> Tuple n.id n) nodes
Map.fromFoldable $ map (\n -> Tuple n.id n) nodes
eqGraph :: (Graph Node Edge) -> (Graph Node Edge) -> Boolean
eqGraph (Graph {nodes: n1, edges: e1}) (Graph {nodes: n2, edges: e2}) = (n1 == n2) && (e1 == e2)
src/Gargantext/Utils/Reactix.purs
View file @
14586cea
module Gargantext.Utils.Reactix where
module Gargantext.Utils.Reactix where
import Prelude
import Prelude
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe)
import Data.Tuple (Tuple)
import Data.Tuple.Nested ((/\))
import DOM.Simple as DOM
import DOM.Simple as DOM
import DOM.Simple.Console (log, log2)
import DOM.Simple.Console (log, log2)
import DOM.Simple.Document (document)
import DOM.Simple.Document (document)
import DOM.Simple.Event as DE
import DOM.Simple.Element as Element
import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import DOM.Simple.Types (class IsNode)
import DOM.Simple.Types (class IsNode)
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe)
import Data.Tuple (Tuple)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Class (liftEffect)
import Effect.Aff (Aff, launchAff, launchAff_, killFiber)
import Effect.Aff (Aff, launchAff, launchAff_, killFiber)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Effect.Exception (error)
import Effect.Uncurried (EffectFn1, runEffectFn1, mkEffectFn1, mkEffectFn2)
import Effect.Uncurried (EffectFn1, runEffectFn1, mkEffectFn1, mkEffectFn2)
import FFI.Simple ((...), defineProperty, delay, args2, args3)
import FFI.Simple ((...), defineProperty, delay, args2, args3)
...
@@ -191,3 +192,19 @@ appendChildToParentId ps c = delay unit $ \_ -> do
...
@@ -191,3 +192,19 @@ appendChildToParentId ps c = delay unit $ \_ -> do
effectLink :: Effect Unit -> String -> R.Element
effectLink :: Effect Unit -> String -> R.Element
effectLink eff msg = H.a {on: {click: const eff}} [H.text msg]
effectLink eff msg = H.a {on: {click: const eff}} [H.text msg]
useCache :: forall i o. Eq i => i -> (i -> R.Hooks o) -> R.Hooks o
useCache i f = do
iRef <- R.useRef Nothing
oRef <- R.useRef Nothing
let currI = R.readRef iRef
let currO = R.readRef oRef
if currI == Just i then
case currO of
Nothing -> f i -- this one shouldn't happen, but purescript
Just v -> pure v
else do
new <- f i
R.unsafeHooksEffect (R.setRef iRef $ Just i)
R.unsafeHooksEffect (R.setRef oRef $ Just new)
pure new
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment