Commit 10932f5b authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge branch 'dev-warnings-cleanup' into dev

parents bfc60431 9e296c86
......@@ -15,9 +15,9 @@
}
#graph-explorer .graph-tree {
position: absolute;
top: 120px;
max-height: 600px;
overflow-y: scroll;
top: 150px;
z-index: 1;
}
#graph-explorer #graph-view {
......@@ -25,13 +25,13 @@
}
#graph-explorer #sp-container {
position: absolute;
left: 70%;
max-height: 600px;
overflow-y: scroll;
top: 150px;
z-index: 1;
left: 70%;
border: 1px white solid;
background-color: white;
max-height: 600px;
overflow-y: scroll;
}
#graph-explorer #sp-container #myTab {
marginBottom: 18px;
......@@ -50,4 +50,13 @@
z-index: 1;
}
.input-with-autocomplete .completions {
position: absolute;
max-height: 300px;
overflow-y: scroll;
width: 300px;
top: 50px;
z-index: 5;
}
/*# sourceMappingURL=Graph.css.map */
@mixin sidePanelCommon
position: absolute
max-height: 600px
overflow-y: scroll
top: 150px
z-index: 1
#graph-explorer
#toolbar
display: flex
......@@ -14,24 +21,16 @@
height: 79px
.graph-tree
position: absolute
top: 120px
max-height: 600px
overflow-y: scroll
z-index: 1
@include sidePanelCommon
#graph-view
height: 95%
#sp-container
position: absolute
@include sidePanelCommon
left: 70%
top: 150px
z-index: 1
border: 1px white solid
background-color: white
max-height: 600px
overflow-y: scroll
#myTab
marginBottom: 18px
......@@ -49,3 +48,12 @@
#tree
position: absolute
z-index: 1
.input-with-autocomplete
.completions
position: absolute
max-height: 300px
overflow-y: scroll
width: 300px
top: 50px
z-index: 5
......@@ -204,7 +204,7 @@ li:hover a#rename-leaf {
justify-content: center;
}
.flex-center {
.flex-space-between, .flex-center {
display: flex;
justify-content: space-between;
}
......
......@@ -188,8 +188,7 @@ li
flew-wrap: wrap
justify-content: center
.flex-space-between
.flex-center
.flex-space-between,.flex-center
display: flex
justify-content: space-between
......
......@@ -16,9 +16,9 @@ import Data.Maybe (Maybe(..), maybe)
import Data.Set (Set)
import Data.Set as Set
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..), fst, snd)
import Data.Tuple (Tuple(..), fst)
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log, log3)
import DOM.Simple.Console (log3)
import DOM.Simple.Event as DE
import Effect (Effect)
import Effect.Aff (Aff, launchAff)
......@@ -28,11 +28,10 @@ import Reactix.DOM.HTML as H
------------------------------------------------------------------------
import Gargantext.Components.Table as T
import Gargantext.Components.Loader (loader)
import Gargantext.Components.Table as T
import Gargantext.Ends (Frontends, url)
import Gargantext.Utils.Reactix as R2
import Gargantext.Routes as Routes
import Gargantext.Routes (AppRoute, SessionRoute(NodeAPI))
import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Sessions (Session, sessionId, post, delete, put)
import Gargantext.Types (NodeType(..), OrderBy(..), TabType, TabPostQuery(..), AffTableResult)
------------------------------------------------------------------------
......
......@@ -11,7 +11,7 @@ import Gargantext.Components.Forest.Tree.Node.Action (Action(..), ID, Name)
import Gargantext.Components.Forest.Tree.Node (SettingsBox(..), settingsBox)
import Gargantext.Types (NodeType(..), readNodeType)
import Gargantext.Utils.Reactix as R2
import Prelude (Unit, bind, const, discard, map, pure, show, ($), (<>), (>))
import Prelude (Unit, bind, const, discard, map, pure, show, ($), (<>), (>), (<<<))
import Reactix as R
import Reactix.DOM.HTML as H
......@@ -54,29 +54,24 @@ createNodeView d p@{nodeType} (_ /\ setPopupOpen) nodeTypes = R.createElement el
]
where
SettingsBox {edit} = settingsBox nt
maybeEdit = [ if edit
then
maybeEdit = [ if edit then
H.div {className: "form-group"}
[ H.input { type: "text"
, placeholder: "Node name"
, defaultValue: "Write Name here"
, className: "form-control"
, onInput: mkEffectFn1 $ \e -> setNodeName
$ const
$ e .. "target" .. "value"
, onInput: mkEffectFn1 $ setNodeName <<< const <<< R2.unsafeEventValue
}
]
else
H.div {} []
]
maybeChoose = [ if length nodeTypes > 1
then
R.fragment [H.div {className: "form-group"} $ [ R2.select { className: "form-control"
, onChange: mkEffectFn1 $ \e -> setNodeType
$ const
$ readIt
$ e .. "target" .. "value"
maybeChoose = [ if length nodeTypes > 1 then
R.fragment [
H.div {className: "form-group"} $ [
R2.select { className: "form-control"
, onChange: mkEffectFn1 $ setNodeType <<< const <<< readIt <<< R2.unsafeEventValue
}
(map (\opt -> H.option {} [ H.text $ show opt ]) nodeTypes)
]
......
......@@ -3,13 +3,14 @@ module Gargantext.Components.Forest.Tree.Node.Action.Rename where
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff, launchAff)
import Effect.Uncurried (mkEffectFn1)
import FFI.Simple ((..))
import Gargantext.Components.Forest.Tree.Node.Action
import Gargantext.Types (NodeType)
import Prelude (Unit, bind, const, discard, pure, ($))
import Prelude (Unit, bind, const, discard, pure, ($), (<<<))
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.Forest.Tree.Node.Action
import Gargantext.Types (NodeType)
import Gargantext.Utils.Reactix as R2
-- | START Rename Box
type RenameBoxProps =
......@@ -35,7 +36,7 @@ renameBox d p (true /\ setRenameBoxOpen) = R.createElement el p []
, placeholder: "Rename Node"
, defaultValue: name
, className: "form-control"
, onInput: mkEffectFn1 $ \e -> setRenameNodeName $ const $ e .. "target" .. "value"
, onInput: mkEffectFn1 $ setRenameNodeName <<< const <<< R2.unsafeEventValue
}
]
renameBtn (newName /\ _) =
......
......@@ -64,7 +64,7 @@ uploadFileViewCpt d = R.hooksComponent "UploadFileView" cpt
setMContents $ const $ Just $ UploadFileContents contents
onChangeFileType (fileType /\ setFileType) = mkEffectFn1 $ \e -> do
setFileType $ const $ unsafePartial $ fromJust $ readFileType $ e .. "target" .. "value"
setFileType $ const $ unsafePartial $ fromJust $ readFileType $ R2.unsafeEventValue e
uploadButton :: Int -> R.State (Maybe UploadFileContents) -> R.State FileType -> R.Element
uploadButton id (mContents /\ setMContents) (fileType /\ setFileType) =
......@@ -131,7 +131,7 @@ fileTypeView d p (Just (DroppedFile {contents, fileType}) /\ setDroppedFile) (_
]
where
onChange = mkEffectFn1 $ \e ->
setDroppedFile $ const $ Just $ DroppedFile $ {contents, fileType: readFileType $ e .. "target" .. "value"}
setDroppedFile $ const $ Just $ DroppedFile $ {contents, fileType: readFileType $ R2.unsafeEventValue e}
renderOption opt = H.option {} [ H.text $ show opt ]
panelFooter =
H.div {className: "panel-footer"}
......
......@@ -32,6 +32,7 @@ type Props sigma forceatlas2 =
, graph :: SigmaxTypes.SGraph
, multiSelectEnabledRef :: R.Ref Boolean
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, selectorSize :: R.State Int
, showEdges :: R.State SigmaxTypes.ShowEdgesState
, sigmaRef :: R.Ref Sigmax.Sigma
, sigmaSettings :: sigma
......@@ -102,6 +103,10 @@ graphCpt = R.hooksComponent "Graph" cpt
Sigmax.updateNodes sigma tNodesMap
Sigmax.setEdges sigma (not $ SigmaxTypes.edgeStateHidden showEdges)
-- R.useEffect1' (fst props.selectorSize) $ do
-- Sigmax.dependOnSigma (R.readRef sigmaRef) "[graphCpt (Ready)] no sigma" $ \sigma -> do
-- Sigmax.selectorWithSize sigma $ fst props.selectorSize
stageHooks _ = pure unit
......
......@@ -11,8 +11,6 @@ import Data.Nullable (null, Nullable)
import Data.Sequence as Seq
import Data.Set as Set
import Data.Tuple (fst, snd, Tuple(..))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import DOM.Simple.Types (Element)
import Effect.Aff (Aff)
import Math (log)
......@@ -191,6 +189,7 @@ graphViewCpt = R.hooksComponent "GraphView" cpt
, graph
, multiSelectEnabledRef
, selectedNodeIds: controls.selectedNodeIds
, selectorSize: controls.selectorSize
, showEdges: controls.showEdges
, sigmaRef: controls.sigmaRef
, sigmaSettings: Graph.sigmaSettings
......@@ -204,16 +203,19 @@ convert (GET.GraphData r) = Tuple r.metaData $ SigmaxTypes.Graph {nodes, edges}
nodes = foldMapWithIndex nodeFn r.nodes
nodeFn i (GET.Node n) =
Seq.singleton
{ id : n.id_
, size : log (toNumber n.size + 1.0)
{ borderColor: color
, color : color
, hidden : false
, id : n.id_
, label : n.label
, size : log (toNumber n.size + 1.0)
, type : "def" -- default type
, x : n.x -- cos (toNumber i)
, y : n.y -- sin (toNumber i)
, color : GET.intColor (cDef n.attributes)
}
where
cDef (GET.Cluster {clustDefault}) = clustDefault
color = GET.intColor (cDef n.attributes)
nodesMap = SigmaxTypes.nodesMap nodes
edges = foldMap edgeFn r.edges
edgeFn (GET.Edge e) = Seq.singleton { id : e.id_
......@@ -412,6 +414,6 @@ transformGraph controls graph = SigmaxTypes.Graph {nodes: newNodes, edges: newEd
_ -> edge
nodeMarked node@{ id } =
if Set.member id (fst controls.selectedNodeIds) then
node { color = "#ff0000" }
node { borderColor = "#000", type = "hovered" }
else
node
......@@ -43,6 +43,7 @@ type Controls =
, multiSelectEnabled :: R.State Boolean
, nodeSize :: R.State Range.NumberRange
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
, selectorSize :: R.State Int
, showControls :: R.State Boolean
, showEdges :: R.State SigmaxTypes.ShowEdgesState
, showSidePanel :: R.State GET.SidePanelState
......@@ -60,7 +61,6 @@ type LocalControls =
initialLocalControls :: R.Hooks (Record LocalControls)
initialLocalControls = do
labelSize <- R.useState' 14.0
search <- R.useState' ""
pure $ {
labelSize
......@@ -114,6 +114,16 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
else
pure unit
let edgesConfluenceSorted = A.sortWith (_.confluence) $ Seq.toUnfoldable $ SigmaxTypes.graphEdges props.graph
let edgeConfluenceMin = maybe 0.0 _.confluence $ A.head edgesConfluenceSorted
let edgeConfluenceMax = maybe 100.0 _.confluence $ A.last edgesConfluenceSorted
let edgeConfluenceRange = Range.Closed { min: edgeConfluenceMin, max: edgeConfluenceMax }
let edgesWeightSorted = A.sortWith (_.weight) $ Seq.toUnfoldable $ SigmaxTypes.graphEdges props.graph
let edgeWeightMin = maybe 0.0 _.weight $ A.head edgesWeightSorted
let edgeWeightMax = maybe 100.0 _.weight $ A.last edgesWeightSorted
let edgeWeightRange = Range.Closed { min: edgeWeightMin, max: edgeWeightMax }
let nodesSorted = A.sortWith (_.size) $ Seq.toUnfoldable $ SigmaxTypes.graphNodes props.graph
let nodeSizeMin = maybe 0.0 _.size $ A.head nodesSorted
let nodeSizeMax = maybe 100.0 _.size $ A.last nodesSorted
......@@ -128,8 +138,8 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
RH.li {} [ centerButton props.sigmaRef ]
, RH.li {} [ pauseForceAtlasButton {state: props.forceAtlasState} ]
, RH.li {} [ edgesToggleButton {state: props.showEdges} ]
, RH.li {} [ edgeConfluenceControl props.sigmaRef props.edgeConfluence ]
, RH.li {} [ edgeWeightControl props.sigmaRef props.edgeWeight ]
, RH.li {} [ edgeConfluenceControl edgeConfluenceRange props.edgeConfluence ]
, RH.li {} [ edgeWeightControl edgeWeightRange props.edgeWeight ]
-- change level
-- file upload
-- run demo
......@@ -141,16 +151,14 @@ controlsCpt = R.hooksComponent "GraphControls" cpt
-- zoom: 0 -100 - calculate ratio
, RH.li {} [ multiSelectEnabledButton props.multiSelectEnabled ] -- toggle multi node selection
-- save button
, RH.li {} [ nodeSearchControl { selectedNodeIds: props.selectedNodeIds } ]
, RH.li {} [ nodeSearchControl { graph: props.graph
, selectedNodeIds: props.selectedNodeIds } ]
]
]
]
useGraphControls :: SigmaxTypes.SGraph -> R.Hooks (Record Controls)
useGraphControls graph = do
let edges = SigmaxTypes.graphEdges graph
let nodes = SigmaxTypes.graphNodes graph
cursorSize <- R.useState' 10.0
edgeConfluence <- R.useState' $ Range.Closed { min: 0.0, max: 1.0 }
edgeWeight <- R.useState' $ Range.Closed { min: 0.0, max: 1.0 }
......@@ -160,6 +168,7 @@ useGraphControls graph = do
nodeSize <- R.useState' $ Range.Closed { min: 0.0, max: 100.0 }
showTree <- R.useState' false
selectedNodeIds <- R.useState' $ Set.empty
selectorSize <- R.useState' 5
showControls <- R.useState' false
showEdges <- R.useState' SigmaxTypes.EShow
showSidePanel <- R.useState' GET.InitialClosed
......@@ -175,6 +184,7 @@ useGraphControls graph = do
, multiSelectEnabled
, nodeSize
, selectedNodeIds
, selectorSize
, showControls
, showEdges
, showSidePanel
......
......@@ -34,12 +34,12 @@ rangeControlCpt = R.hooksComponent "RangeButton" cpt
, RS.rangeSlider sliderProps
]
edgeConfluenceControl :: R.Ref Sigmax.Sigma -> R.State Range.NumberRange -> R.Element
edgeConfluenceControl sigmaRef (state /\ setState) =
edgeConfluenceControl :: Range.NumberRange -> R.State Range.NumberRange -> R.Element
edgeConfluenceControl (Range.Closed { min, max }) (state /\ setState) =
rangeControl {
caption: "Edge Confluence Weight"
, sliderProps: {
bounds: Range.Closed { min: 0.0, max: 1.0 }
bounds: Range.Closed { min, max }
, initialValue: state
, epsilon: 0.01
, step: 1.0
......@@ -49,47 +49,32 @@ edgeConfluenceControl sigmaRef (state /\ setState) =
}
}
edgeWeightControl :: R.Ref Sigmax.Sigma -> R.State Range.NumberRange -> R.Element
edgeWeightControl sigmaRef (state /\ setState) =
edgeWeightControl :: Range.NumberRange -> R.State Range.NumberRange -> R.Element
edgeWeightControl (Range.Closed { min, max }) (state /\ setState) =
rangeControl {
caption: "Edge Weight"
, sliderProps: {
bounds: Range.Closed { min: 0.0, max: 3.0 }
bounds: Range.Closed { min, max }
, initialValue: state
, epsilon: 0.01
, step: 1.0
, width: 10.0
, height: 5.0
, onChange: setState <<< const
-- , onChange: \range@(Range.Closed {min, max}) -> do
-- let sigma = R.readRef sigmaRef
-- Sigmax.dependOnSigma sigma "[edgeWeightControl] sigma: Nothing" $ \s -> do
-- Sigma.setSettings s {
-- minEdgeSize: min
-- , maxEdgeSize: max
-- }
-- setState $ const range
}
}
nodeSizeControl :: Range.NumberRange -> R.State Range.NumberRange -> R.Element
nodeSizeControl (Range.Closed { min: rangeMin, max: rangeMax }) (state /\ setState) =
nodeSizeControl (Range.Closed { min, max }) (state /\ setState) =
rangeControl {
caption: "Node Size"
, sliderProps: {
bounds: Range.Closed { min: rangeMin, max: rangeMax }
bounds: Range.Closed { min, max }
, initialValue: state
, epsilon: 0.1
, step: 1.0
, width: 10.0
, height: 5.0
, onChange: \range@(Range.Closed {min, max}) -> do
-- let sigma = R.readRef sigmaRef
-- Sigmax.dependOnSigma sigma "[nodeSizeControl] sigma: Nothing" $ \s -> do
-- Sigma.setSettings s {
-- minNodeSize: min
-- , maxNodeSize: max
-- }
setState $ const range
, onChange: setState <<< const
}
}
......@@ -3,49 +3,70 @@ module Gargantext.Components.GraphExplorer.Search
, nodeSearchControl
) where
import Global (readFloat)
import Prelude
import Data.Sequence as Seq
import Data.Set as Set
import Data.Tuple (snd)
import Data.String as S
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Effect (Effect)
import FFI.Simple ((..))
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Utils.Reactix as R2
type Props = (
selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
graph :: SigmaxTypes.SGraph
, selectedNodeIds :: R.State SigmaxTypes.SelectedNodeIds
)
-- | Whether a node matches a search string
nodeMatchesSearch :: String -> Record SigmaxTypes.Node -> Boolean
nodeMatchesSearch s n = S.contains (S.Pattern $ normalize s) (normalize n.label)
where
normalize = S.toLower
searchNodes :: String -> Seq.Seq (Record SigmaxTypes.Node) -> Seq.Seq (Record SigmaxTypes.Node)
searchNodes "" _ = Seq.empty
searchNodes s nodes = Seq.filter (nodeMatchesSearch s) nodes
nodeSearchControl :: Record Props -> R.Element
nodeSearchControl props = R.createElement sizeButtonCpt props []
sizeButtonCpt :: R.Component Props
sizeButtonCpt = R.hooksComponent "NodeSearchControl" cpt
where
cpt {selectedNodeIds} _ = do
(search /\ setSearch) <- R.useState' ""
cpt {graph, selectedNodeIds} _ = do
search@(search' /\ setSearch) <- R.useState' ""
pure $
H.div { className: "form-group" }
[ H.div { className: "input-group" }
[ H.input { type: "text"
, className: "form-control"
, defaultValue: search
, on: { input: \e -> setSearch $ const $ e .. "target" .. "value" }
}
[ inputWithAutocomplete { autocompleteSearch: autocompleteSearch graph
, onAutocompleteClick: \s -> triggerSearch graph s selectedNodeIds
, onEnterPress: \s -> triggerSearch graph s selectedNodeIds
, state: search }
, H.div { className: "btn input-group-addon"
, on: { click: \_ -> log2 "[sizeButtonCpt] search" search }
, on: { click: \_ -> triggerSearch graph search' selectedNodeIds }
}
[ H.span { className: "fa fa-search" } [] ]
]
]
-- TODO Wherefrom do I get graph nodes?
-- How to implement filtering here? I want to set selectedNodeIds based on graph data.
autocompleteSearch :: SigmaxTypes.SGraph -> String -> Array String
autocompleteSearch graph s = Seq.toUnfoldable $ (_.label) <$> searchNodes s nodes
where
nodes = SigmaxTypes.graphNodes graph
triggerSearch :: SigmaxTypes.SGraph
-> String
-> R.State SigmaxTypes.SelectedNodeIds
-> Effect Unit
triggerSearch graph search (_ /\ setSelectedNodeIds) = do
let nodes = SigmaxTypes.graphNodes graph
let matching = (_.id) <$> searchNodes search nodes
log2 "[triggerSearch] search" search
setSelectedNodeIds $ const $ Set.fromFoldable matching
......@@ -42,7 +42,7 @@ sidebarCpt = R.hooksComponent "Sidebar" cpt
let nodesMap = SigmaxTypes.nodesGraphMap props.graph
pure $
RH.div { id: "sp-container", className: "col-md-2" }
RH.div { id: "sp-container", className: "col-md-3" }
[ RH.div {}
[ RH.div { className: "row" }
[ RH.div { className: "col-md-12" }
......
module Gargantext.Components.InputWithAutocomplete where
import Prelude
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe)
import Data.Tuple.Nested ((/\))
import DOM.Simple as DOM
import DOM.Simple.Event as DE
import Effect (Effect)
import Effect.Timer (setTimeout)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Utils.Reactix as R2
type Completions = Array String
type Props =
(
autocompleteSearch :: String -> Completions
, onAutocompleteClick :: String -> Effect Unit
, onEnterPress :: String -> Effect Unit
, state :: R.State String
)
inputWithAutocomplete :: Record Props -> R.Element
inputWithAutocomplete props = R.createElement inputWithAutocompleteCpt props []
inputWithAutocompleteCpt :: R.Component Props
inputWithAutocompleteCpt = R.hooksComponent "InputWithAutocomplete" cpt
where
cpt props@{autocompleteSearch, onAutocompleteClick, onEnterPress, state: state@(state' /\ setState)} _ = do
inputRef <- R.useRef null
completions <- R.useState' $ autocompleteSearch state'
pure $
H.span { className: "input-with-autocomplete" }
[
completionsCpt completions
, H.input { type: "text"
, ref: inputRef
, className: "form-control"
, value: state'
, on: { blur: onBlur completions
, focus: onFocus completions
, input: onInput completions
, change: onInput completions
, keyUp: onInputKeyUp inputRef completions } }
]
where
-- setTimeout is a bit of a hack here -- clicking on autocomplete
-- element will clear out the blur first, so the autocomplete click
-- won't fire without a timeout here. However, blur is very handy and
-- handles automatic autocomplete search, otherwise I'd have to hide it
-- in various different places (i.e. carefully handle all possible
-- events where blur happens and autocomplete should hide).
onBlur (_ /\ setCompletions) e = setTimeout 100 $ do
setCompletions $ const []
onFocus (_ /\ setCompletions) e = setCompletions $ const $ autocompleteSearch state'
onInput (_ /\ setCompletions) e = do
let val = R2.unsafeEventValue e
setState $ const val
setCompletions $ const $ autocompleteSearch val
onInputKeyUp :: R.Ref (Nullable DOM.Element) -> R.State Completions -> DE.KeyboardEvent -> Effect Unit
onInputKeyUp inputRef (_ /\ setCompletions) e = do
if DE.key e == "Enter" then do
let val = R2.unsafeEventValue e
let mInput = toMaybe $ R.readRef inputRef
setState $ const val
onEnterPress val
case mInput of
Nothing -> pure unit
Just input -> R2.blur input
else
pure $ unit
completionsCpt :: R.State Completions -> R.Element
completionsCpt (completions /\ setCompletions) =
H.div { className }
[
H.div { className: "list-group" } (cCpt <$> completions)
]
where
className = "completions " <> (if completions == [] then "hidden" else "")
cCpt c =
H.button { type: "button"
, className: "list-group-item"
, on: { click: onClick c } } [ H.text c ]
onClick c _ = do
setState $ const c
onAutocompleteClick c
module Gargantext.Components.Search.SearchField
( Search, Props, defaultSearch, searchField, searchFieldComponent, isIsTex) where
import Prelude (const, map, pure, show, discard, ($), (&&), (<), (<$>), (<>), (==))
import Prelude (const, map, pure, show, discard, ($), (&&), (<), (<$>), (<>), (==), (<<<))
import Data.Maybe (Maybe(..), maybe)
import Data.String (length)
import Data.Set as Set
......@@ -9,7 +9,6 @@ import Data.Tuple (fst)
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Gargantext.Utils.Reactix as R2
import FFI.Simple ((..))
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.Search.Types -- (Database(..), readDatabase, Lang(..), readLang, Org(..), readOrg, allOrgs, allIMTorgs, HAL_Filters(..), IMT_org(..))
......@@ -185,7 +184,7 @@ langList (lang /\ setLang) langs =
liItem :: Lang -> R.Element
liItem l = H.option {className : "text-primary center"} [ H.text (show l) ]
lang' e = readLang $ e .. "target" .. "value"
lang' = readLang <<< R2.unsafeEventValue
langNav :: R.State Search -> Array Lang -> R.Element
......@@ -260,7 +259,7 @@ databaseInput ({datafield} /\ setSearch) dbs =
liItem db' = H.option {className : "text-primary center"} [ H.text (show db') ]
onChange e = do
let value = e .. "target" .. "value"
let value = R2.unsafeEventValue e
setSearch $ _ {datafield = Just $ External $ readDatabase value }
......@@ -276,7 +275,7 @@ orgInput ({datafield} /\ setSearch) orgs =
liItem :: Org -> R.Element
liItem org = H.option {className : "text-primary center"} [ H.text (show org) ]
onChange e = do
let value = e .. "target" .. "value"
let value = R2.unsafeEventValue e
setSearch $ _ { datafield = Just $ External $ Just $ HAL $ readOrg value }
filterInput :: R.State String -> R.Element
......@@ -284,10 +283,7 @@ filterInput (term /\ setTerm) =
H.div {className: "form-group"} [ H.input { defaultValue: term
, className: "form-control"
, type: "text"
, on: { change: \e -> setTerm
$ const
$ e .. "target" .. "value"
}
, on: { change: setTerm <<< const <<< R2.unsafeEventValue }
, "required pattern": "[[0-9]+[ ]+]*"
-- TODO ^FIXME not sure about the regex comprehension: that should match "123 2334 44545" only (Integers separated by one space)
-- form validation with CSS
......@@ -308,8 +304,7 @@ searchInput ({term} /\ setSearch) =
]
where
onChange e = do
let value = e .. "target" .. "value"
setSearch $ _ {term = value }
setSearch $ _ { term = R2.unsafeEventValue e }
submitButton :: R.State Search
......
......@@ -132,12 +132,6 @@ handleForceAtlas2Pause sigmaRef (toggled /\ setToggled) mFAPauseRef = do
-- restore edges state
Sigma.stopForceAtlas2 s
_ -> pure unit
-- handle case when user pressed pause/start fa button before timeout fired
--case R.readRef mFAPauseRef of
-- Nothing -> pure unit
-- Just timeoutId -> do
-- R.setRef mFAPauseRef Nothing
-- clearTimeout timeoutId
setEdges :: Sigma.Sigma -> Boolean -> Effect Unit
setEdges sigma val = do
......@@ -148,45 +142,6 @@ setEdges sigma val = do
}
Sigma.setSettings sigma settings
-- -- prevent showing edges (via show edges button) when FA is running (flickering)
-- isFARunning <- Sigma.isForceAtlas2Running sigma
-- case Tuple val isFARunning of
-- Tuple false _ ->
-- Sigma.setSettings sigma settings
-- Tuple true false ->
-- Sigma.setSettings sigma settings
-- _ -> pure unit
markSelectedEdges :: Sigma.Sigma -> ST.SelectedEdgeIds -> ST.EdgesMap -> Effect Unit
markSelectedEdges sigma selectedEdgeIds graphEdges = do
Sigma.forEachEdge sigma \e -> do
case Map.lookup e.id graphEdges of
Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map"
Just {color} -> do
let newColor =
if Set.member e.id selectedEdgeIds then
"#ff0000"
else
color
_ <- pure $ (e .= "color") newColor
pure unit
Sigma.refresh sigma
markSelectedNodes :: Sigma.Sigma -> ST.SelectedNodeIds -> ST.NodesMap -> Effect Unit
markSelectedNodes sigma selectedNodeIds graphNodes = do
Sigma.forEachNode sigma \n -> do
case Map.lookup n.id graphNodes of
Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map"
Just {color} -> do
let newColor =
if Set.member n.id selectedNodeIds then
"#ff0000"
else
color
_ <- pure $ (n .= "color") newColor
pure unit
Sigma.refresh sigma
updateEdges :: Sigma.Sigma -> ST.EdgesMap -> Effect Unit
updateEdges sigma edgesMap = do
......@@ -207,9 +162,14 @@ updateNodes sigma nodesMap = do
let mTNode = Map.lookup n.id nodesMap
case mTNode of
Nothing -> error $ "Node id " <> n.id <> " not found in nodesMap"
(Just {color: tColor, hidden: tHidden}) -> do
(Just { borderColor: tBorderColor
, color: tColor
, hidden: tHidden
, type: tType}) -> do
_ <- pure $ (n .= "borderColor") tBorderColor
_ <- pure $ (n .= "color") tColor
_ <- pure $ (n .= "hidden") tHidden
_ <- pure $ (n .= "type") tType
pure unit
--Sigma.refresh sigma
......@@ -244,3 +204,39 @@ bindSelectedEdgesClick sigmaRef (_ /\ setSelectedEdgeIds) =
Set.delete edge.id eids
else
Set.insert edge.id eids
selectorWithSize :: Sigma.Sigma -> Int -> Effect Unit
selectorWithSize sigma size = do
pure unit
-- DEPRECATED
markSelectedEdges :: Sigma.Sigma -> ST.SelectedEdgeIds -> ST.EdgesMap -> Effect Unit
markSelectedEdges sigma selectedEdgeIds graphEdges = do
Sigma.forEachEdge sigma \e -> do
case Map.lookup e.id graphEdges of
Nothing -> error $ "Edge id " <> e.id <> " not found in graphEdges map"
Just {color} -> do
let newColor =
if Set.member e.id selectedEdgeIds then
"#ff0000"
else
color
_ <- pure $ (e .= "color") newColor
pure unit
Sigma.refresh sigma
markSelectedNodes :: Sigma.Sigma -> ST.SelectedNodeIds -> ST.NodesMap -> Effect Unit
markSelectedNodes sigma selectedNodeIds graphNodes = do
Sigma.forEachNode sigma \n -> do
case Map.lookup n.id graphNodes of
Nothing -> error $ "Node id " <> n.id <> " not found in graphNodes map"
Just {color} -> do
let newColor =
if Set.member n.id selectedNodeIds then
"#ff0000"
else
color
_ <- pure $ (n .= "color") newColor
pure unit
Sigma.refresh sigma
......@@ -6,7 +6,21 @@ if (typeof window !== 'undefined') {
window.sigma = sigma;
}
require('sigma/plugins/garg.js').init(sigma, window);
const CustomShapes = require('sigma/plugins/garg.js').init(sigma, window).customShapes;
require('sigma/src/utils/sigma.utils.js').init(sigma);
sigma.canvas.nodes.hovered = (node, context, settings) => {
// hack
// We need to temporarily set node.type to 'def'. This is for 2 reasons
// 1. Make it render as a normal node
// 2. Avoid infinite recursion (hovers.def calls node renderer and we would end up here back
// again with node.type = 'hovered')
node.type = 'def';
sigma.canvas.hovers.def(node, context, settings);
node.type = 'hovered';
};
CustomShapes.init();
function _sigma(left, right, opts) {
try {
......
......@@ -22,18 +22,21 @@ type Renderer = { "type" :: String, container :: Element }
type Node =
( id :: String
, label :: String
( borderColor :: String
, color :: String
, hidden :: Boolean
, id :: String
, label :: String
, size :: Number
, type :: String -- available types: circle, cross, def, diamond, equilateral, pacman, square, star
, x :: Number
, y :: Number
, size :: Number
, color :: String )
)
type Edge =
( id :: String
, color :: String
( color :: String
, confluence :: Number
, id :: String
, hidden :: Boolean
, size :: Number
, source :: String
......
......@@ -223,3 +223,6 @@ inputFileBlob e = unsafePartial $ do
dataTransferFileBlob e = unsafePartial $ do
let ff = fromJust $ item 0 $ ((e .. "dataTransfer" .. "files") :: FileList)
pure $ toBlob ff
blur :: DOM.Element -> Effect Unit
blur el = el ... "blur" $ []
......@@ -5613,10 +5613,10 @@ sander@^0.5.0:
mkdirp "^0.5.1"
rimraf "^2.5.2"
sass@^1.22.9:
version "1.22.9"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.22.9.tgz#41a2ed6038027f58be2bd5041293452a29c2cb84"
integrity sha512-FzU1X2V8DlnqabrL4u7OBwD2vcOzNMongEJEx3xMEhWY/v26FFR3aG0hyeu2T965sfR0E9ufJwmG+Qjz78vFPQ==
sass@^1.23.7:
version "1.23.7"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.23.7.tgz#090254e006af1219d442f1bff31e139d5e085dff"
integrity sha512-cYgc0fanwIpi0rXisGxl+/wadVQ/HX3RhpdRcjLdj2o2ye/sxUTpAxIhbmJy3PLQgRFbf6Pn8Jsrta2vdXcoOQ==
dependencies:
chokidar ">=2.0.0 <4.0.0"
......
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