Search.purs 2.91 KB
Newer Older
1
module Gargantext.Components.GraphExplorer.Search
2
  ( Props, nodeSearchControl ) where
3 4

import Prelude
5 6

import DOM.Simple.Console (log2)
7
import Data.Foldable (foldl)
8
import Data.Sequence as Seq
9 10
import Data.Set as Set
import Effect (Effect)
11
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
12
import Gargantext.Hooks.Sigmax.Types as SigmaxT
13 14
import Gargantext.Utils (queryMatchesLabel)
import Gargantext.Utils.Reactix as R2
15 16 17
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
18

19
here :: R2.Here
20
here = R2.here "Gargantext.Components.GraphExplorer.Search"
21 22

type Props = (
23
    graph              :: SigmaxT.SGraph
24 25
  , multiSelectEnabled :: T.Box Boolean
  , selectedNodeIds    :: T.Box SigmaxT.NodeIds
26 27
  )

28
-- | Whether a node matches a search string
29
--   Searches given node and matches it's label or any of the children's labels.
30
nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean
31
nodeMatchesSearch s n@{ children } =
32
  foldl (\_ childLabel -> queryMatchesLabel s childLabel) initial children
33 34
  where
    initial = queryMatchesLabel s n.label
35

36
searchNodes :: String -> Seq.Seq (Record SigmaxT.Node) -> Seq.Seq (Record SigmaxT.Node)
37 38
searchNodes "" _ = Seq.empty
searchNodes s nodes = Seq.filter (nodeMatchesSearch s) nodes
39

40
nodeSearchControl :: R2.Component Props
41 42 43
nodeSearchControl = R.createElement nodeSearchControlCpt
nodeSearchControlCpt :: R.Component Props
nodeSearchControlCpt = here.component "nodeSearchControl" cpt
44
  where
45
    cpt { graph, multiSelectEnabled, selectedNodeIds } _ = do
46 47
      search <- T.useBox ""
      search' <- T.useLive T.unequal search
48
      multiSelectEnabled' <- T.useLive T.unequal multiSelectEnabled
49

50 51
      let doSearch s = triggerSearch graph s multiSelectEnabled' selectedNodeIds

52 53 54
      pure $ R.fragment
        [ inputWithAutocomplete { autocompleteSearch: autocompleteSearch graph
                                , classes: "mx-2"
55 56
                                , onAutocompleteClick: doSearch
                                , onEnterPress: doSearch
57 58
                                , state: search } []
        , H.div { className: "btn input-group-addon"
59
                , on: { click: \_ -> doSearch search' }
60 61 62
                }
          [ H.span { className: "fa fa-search" } [] ]
        ]
63

64
autocompleteSearch :: SigmaxT.SGraph -> String -> Array String
65 66
autocompleteSearch graph s = Seq.toUnfoldable $ (_.label) <$> searchNodes s nodes
  where
67
    nodes = SigmaxT.graphNodes graph
68

69
triggerSearch :: SigmaxT.SGraph
70
              -> String
71
              -> Boolean
72
              -> T.Box SigmaxT.NodeIds
73
              -> Effect Unit
74
triggerSearch graph search multiSelectEnabled selectedNodeIds = do
75
  let graphNodes = SigmaxT.graphNodes graph
76
  let matching = Set.fromFoldable $ (_.id) <$> searchNodes search graphNodes
77

78
  log2 "[triggerSearch] search" search
79

80
  T.modify_ (\nodes ->
81
    Set.union matching $ if multiSelectEnabled then nodes else SigmaxT.emptyNodeIds) selectedNodeIds