module Gargantext.Components.GraphExplorer.Search ( Props , nodeSearchControl ) where import Prelude import Data.Sequence as Seq import Data.Set as Set import Data.String as S import Data.Tuple.Nested ((/\)) import DOM.Simple.Console (log2) import Effect (Effect) import Reactix as R import Reactix.DOM.HTML as H import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete) import Gargantext.Hooks.Sigmax.Types as SigmaxT type Props = ( graph :: SigmaxT.SGraph , multiSelectEnabled :: R.State Boolean , selectedNodeIds :: R.State SigmaxT.NodeIds ) -- | Whether a node matches a search string nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean nodeMatchesSearch s n = S.contains (S.Pattern $ normalize s) (normalize n.label) where normalize = S.toLower searchNodes :: String -> Seq.Seq (Record SigmaxT.Node) -> Seq.Seq (Record SigmaxT.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 {graph, multiSelectEnabled, selectedNodeIds} _ = do search@(search' /\ setSearch) <- R.useState' "" pure $ H.div { className: "form-group" } [ H.div { className: "input-group" } [ inputWithAutocomplete { autocompleteSearch: autocompleteSearch graph , onAutocompleteClick: \s -> triggerSearch graph s multiSelectEnabled selectedNodeIds , onEnterPress: \s -> triggerSearch graph s multiSelectEnabled selectedNodeIds , state: search } , H.div { className: "btn input-group-addon" , on: { click: \_ -> triggerSearch graph search' multiSelectEnabled selectedNodeIds } } [ H.span { className: "fa fa-search" } [] ] ] ] autocompleteSearch :: SigmaxT.SGraph -> String -> Array String autocompleteSearch graph s = Seq.toUnfoldable $ (_.label) <$> searchNodes s nodes where nodes = SigmaxT.graphNodes graph triggerSearch :: SigmaxT.SGraph -> String -> R.State Boolean -> R.State SigmaxT.NodeIds -> Effect Unit triggerSearch graph search (multiSelectEnabled /\ _) (_ /\ setNodeIds) = do let graphNodes = SigmaxT.graphNodes graph let matching = Set.fromFoldable $ (_.id) <$> searchNodes search graphNodes log2 "[triggerSearch] search" search setNodeIds $ \nodes -> Set.union matching $ if multiSelectEnabled then nodes else SigmaxT.emptyNodeIds