SearchField.purs 3.43 KB
Newer Older
1 2
module Gargantext.Components.Search.SearchField
  ( Search, Props, searchField, searchFieldComponent )where
3 4 5 6 7 8 9 10 11 12 13 14 15 16

import Prelude hiding (div)
import Data.Map as Map
import Data.Maybe ( Maybe(..), maybe, maybe' )
import Data.Nullable (Nullable, null)
import Data.Traversable ( traverse_ )
import Data.Tuple ( Tuple(..), fst )
import Data.Tuple.Nested ( (/\) )
import DOM.Simple as DOM
import DOM.Simple.Console
import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import Effect ( Effect )
import Effect.Uncurried (mkEffectFn1)
17
import FFI.Simple ((..), (.=))
18 19
import Reactix as R
import Reactix.DOM.HTML as HTML
20
import Reactix.DOM.HTML (text, button, div, input, option, form, span, ul, li, a)
21
import Reactix.SyntheticEvent as E
22
import Gargantext.Components.Search.Types
23 24 25

select = R.createElement "select"

26
type Search = { database :: Maybe Database, term :: String }
27 28

defaultSearch :: Search
29
defaultSearch = { database: Nothing, term: "" }
30

31
type Props =
32 33
  -- list of databases to search, or parsers to use on uploads
  ( databases :: Array Database
34
  -- State hook for a search, how we get data in and out
35
  , search :: R.State (Maybe Search)
36 37 38 39 40 41 42 43 44 45 46 47
  )

searchField :: Record Props -> R.Element
searchField p = R.createElement searchFieldComponent p []

placeholder :: String
placeholder = "Query, URL or FILE (works with Firefox or Chromium browsers)"

searchFieldComponent :: R.Memo Props
searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
  where
    cpt props _ = do
48 49
      let search = maybe defaultSearch identity (fst props.search)
      term <- R.useState $ \_ -> pure search.term
50
      db   <- R.useState $ \_ -> pure Nothing
51
      pure $
52 53 54 55 56 57
          div { className: "search-field input-group" }
              [ databaseInput db props.databases
              , searchInput term
              , span { className: "input-group-btn" }
                     [ submitButton db term props.search ]
              ]
58 59 60 61
    hasChanged p p' = (fst p.search /= fst p'.search) || (p.databases /= p'.databases)

databaseInput :: R.State (Maybe Database) -> Array Database -> R.Element
databaseInput (db /\ setDB) dbs =
62 63 64 65
  div { className: "input-group-btn search-panel dropdown" }
      [
        dropdownBtn db
        , ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
66
      ]
67
  where
68
    liItem db = li { onClick }
69
                   [ a {href: "#"} [text (show db) ] ]
70
                where
71
                  onClick = mkEffectFn1 $ \_ -> setDB $ Just db
72 73 74 75
    dropdownBtnProps = { id: "search-dropdown"
                        , className: "btn btn-default dropdown-toggle"
                        , type: "button"} .= "data-toggle" $ "dropdown"
    dropdownBtn (Just db) = button dropdownBtnProps [ span {} [ text (show db) ] ]
76
    dropdownBtn (Nothing) = button dropdownBtnProps [ span {} [ text "-" ] ]
77 78 79

searchInput :: R.State String -> R.Element
searchInput (term /\ setTerm) =
80
  input { defaultValue: term
81 82 83 84
        , className: "form-control"
        , type: "text"
        , onChange
        , placeholder }
85 86
  where onChange = mkEffectFn1 $ \e -> setTerm $ e .. "target" .. "value"

87

88
submitButton :: R.State (Maybe Database) -> R.State String -> R.State (Maybe Search) -> R.Element
89
submitButton (database /\ _) (term /\ _) (_ /\ setSearch) =
90
  button { className: "btn btn-default", type: "button", onClick: click } [ text "Search" ]
91
  where
92 93 94
    click = mkEffectFn1 $ \_ -> do
      case term of
        "" -> setSearch Nothing
95
        _ -> setSearch $ Just { database, term }