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

import Prelude
7
import Data.Sequence as Seq
8
import Data.Set as Set
9
import Data.String as S
10
import Data.Tuple.Nested ((/\))
11
import DOM.Simple.Console (log2)
12 13 14 15
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H

16
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
17
import Gargantext.Hooks.Sigmax.Types as SigmaxT
18 19

type Props = (
20
    graph           :: SigmaxT.SGraph
21
  , multiSelectEnabled :: R.State Boolean
22
  , selectedNodeIds :: R.State SigmaxT.NodeIds
23 24
  )

25
-- | Whether a node matches a search string
26
nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean
27 28 29 30
nodeMatchesSearch s n = S.contains (S.Pattern $ normalize s) (normalize n.label)
  where
    normalize = S.toLower

31
searchNodes :: String -> Seq.Seq (Record SigmaxT.Node) -> Seq.Seq (Record SigmaxT.Node)
32 33
searchNodes "" _ = Seq.empty
searchNodes s nodes = Seq.filter (nodeMatchesSearch s) nodes
34

35 36 37 38 39 40
nodeSearchControl :: Record Props -> R.Element
nodeSearchControl props = R.createElement sizeButtonCpt props []

sizeButtonCpt :: R.Component Props
sizeButtonCpt = R.hooksComponent "NodeSearchControl" cpt
  where
41
    cpt {graph, multiSelectEnabled, selectedNodeIds} _ = do
42
      search@(search' /\ setSearch) <- R.useState' ""
43 44

      pure $
45 46
        H.div { className: "form-group" }
          [ H.div { className: "input-group" }
47
            [ inputWithAutocomplete { autocompleteSearch: autocompleteSearch graph
48 49
                                    , onAutocompleteClick: \s -> triggerSearch graph s multiSelectEnabled selectedNodeIds
                                    , onEnterPress: \s -> triggerSearch graph s multiSelectEnabled selectedNodeIds
50
                                    , state: search }
51
            , H.div { className: "btn input-group-addon"
52
                    , on: { click: \_ -> triggerSearch graph search' multiSelectEnabled selectedNodeIds }
53
                    }
54 55
              [ H.span { className: "fa fa-search" } [] ]
            ]
56 57
          ]

58
autocompleteSearch :: SigmaxT.SGraph -> String -> Array String
59 60
autocompleteSearch graph s = Seq.toUnfoldable $ (_.label) <$> searchNodes s nodes
  where
61
    nodes = SigmaxT.graphNodes graph
62

63
triggerSearch :: SigmaxT.SGraph
64 65
              -> String
              -> R.State Boolean
66
              -> R.State SigmaxT.NodeIds
67
              -> Effect Unit
68 69
triggerSearch graph search (multiSelectEnabled /\ _) (_ /\ setNodeIds) = do
  let graphNodes = SigmaxT.graphNodes graph
70
  let matching = Set.fromFoldable $ (_.id) <$> searchNodes search graphNodes
71

72
  log2 "[triggerSearch] search" search
73

74 75
  setNodeIds $ \nodes ->
    Set.union matching $ if multiSelectEnabled then nodes else SigmaxT.emptyNodeIds