Commit cee15b12 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[sigmajs] some work to bring new sigma.js

parent 68554c2b
Pipeline #3189 failed with stage
in 0 seconds
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
"echarts": "^5.1.2", "echarts": "^5.1.2",
"echarts-for-react": "^3.0.1", "echarts-for-react": "^3.0.1",
"esbuild": "^0.15.7", "esbuild": "^0.15.7",
"graphology": "^0.24.1",
"graphql": "^15.6.1", "graphql": "^15.6.1",
"graphql-ws": "^5.5.0", "graphql-ws": "^5.5.0",
"highlightjs": "^9.16.2", "highlightjs": "^9.16.2",
...@@ -55,7 +56,7 @@ ...@@ -55,7 +56,7 @@
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-tooltip": "^4.2.8", "react-tooltip": "^4.2.8",
"secp256k1": "^4.0.2", "secp256k1": "^4.0.2",
"sigma": "https://github.com/garganscript/sigma.js#main" "sigma": "^2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.15.0", "@babel/core": "^7.15.0",
......
...@@ -12,12 +12,14 @@ import DOM.Simple.Types (Element) ...@@ -12,12 +12,14 @@ import DOM.Simple.Types (Element)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable) import Data.Nullable (Nullable)
import Effect.Class.Console as ECC
import Gargantext.Components.App.Store as AppStore import Gargantext.Components.App.Store as AppStore
import Gargantext.Components.GraphExplorer.Store as GraphStore 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
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Graphology as Graphology
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 (getter) import Gargantext.Utils (getter)
...@@ -39,7 +41,6 @@ type Props sigma forceatlas2 = ...@@ -39,7 +41,6 @@ type Props sigma forceatlas2 =
drawGraph :: forall s fa2. R2.Leaf (Props s fa2) drawGraph :: forall s fa2. R2.Leaf (Props s fa2)
drawGraph = R2.leaf drawGraphCpt drawGraph = R2.leaf drawGraphCpt
drawGraphCpt :: forall s fa2. R.Memo (Props s fa2) drawGraphCpt :: forall s fa2. R.Memo (Props s fa2)
drawGraphCpt = R.memo' $ here.component "graph" cpt where drawGraphCpt = R.memo' $ here.component "graph" cpt where
-- | Component -- | Component
...@@ -90,7 +91,11 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where ...@@ -90,7 +91,11 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
case Sigmax.readSigma rSigma of case Sigmax.readSigma rSigma of
Nothing -> do Nothing -> do
theme <- T.read boxes.theme theme <- T.read boxes.theme
eSigma <- Sigma.sigma {settings: sigmaSettings theme} eSigma <- case R.readNullableRef elRef of
Nothing -> do
_ <- ECC.error "elRef is empty"
pure $ Left "elRef is empty"
Just el -> Sigma.sigma el {settings: sigmaSettings theme}
case eSigma of case eSigma of
Left err -> here.warn2 "[graphCpt] error creating sigma" err Left err -> here.warn2 "[graphCpt] error creating sigma" err
Right sig -> do Right sig -> do
...@@ -104,7 +109,8 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where ...@@ -104,7 +109,8 @@ drawGraphCpt = R.memo' $ here.component "graph" cpt where
} }
pure unit pure unit
Sigmax.refreshData sig $ Sigmax.sigmafy graph' newGraph <- Graphology.graphFromSigmaxGraph graph'
Sigmax.refreshData sig newGraph
Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do
-- bind the click event only initially, when ref was empty -- bind the click event only initially, when ref was empty
......
...@@ -18,6 +18,7 @@ import Effect (Effect) ...@@ -18,6 +18,7 @@ import Effect (Effect)
import Effect.Class.Console (error) import Effect.Class.Console (error)
import Effect.Timer (TimeoutId, clearTimeout) import Effect.Timer (TimeoutId, clearTimeout)
import FFI.Simple ((.=)) import FFI.Simple ((.=))
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as ST import Gargantext.Hooks.Sigmax.Types as ST
import Gargantext.Utils.Console as C import Gargantext.Utils.Console as C
...@@ -77,13 +78,17 @@ cleanupSigma sigma context = traverse_ kill (readSigma sigma) ...@@ -77,13 +78,17 @@ cleanupSigma sigma context = traverse_ kill (readSigma sigma)
errorMsg = prefix <> "Error killing sigma:" errorMsg = prefix <> "Error killing sigma:"
successMsg = prefix <> "Killed sigma" successMsg = prefix <> "Killed sigma"
refreshData :: forall n e. Sigma.Sigma -> Sigma.Graph n e -> Effect Unit refreshData :: Sigma.Sigma -> Graphology.Graph -> Effect Unit
refreshData sigma graph refreshData sigma graph = do
= console.log clearingMsg console.log clearingMsg
*> Sigma.clear sigmaGraph Graphology.clear sigmaGraph
*> console.log readingMsg console.log readingMsg
*> Sigma.graphRead sigmaGraph graph _ <- Graphology.updateWithGraph sigmaGraph graph
>>= either (console.log2 errorMsg) refresh
-- refresh
console.log refreshingMsg
Sigma.refresh sigma
--pure $ either (console.log2 errorMsg) refresh
where where
sigmaGraph = Sigma.graph sigma sigmaGraph = Sigma.graph sigma
refresh _ = console.log refreshingMsg *> Sigma.refresh sigma refresh _ = console.log refreshingMsg *> Sigma.refresh sigma
...@@ -92,12 +97,6 @@ refreshData sigma graph ...@@ -92,12 +97,6 @@ refreshData sigma graph
refreshingMsg = "[refreshData] Refreshing graph" refreshingMsg = "[refreshData] Refreshing graph"
errorMsg = "[refreshData] Error reading graph data:" errorMsg = "[refreshData] Error reading graph data:"
sigmafy :: forall n e. ST.Graph n e -> Sigma.Graph n e
sigmafy (ST.Graph g) = {nodes,edges}
where
nodes = A.fromFoldable g.nodes
edges = A.fromFoldable g.edges
dependOnSigma :: Sigma -> String -> (Sigma.Sigma -> Effect Unit) -> Effect Unit dependOnSigma :: Sigma -> String -> (Sigma.Sigma -> Effect Unit) -> Effect Unit
dependOnSigma sigma notFoundMsg f = do dependOnSigma sigma notFoundMsg f = do
case readSigma sigma of case readSigma sigma of
...@@ -146,7 +145,7 @@ setEdges sigma val = do ...@@ -146,7 +145,7 @@ setEdges sigma val = do
updateEdges :: Sigma.Sigma -> ST.EdgesMap -> Effect Unit updateEdges :: Sigma.Sigma -> ST.EdgesMap -> Effect Unit
updateEdges sigma edgesMap = do updateEdges sigma edgesMap = do
Sigma.forEachEdge (Sigma.graph sigma) \e -> do Graphology.forEachEdge (Sigma.graph sigma) \e -> do
let mTEdge = Map.lookup e.id edgesMap let mTEdge = Map.lookup e.id edgesMap
case mTEdge of case mTEdge of
Nothing -> error $ "Edge id " <> e.id <> " not found in edgesMap" Nothing -> error $ "Edge id " <> e.id <> " not found in edgesMap"
...@@ -159,7 +158,7 @@ updateEdges sigma edgesMap = do ...@@ -159,7 +158,7 @@ updateEdges sigma edgesMap = do
updateNodes :: Sigma.Sigma -> ST.NodesMap -> Effect Unit updateNodes :: Sigma.Sigma -> ST.NodesMap -> Effect Unit
updateNodes sigma nodesMap = do updateNodes sigma nodesMap = do
Sigma.forEachNode (Sigma.graph sigma) \n -> do Graphology.forEachNode (Sigma.graph sigma) \n -> do
let mTNode = Map.lookup n.id nodesMap let mTNode = Map.lookup n.id nodesMap
case mTNode of case mTNode of
Nothing -> error $ "Node id " <> n.id <> " not found in nodesMap" Nothing -> error $ "Node id " <> n.id <> " not found in nodesMap"
...@@ -217,22 +216,22 @@ performDiff sigma g = do ...@@ -217,22 +216,22 @@ performDiff sigma g = do
if (Seq.null addEdges) && (Seq.null addNodes) && (Set.isEmpty removeEdges) && (Set.isEmpty removeNodes) then if (Seq.null addEdges) && (Seq.null addNodes) && (Set.isEmpty removeEdges) && (Set.isEmpty removeNodes) then
pure unit pure unit
else do else do
traverse_ (Sigma.addNode sigmaGraph) addNodes traverse_ (Graphology.addNode sigmaGraph) addNodes
traverse_ (Sigma.addEdge sigmaGraph) addEdges traverse_ (Graphology.addEdge sigmaGraph) addEdges
traverse_ (Sigma.removeEdge sigmaGraph) removeEdges traverse_ (Graphology.removeEdge sigmaGraph) removeEdges
traverse_ (Sigma.removeNode sigmaGraph) removeNodes traverse_ (Graphology.removeNode sigmaGraph) removeNodes
Sigma.refresh sigma Sigma.refresh sigma
Sigma.killForceAtlas2 sigma Sigma.killForceAtlas2 sigma
where where
sigmaGraph = Sigma.graph sigma sigmaGraph = Sigma.graph sigma
sigmaEdgeIds = Sigma.sigmaEdgeIds sigmaGraph sigmaEdgeIds = Graphology.edgeIds sigmaGraph
sigmaNodeIds = Sigma.sigmaNodeIds sigmaGraph sigmaNodeIds = Graphology.nodeIds sigmaGraph
{add: Tuple addEdges addNodes, remove: Tuple removeEdges removeNodes} = ST.sigmaDiff sigmaEdgeIds sigmaNodeIds g {add: Tuple addEdges addNodes, remove: Tuple removeEdges removeNodes} = ST.sigmaDiff sigmaEdgeIds sigmaNodeIds g
-- DEPRECATED -- DEPRECATED
markSelectedEdges :: Sigma.Sigma -> ST.EdgeIds -> ST.EdgesMap -> Effect Unit markSelectedEdges :: Sigma.Sigma -> ST.EdgeIds -> ST.EdgesMap -> Effect Unit
markSelectedEdges sigma selectedEdgeIds graphEdges = do markSelectedEdges sigma selectedEdgeIds graphEdges = do
Sigma.forEachEdge (Sigma.graph sigma) \e -> do Graphology.forEachEdge (Sigma.graph sigma) \e -> do
case Map.lookup e.id graphEdges of case Map.lookup e.id graphEdges of
Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map" Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map"
Just {color} -> do Just {color} -> do
...@@ -247,7 +246,7 @@ markSelectedEdges sigma selectedEdgeIds graphEdges = do ...@@ -247,7 +246,7 @@ markSelectedEdges sigma selectedEdgeIds graphEdges = do
markSelectedNodes :: Sigma.Sigma -> ST.NodeIds -> ST.NodesMap -> Effect Unit markSelectedNodes :: Sigma.Sigma -> ST.NodeIds -> ST.NodesMap -> Effect Unit
markSelectedNodes sigma selectedNodeIds graphNodes = do markSelectedNodes sigma selectedNodeIds graphNodes = do
Sigma.forEachNode (Sigma.graph sigma) \n -> do Graphology.forEachNode (Sigma.graph sigma) \n -> do
case Map.lookup n.id graphNodes of case Map.lookup n.id graphNodes of
Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map" Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map"
Just {color} -> do Just {color} -> do
......
'use strict';
import Graph from 'graphology';
export function _newGraph() {
return new Graph();
}
export function _addNode(g, name, n) {
return g.addNode(name, n);
}
export function _addEdge(g, source, target, e) {
return g.addEdge(source, target, e);
}
// Almost the same as graphology.mapNodes but with a change that only
// 1 argument is passed: the whole node structure
export function _mapNodes(g, fn) {
return g.mapNodes(function(name, attrs) {
return fn({id: name, ...attrs});
});
}
// Almost the same as graphology.mapNodes but with a change that only
// 1 argument is passed: the whole node structure
// TODO Add source, target
export function _mapEdges(g, fn) {
return g.mapEdges(function(name, attrs) {
return fn({id: name, ...attrs});
});
}
module Gargantext.Hooks.Sigmax.Graphology where
-- FFI for graphology: https://graphology.github.io/
-- serialized graph: https://graphology.github.io/serialization#format
-- to use with: Graph.from(data)
import Prelude
import Data.Array as A
import Data.Sequence as Seq
import Data.Set as Set
import Data.Traversable (traverse)
import Effect (Effect)
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, EffectFn4, runEffectFn1, runEffectFn2, runEffectFn3, runEffectFn4)
import FFI.Simple ((..), (...), (.=))
import Gargantext.Hooks.Sigmax.Types as Types
import Record as Record
-- | Type representing `graphology.graph`
foreign import data Graph :: Type
foreign import _newGraph :: EffectFn1 Unit Graph
foreign import _addNode :: EffectFn3 Graph String (Record Types.Node) String
foreign import _addEdge :: EffectFn4 Graph String String (Record Types.Edge) String
foreign import _mapNodes :: forall a. EffectFn2 Graph (Record Types.Node -> a) (Array a)
foreign import _mapEdges :: forall a. EffectFn2 Graph (Record Types.Edge -> a) (Array a)
newGraph :: Unit -> Effect Graph
newGraph = runEffectFn1 _newGraph
graphFromSigmaxGraph :: Types.Graph Types.Node Types.Edge -> Effect Graph
graphFromSigmaxGraph (Types.Graph g) = do
graph <- newGraph unit
_ <- traverse (addNode graph) nodes
_ <- traverse (addEdge graph) edges
pure graph
where
nodes = A.fromFoldable g.nodes
edges = A.fromFoldable g.edges
addNode :: Graph -> Record Types.Node -> Effect String
addNode g node@{ id } = runEffectFn3 _addNode g id node
removeNode :: Graph -> String -> Effect Unit
removeNode g nId = pure $ g ... "dropNode" $ [nId]
forEachNode :: Graph -> (Record Types.Node -> Effect Unit) -> Effect Unit
-- TODO Check this: how does FFI translate function of two arguments
-- into PS \x y ?
forEachNode g fn = pure $ g ... "forEachNode" $ [\_ n -> fn n]
mapNodes :: Graph -> (Record Types.Node -> Record Types.Node) -> Effect (Array (Record Types.Node))
mapNodes = runEffectFn2 _mapNodes
addEdge :: Graph -> Record Types.Edge -> Effect String
addEdge g edge@{ source, target } = runEffectFn4 _addEdge g source target edge
removeEdge :: Graph -> String -> Effect Unit
removeEdge g eId = pure $ g ... "dropEdge" $ [eId]
forEachEdge :: Graph -> (Record Types.Edge -> Effect Unit) -> Effect Unit
forEachEdge g fn = pure $ g ... "forEachEdge" $ [\_ e -> fn e]
mapEdges :: Graph -> (Record Types.Edge -> Record Types.Edge) -> Effect (Array (Record Types.Edge))
mapEdges = runEffectFn2 _mapEdges
-- TODO Maybe our use of this function (`updateWithGraph`) in code is
-- too much. We convert Types.Graph into Graphology.Graph and then
-- update Sigma.graph with this.
-- | Since we don't want to replace directly the sigma.graph, we call
-- update. This "intelligently" scans the `target` graph and updates
-- so that in the end it is the same as `source`.
updateWithGraph :: Graph -> Graph -> Effect Graph
-- TODO Add updateEdgesFromGraph
updateWithGraph target source = updateNodesFromGraph target source
-- | Update `target` graph so that it's `.nodes` is the same as that
-- | of `source` (with attributes as well)
updateNodesFromGraph :: Graph -> Graph -> Effect Graph
-- TODO Fixme
updateNodesFromGraph source _target = pure source
-- updateNodesFromGraph target source =
-- forEachNode target $ node@{ id } -> do
-- if Set.member id sourceNodeIds then
-- -- update node
-- updateNodes (removeNodes (addNodes target missingNodes) newNodes) nodesToUpdate
-- where
-- sourceNodeIds = nodeIds source
-- sourceEdgeIds = edgeIds source
-- targetNodeIds = nodeIds target
-- targetEdgeIds = edgeIds target
-- newNodeIds = Set.difference sourceNodeIds targetNodeIds
-- missingNodeIds = Set.difference targetNodeIds sourceNodeIds
-- | Clear a graphology graph.
clear :: Graph -> Effect Unit
clear g = pure $ g ... "clear" $ []
edges_ :: Graph -> Array Types.EdgeId
edges_ g = g ... "edges" $ [] :: Array Types.EdgeId
nodes_ :: Graph -> Array Types.NodeId
nodes_ g = g ... "nodes" $ [] :: Array Types.NodeId
-- | Call `sigmaGraph.edges()` on a sigmajs graph instance.
edges :: Graph -> Effect (Seq.Seq (Record Types.Edge))
edges g = do
edges' <- mapEdges g identity
pure $ Seq.fromFoldable edges'
-- | Call `sigmaGraph.nodes()` on a sigmajs graph instance.
nodes :: Graph -> Effect (Seq.Seq (Record Types.Node))
nodes g = do
nodes' <- mapNodes g identity
pure $ Seq.fromFoldable nodes'
-- | Fetch ids of graph edges in a sigmajs instance.
edgeIds :: Graph -> Types.EdgeIds
edgeIds = Set.fromFoldable <<< edges_
-- | Fetch ids of graph nodes in a sigmajs instance.
nodeIds :: Graph -> Types.NodeIds
nodeIds = Set.fromFoldable <<< nodes_
-- | Read graph into a graphology instance.
-- graphRead :: forall nodeExtra node edgeExtra edge.
-- NodeProps nodeExtra node => EdgeProps edgeExtra edge =>
-- SigmaGraph -> Graph node edge -> Effect (Either EEx.Error Unit)
-- graphRead sg g = EEx.try $ pure $ sg ... "read" $ [ g ]
--type Graph n e = { nodes :: Array {|n}, edges :: Array {|e} }
'use strict'; 'use strict';
//import { sigma } from 'sigma/src/garg.js'; import Graph from 'graphology';
import sigma from 'sigma'; import Sigma from 'sigma';
console.log('imported sigma', sigma); let sigma = Sigma.Sigma;
console.log('imported sigma', Sigma);
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.sigma = sigma; window.sigma = Sigma;
} }
/*import('sigma/plugins/garg.js').then((module) => { /*import('sigma/plugins/garg.js').then((module) => {
...@@ -183,9 +184,12 @@ let sigmaMouseSelector = function(sigma, options) { ...@@ -183,9 +184,12 @@ let sigmaMouseSelector = function(sigma, options) {
sigmaMouseSelector(sigma); sigmaMouseSelector(sigma);
*/ */
function _sigma(left, right, opts) { function _sigma(left, right, el, opts) {
try { try {
return right(new sigma(opts)); let graph = new Graph();
console.log('initializing sigma with el', el);
console.log('initializing sigma with opts', opts);
return right(new sigma(graph, el, opts));
} catch(e) { } catch(e) {
return left(e); return left(e);
} }
...@@ -206,7 +210,7 @@ function _bindMouseSelectorPlugin(left, right, sig) { ...@@ -206,7 +210,7 @@ function _bindMouseSelectorPlugin(left, right, sig) {
return left(e); return left(e);
} }
} }
function _bind(sigma, event, handler) { sigma.bind(event, handler); } function _on(sigma, event, handler) { sigma.on(event, handler); }
function _takeScreenshot(sigma) { function _takeScreenshot(sigma) {
let c = sigma.renderers[0].container; let c = sigma.renderers[0].container;
...@@ -237,11 +241,20 @@ function _proxySetSettings(window, sigma, settings) { ...@@ -237,11 +241,20 @@ function _proxySetSettings(window, sigma, settings) {
window.sigma.instances(id).refresh(); window.sigma.instances(id).refresh();
} }
let dummy = function() {};
let _setSettings = function(g, settings) {
for(const key in settings) {
g.setSetting(key, settings[key]);
}
}
export { _sigma, export { _sigma,
_addRenderer, _addRenderer,
_bindMouseSelectorPlugin, dummy as _bindMouseSelectorPlugin,
_bind, _on,
_takeScreenshot, _takeScreenshot,
_getEdges, _getEdges,
_getNodes, _getNodes,
_proxySetSettings }; _proxySetSettings,
_setSettings };
...@@ -6,22 +6,19 @@ import DOM.Simple.Types (Element, Window) ...@@ -6,22 +6,19 @@ import DOM.Simple.Types (Element, Window)
import Data.Array as A import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Data.Sequence as Seq
import Data.Set as Set
import Data.Traversable (traverse_) import Data.Traversable (traverse_)
import Effect (Effect) import Effect (Effect)
import Effect.Exception as EEx import Effect.Exception as EEx
import Effect.Timer (setTimeout) import Effect.Timer (setTimeout)
import Effect.Uncurried (EffectFn1, EffectFn3, EffectFn4, mkEffectFn1, runEffectFn1, runEffectFn3, runEffectFn4) import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, EffectFn4, mkEffectFn1, runEffectFn1, runEffectFn2, runEffectFn3, runEffectFn4)
import FFI.Simple ((..), (...), (.=)) import FFI.Simple ((..), (...), (.=))
import Foreign.Object as Object import Foreign.Object as Object
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.Types as Types import Gargantext.Hooks.Sigmax.Types as Types
import Type.Row (class Union) import Type.Row (class Union)
-- | Type representing a sigmajs instance -- | Type representing a sigmajs instance
foreign import data Sigma :: Type foreign import data Sigma :: Type
-- | Type representing `sigma.graph`
foreign import data SigmaGraph :: Type
type NodeRequiredProps = ( id :: Types.NodeId ) type NodeRequiredProps = ( id :: Types.NodeId )
type EdgeRequiredProps = ( id :: Types.EdgeId, source :: Types.NodeId, target :: Types.NodeId ) type EdgeRequiredProps = ( id :: Types.EdgeId, source :: Types.NodeId, target :: Types.NodeId )
...@@ -37,12 +34,11 @@ instance edgeProps ...@@ -37,12 +34,11 @@ instance edgeProps
:: Union EdgeRequiredProps extra all :: Union EdgeRequiredProps extra all
=> EdgeProps all extra => EdgeProps all extra
type Graph n e = { nodes :: Array {|n}, edges :: Array {|e} }
type SigmaOpts s = { settings :: s } type SigmaOpts s = { settings :: s }
-- | Initialize sigmajs. -- | Initialize sigmajs.
sigma :: forall opts err. SigmaOpts opts -> Effect (Either err Sigma) sigma :: forall opts err. Element -> SigmaOpts opts -> Effect (Either err Sigma)
sigma = runEffectFn3 _sigma Left Right sigma = runEffectFn4 _sigma Left Right
-- | Kill a sigmajs instance. -- | Kill a sigmajs instance.
kill :: Sigma -> Effect Unit kill :: Sigma -> Effect Unit
...@@ -102,29 +98,21 @@ killSigma :: Sigma -> Effect (Either EEx.Error Unit) ...@@ -102,29 +98,21 @@ killSigma :: Sigma -> Effect (Either EEx.Error Unit)
killSigma s = EEx.try $ pure $ s ... "kill" $ [] killSigma s = EEx.try $ pure $ s ... "kill" $ []
-- | Get the `.graph` object from a sigmajs instance. -- | Get the `.graph` object from a sigmajs instance.
graph :: Sigma -> SigmaGraph graph :: Sigma -> Graphology.Graph
graph s = s .. "graph" :: SigmaGraph graph s = s ... "getGraph" $ [] :: Graphology.Graph
-- | Read graph into a sigmajs instance.
graphRead :: forall nodeExtra node edgeExtra edge. NodeProps nodeExtra node => EdgeProps edgeExtra edge => SigmaGraph -> Graph node edge -> Effect (Either EEx.Error Unit)
graphRead sg g = EEx.try $ pure $ sg ... "read" $ [ g ]
-- | Clear a sigmajs graph.
clear :: SigmaGraph -> Effect Unit
clear sg = pure $ sg ... "clear" $ []
-- | Call `sigma.bind(event, handler)` on a sigmajs instance. -- | Call `sigma.bind(event, handler)` on a sigmajs instance.
bind_ :: forall e. Sigma -> String -> (e -> Effect Unit) -> Effect Unit on_ :: forall e. Sigma -> String -> (e -> Effect Unit) -> Effect Unit
bind_ s e h = runEffectFn3 _bind s e (mkEffectFn1 h) on_ s e h = runEffectFn3 _on s e (mkEffectFn1 h)
-- | Generic function to bind a sigmajs event for edges. -- | Generic function to bind a sigmajs event for edges.
bindEdgeEvent :: Sigma -> String -> (Record Types.Edge -> Effect Unit) -> Effect Unit bindEdgeEvent :: Sigma -> String -> (Record Types.Edge -> Effect Unit) -> Effect Unit
bindEdgeEvent s ev f = bind_ s ev $ \e -> do bindEdgeEvent s ev f = on_ s ev $ \e -> do
let edge = e .. "data" .. "edge" :: Record Types.Edge let edge = e .. "data" .. "edge" :: Record Types.Edge
f edge f edge
-- | Generic function to bind a sigmajs event for nodes. -- | Generic function to bind a sigmajs event for nodes.
bindNodeEvent :: Sigma -> String -> (Record Types.Node -> Effect Unit) -> Effect Unit bindNodeEvent :: Sigma -> String -> (Record Types.Node -> Effect Unit) -> Effect Unit
bindNodeEvent s ev f = bind_ s ev $ \e -> do bindNodeEvent s ev f = on_ s ev $ \e -> do
let node = e .. "data" .. "node" :: Record Types.Node let node = e .. "data" .. "node" :: Record Types.Node
f node f node
...@@ -132,52 +120,6 @@ bindNodeEvent s ev f = bind_ s ev $ \e -> do ...@@ -132,52 +120,6 @@ bindNodeEvent s ev f = bind_ s ev $ \e -> do
unbind_ :: Sigma -> String -> Effect Unit unbind_ :: Sigma -> String -> Effect Unit
unbind_ s e = pure $ s ... "unbind" $ [e] unbind_ s e = pure $ s ... "unbind" $ [e]
edges_ :: SigmaGraph -> Array (Record Types.Edge)
edges_ sg = sg ... "edges" $ [] :: Array (Record Types.Edge)
nodes_ :: SigmaGraph -> Array (Record Types.Node)
nodes_ sg = sg ... "nodes" $ [] :: Array (Record Types.Node)
-- | Call `sigmaGraph.edges()` on a sigmajs graph instance.
edges :: SigmaGraph -> Seq.Seq (Record Types.Edge)
edges = Seq.fromFoldable <<< edges_
-- | Call `sigmaGraph.nodes()` on a sigmajs graph instance.
nodes :: SigmaGraph -> Seq.Seq (Record Types.Node)
nodes = Seq.fromFoldable <<< nodes_
-- | Fetch ids of graph edges in a sigmajs instance.
sigmaEdgeIds :: SigmaGraph -> Types.EdgeIds
sigmaEdgeIds sg = Set.fromFoldable edgeIds
where
edgeIds = _.id <$> edges sg
-- | Fetch ids of graph nodes in a sigmajs instance.
sigmaNodeIds :: SigmaGraph -> Types.NodeIds
sigmaNodeIds sg = Set.fromFoldable nodeIds
where
nodeIds = _.id <$> nodes sg
-- | Call `addEdge` on a sigmajs graph.
addEdge :: SigmaGraph -> Record Types.Edge -> Effect Unit
addEdge sg e = pure $ sg ... "addEdge" $ [e]
-- | Call `removeEdge` on a sigmajs graph.
removeEdge :: SigmaGraph -> String -> Effect Unit
removeEdge sg eId = pure $ sg ... "dropEdge" $ [eId]
--removeEdge = runEffectFn2 _removeEdge
-- | Call `addNode` on a sigmajs graph.
addNode :: SigmaGraph -> Record Types.Node -> Effect Unit
addNode sg n = pure $ sg ... "addNode" $ [n]
-- | Call `removeNode` on a sigmajs graph.
removeNode :: SigmaGraph -> String -> Effect Unit
removeNode sg nId = pure $ sg ... "dropNode" $ [nId]
-- | Iterate over all edges in a sigmajs graph.
forEachEdge :: SigmaGraph -> (Record Types.Edge -> Effect Unit) -> Effect Unit
forEachEdge sg f = traverse_ f (edges sg)
-- | Iterate over all nodes in a sigmajs graph.
forEachNode :: SigmaGraph -> (Record Types.Node -> Effect Unit) -> Effect Unit
forEachNode sg f = traverse_ f (nodes sg)
-- | Bind a `clickNode` event. -- | Bind a `clickNode` event.
bindClickNode :: Sigma -> (Record Types.Node -> Effect Unit) -> Effect Unit bindClickNode :: Sigma -> (Record Types.Node -> Effect Unit) -> Effect Unit
bindClickNode s f = bindNodeEvent s "clickNode" f bindClickNode s f = bindNodeEvent s "clickNode" f
...@@ -187,7 +129,7 @@ unbindClickNode s = unbind_ s "clickNode" ...@@ -187,7 +129,7 @@ unbindClickNode s = unbind_ s "clickNode"
-- | Bind a `clickNodes` event. -- | Bind a `clickNodes` event.
bindClickNodes :: Sigma -> (Array (Record Types.Node) -> Effect Unit) -> Effect Unit bindClickNodes :: Sigma -> (Array (Record Types.Node) -> Effect Unit) -> Effect Unit
bindClickNodes s f = bind_ s "clickNodes" $ \e -> do bindClickNodes s f = on_ s "clickNodes" $ \e -> do
let ns = e .. "data" .. "node" :: Array (Record Types.Node) let ns = e .. "data" .. "node" :: Array (Record Types.Node)
f ns f ns
-- | Unbind a `clickNodes` event. -- | Unbind a `clickNodes` event.
...@@ -211,34 +153,39 @@ bindOverEdge s f = bindEdgeEvent s "overEdge" f ...@@ -211,34 +153,39 @@ bindOverEdge s f = bindEdgeEvent s "overEdge" f
-- | Call `settings(s)` on a sigmajs instance. -- | Call `settings(s)` on a sigmajs instance.
setSettings :: forall settings. Sigma -> settings -> Effect Unit setSettings :: forall settings. Sigma -> settings -> Effect Unit
setSettings s settings = do setSettings = runEffectFn2 _setSettings
_ <- pure $ s ... "settings" $ [ settings ]
refresh s
-- | Call `settins(s)` on the the main proxy `window.sigma` -- | Call `settins(s)` on the the main proxy `window.sigma`
proxySetSettings :: forall settings. proxySetSettings :: forall settings.
Window -> Sigma -> settings -> Effect Unit Window -> Sigma -> settings -> Effect Unit
proxySetSettings = runEffectFn3 _proxySetSettings proxySetSettings = runEffectFn3 _proxySetSettings
-- TODO
-- | Start forceAtlas2 on a sigmajs instance. -- | Start forceAtlas2 on a sigmajs instance.
startForceAtlas2 :: forall settings. Sigma -> settings -> Effect Unit startForceAtlas2 :: forall settings. Sigma -> settings -> Effect Unit
startForceAtlas2 s settings = pure $ s ... "startForceAtlas2" $ [ settings ] startForceAtlas2 _ _ = pure unit
--startForceAtlas2 s settings = pure $ s ... "startForceAtlas2" $ [ settings ]
-- | Restart forceAtlas2 on a sigmajs instance. -- | Restart forceAtlas2 on a sigmajs instance.
restartForceAtlas2 :: forall settings. Sigma -> settings -> Effect Unit restartForceAtlas2 :: forall settings. Sigma -> settings -> Effect Unit
restartForceAtlas2 s settings = startForceAtlas2 s settings restartForceAtlas2 s settings = startForceAtlas2 s settings
-- TODO
-- | Stop forceAtlas2 on a sigmajs instance. -- | Stop forceAtlas2 on a sigmajs instance.
stopForceAtlas2 :: Sigma -> Effect Unit stopForceAtlas2 :: Sigma -> Effect Unit
stopForceAtlas2 s = pure $ s ... "stopForceAtlas2" $ [] stopForceAtlas2 _ = pure unit
--stopForceAtlas2 s = pure $ s ... "stopForceAtlas2" $ []
-- TODO
-- | Kill forceAtlas2 on a sigmajs instance. -- | Kill forceAtlas2 on a sigmajs instance.
killForceAtlas2 :: Sigma -> Effect Unit killForceAtlas2 :: Sigma -> Effect Unit
killForceAtlas2 s = pure $ s ... "killForceAtlas2" $ [] killForceAtlas2 _ = pure unit
--killForceAtlas2 s = pure $ s ... "killForceAtlas2" $ []
-- | Return whether forceAtlas2 is running on a sigmajs instance. -- | Return whether forceAtlas2 is running on a sigmajs instance.
isForceAtlas2Running :: Sigma -> Boolean isForceAtlas2Running :: Sigma -> Boolean
isForceAtlas2Running s = s ... "isForceAtlas2Running" $ [] :: Boolean isForceAtlas2Running _ = false
--isForceAtlas2Running s = s ... "isForceAtlas2Running" $ [] :: Boolean
-- | Refresh forceAtlas2 (with a `setTimeout` hack as it seems it doesn't work -- | Refresh forceAtlas2 (with a `setTimeout` hack as it seems it doesn't work
-- | otherwise). -- | otherwise).
...@@ -327,8 +274,9 @@ getNodes = runEffectFn1 _getNodes ...@@ -327,8 +274,9 @@ getNodes = runEffectFn1 _getNodes
-- | FFI -- | FFI
foreign import _sigma :: foreign import _sigma ::
forall a b opts err. forall a b opts err.
EffectFn3 (a -> Either a b) EffectFn4 (a -> Either a b)
(b -> Either a b) (b -> Either a b)
Element
(SigmaOpts opts) (SigmaOpts opts)
(Either err Sigma) (Either err Sigma)
foreign import _addRenderer foreign import _addRenderer
...@@ -344,7 +292,7 @@ foreign import _bindMouseSelectorPlugin ...@@ -344,7 +292,7 @@ foreign import _bindMouseSelectorPlugin
(b -> Either a b) (b -> Either a b)
Sigma Sigma
(Either err Unit) (Either err Unit)
foreign import _bind :: forall e. EffectFn3 Sigma String (EffectFn1 e Unit) Unit foreign import _on :: forall e. EffectFn3 Sigma String (EffectFn1 e Unit) Unit
foreign import _takeScreenshot :: EffectFn1 Sigma String foreign import _takeScreenshot :: EffectFn1 Sigma String
foreign import _getEdges :: EffectFn1 Sigma (Array (Record Types.Edge)) foreign import _getEdges :: EffectFn1 Sigma (Array (Record Types.Edge))
foreign import _getNodes :: EffectFn1 Sigma (Array (Record Types.Node)) foreign import _getNodes :: EffectFn1 Sigma (Array (Record Types.Node))
...@@ -354,3 +302,4 @@ foreign import _proxySetSettings ...@@ -354,3 +302,4 @@ foreign import _proxySetSettings
Sigma Sigma
settings settings
Unit Unit
foreign import _setSettings :: forall settings. EffectFn2 Sigma settings Unit
'use strict'; 'use strict';
import ReactBootstrap from 'react-bootstrap';
if (typeof window !== 'undefined') {
window.ReactBootstrap = ReactBootstrap;
}
import Alert from 'react-bootstrap/Alert'; import Alert from 'react-bootstrap/Alert';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Popover from 'react-bootstrap/Popover'; import Popover from 'react-bootstrap/Popover';
......
...@@ -5393,6 +5393,14 @@ graphology-utils@^2.5.0: ...@@ -5393,6 +5393,14 @@ graphology-utils@^2.5.0:
resolved "https://registry.yarnpkg.com/graphology-utils/-/graphology-utils-2.5.2.tgz#4d30d6e567d27c01f105e1494af816742e8d2440" resolved "https://registry.yarnpkg.com/graphology-utils/-/graphology-utils-2.5.2.tgz#4d30d6e567d27c01f105e1494af816742e8d2440"
integrity sha512-ckHg8MXrXJkOARk56ZaSCM1g1Wihe2d6iTmz1enGOz4W/l831MBCKSayeFQfowgF8wd+PQ4rlch/56Vs/VZLDQ== integrity sha512-ckHg8MXrXJkOARk56ZaSCM1g1Wihe2d6iTmz1enGOz4W/l831MBCKSayeFQfowgF8wd+PQ4rlch/56Vs/VZLDQ==
graphology@^0.24.1:
version "0.24.1"
resolved "https://registry.yarnpkg.com/graphology/-/graphology-0.24.1.tgz#035e452e294b01168cf5c85d5dd0a4b7e4837d87"
integrity sha512-6lNz1PNTAe9Q6ioHKrXu0Lp047sgvOoHa4qmP/8mnJWCGv2iIZPQkuHPUb2/OWDWCqHpw2hKgJLJ55X/66xmHg==
dependencies:
events "^3.3.0"
obliterator "^2.0.2"
graphql-ws@^5.5.0: graphql-ws@^5.5.0:
version "5.5.0" version "5.5.0"
resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.5.0.tgz#79f10248d23d104369eaef93acb9f887276a2c42" resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.5.0.tgz#79f10248d23d104369eaef93acb9f887276a2c42"
...@@ -7541,6 +7549,11 @@ object.pick@^1.3.0: ...@@ -7541,6 +7549,11 @@ object.pick@^1.3.0:
dependencies: dependencies:
isobject "^3.0.1" isobject "^3.0.1"
obliterator@^2.0.2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816"
integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==
on-finished@~2.3.0: on-finished@~2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
...@@ -9444,9 +9457,14 @@ side-channel@^1.0.4: ...@@ -9444,9 +9457,14 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2" get-intrinsic "^1.0.2"
object-inspect "^1.9.0" object-inspect "^1.9.0"
"sigma@link:../../../git-work/github/sigma.js-new": sigma@^2.3.1:
version "0.0.0" version "2.3.1"
uid "" resolved "https://registry.yarnpkg.com/sigma/-/sigma-2.3.1.tgz#69fd9165479fa49ed84348afcd0432215fdf935f"
integrity sha512-YfQsVZf78CeIUv8EYLqp/yvhMwwBXGrbpy+rD1N2X9IqtJ11+VfQRjWfVqHDhjM8oPfWPsaJMtpWFQ8pIflvCA==
dependencies:
"@yomguithereal/helpers" "^1.1.1"
events "^3.3.0"
graphology-utils "^2.5.0"
signal-exit@^3.0.0, signal-exit@^3.0.2: signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3" version "3.0.3"
......
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