Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Grégoire Locqueville
purescript-gargantext
Commits
5f71811d
Commit
5f71811d
authored
Feb 10, 2022
by
arturo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[graph] Graph search completion issue
* #364
parent
405eea77
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
36 deletions
+78
-36
Search.purs
src/Gargantext/Components/GraphExplorer/Search.purs
+6
-7
InputWithAutocomplete.purs
src/Gargantext/Components/InputWithAutocomplete.purs
+72
-29
No files found.
src/Gargantext/Components/GraphExplorer/Search.purs
View file @
5f71811d
...
@@ -2,19 +2,19 @@ module Gargantext.Components.GraphExplorer.Search
...
@@ -2,19 +2,19 @@ module Gargantext.Components.GraphExplorer.Search
( Props, nodeSearchControl ) where
( Props, nodeSearchControl ) where
import Prelude
import Prelude
import DOM.Simple.Console (log2)
import Data.Foldable (foldl)
import Data.Foldable (foldl)
import Data.Sequence as Seq
import Data.Sequence as Seq
import Data.Set as Set
import Data.Set as Set
import DOM.Simple.Console (log2)
import Effect (Effect)
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Utils (queryMatchesLabel)
import Gargantext.Utils (queryMatchesLabel)
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Search"
here = R2.here "Gargantext.Components.GraphExplorer.Search"
...
@@ -29,7 +29,7 @@ type Props = (
...
@@ -29,7 +29,7 @@ type Props = (
-- Searches given node and matches it's label or any of the children's labels.
-- Searches given node and matches it's label or any of the children's labels.
nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean
nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean
nodeMatchesSearch s n@{ children } =
nodeMatchesSearch s n@{ children } =
foldl (\
acc
childLabel -> queryMatchesLabel s childLabel) initial children
foldl (\
_
childLabel -> queryMatchesLabel s childLabel) initial children
where
where
initial = queryMatchesLabel s n.label
initial = queryMatchesLabel s n.label
...
@@ -79,4 +79,3 @@ triggerSearch graph search multiSelectEnabled selectedNodeIds = do
...
@@ -79,4 +79,3 @@ triggerSearch graph search multiSelectEnabled selectedNodeIds = do
T.modify_ (\nodes ->
T.modify_ (\nodes ->
Set.union matching $ if multiSelectEnabled then nodes else SigmaxT.emptyNodeIds) selectedNodeIds
Set.union matching $ if multiSelectEnabled then nodes else SigmaxT.emptyNodeIds) selectedNodeIds
src/Gargantext/Components/InputWithAutocomplete.purs
View file @
5f71811d
...
@@ -2,14 +2,14 @@ module Gargantext.Components.InputWithAutocomplete where
...
@@ -2,14 +2,14 @@ module Gargantext.Components.InputWithAutocomplete where
import Prelude
import Prelude
import DOM.Simple (contains)
import DOM.Simple as DOM
import DOM.Simple as DOM
import DOM.Simple.Event as DE
import DOM.Simple.Event as DE
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..)
, maybe
)
import Data.Nullable (Nullable, null, toMaybe)
import Data.Nullable (Nullable, null, toMaybe)
import Effect (Effect)
import Effect (Effect)
import
Effect.Timer (setTimeout
)
import
FFI.Simple ((..)
)
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import React.SyntheticEvent as E
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
import Toestand as T
import Toestand as T
...
@@ -34,43 +34,72 @@ inputWithAutocomplete = R.createElement inputWithAutocompleteCpt
...
@@ -34,43 +34,72 @@ inputWithAutocomplete = R.createElement inputWithAutocompleteCpt
inputWithAutocompleteCpt :: R.Component Props
inputWithAutocompleteCpt :: R.Component Props
inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
where
where
cpt
props@
{ autocompleteSearch
cpt { autocompleteSearch
, classes
, classes
, onAutocompleteClick
, onAutocompleteClick
, onEnterPress
, onEnterPress
, state } _ = do
, state } _ = do
-- States
state' <- T.useLive T.unequal state
state' <- T.useLive T.unequal state
containerRef <- R.useRef null
inputRef <- R.useRef null
inputRef <- R.useRef null
completions <- T.useBox $ autocompleteSearch state'
completions <- T.useBox $ autocompleteSearch state'
let onFocus completions' _ = T.write_ (autocompleteSearch state') completions'
-- Render
pure $
pure $
H.span { className: "input-with-autocomplete " <> classes }
H.div
{ className: "input-with-autocomplete " <> classes
, ref: containerRef
}
[
[
completionsCpt { completions, onAutocompleteClick, state } []
completionsCpt { completions, onAutocompleteClick, state } []
, H.input { type: "text"
, H.input { type: "text"
, ref: inputRef
, ref: inputRef
, className: "form-control"
, className: "form-control"
, value: state'
, value: state'
, on: { blur: onBlur completions
, on: { focus: onFocus completions state'
, focus: onFocus completions
, input: onInput completions
, input: onInput completions
, change: onInput completions
, change: onInput completions
, keyUp: onInputKeyUp inputRef } }
, keyUp: onInputKeyUp inputRef
, blur: onBlur completions containerRef
}
}
]
]
-- Helpers
where
where
-- (!) `onBlur` DOM.Event is triggered before any `onClick` DOM.Event
-- setTimeout is a bit of a hack here -- clicking on autocomplete
-- So when a completion is being clicked, the UX will be broken
-- element will clear out the blur first, so the autocomplete click
--
-- won't fire without a timeout here. However, blur is very handy and
-- ↳ As a solution we chose to check if the click is made from
-- handles automatic autocomplete search, otherwise I'd have to hide it
-- the autocompletion list
-- in various different places (i.e. carefully handle all possible
onBlur :: forall event.
-- events where blur happens and autocomplete should hide).
T.Box Completions
onBlur completions _ = setTimeout 100 $ do
-> R.Ref (Nullable DOM.Element)
-> event
-> Effect Unit
onBlur completions containerRef event =
if isInnerEvent
then
pure $ (event .. "preventDefault")
else
T.write_ [] completions
T.write_ [] completions
where
mContains = do
a <- toMaybe $ R.readRef containerRef
b <- toMaybe (event .. "relatedTarget")
Just (contains a b)
isInnerEvent = maybe false identity mContains
onFocus :: forall event. T.Box Completions -> String -> event -> Effect Unit
onFocus completions st _ = T.write_ (autocompleteSearch st) completions
onInput :: forall event. T.Box Completions -> event -> Effect Unit
onInput completions e = do
onInput completions e = do
let val = R.unsafeEventValue e
let val = R.unsafeEventValue e
T.write_ val state
T.write_ val state
...
@@ -93,6 +122,10 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
...
@@ -93,6 +122,10 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
else
else
pure $ false
pure $ false
---------------------------------------------------------
type CompletionsProps =
type CompletionsProps =
( completions :: T.Box Completions
( completions :: T.Box Completions
, onAutocompleteClick :: String -> Effect Unit
, onAutocompleteClick :: String -> Effect Unit
...
@@ -106,19 +139,29 @@ completionsCptCpt :: R.Component CompletionsProps
...
@@ -106,19 +139,29 @@ completionsCptCpt :: R.Component CompletionsProps
completionsCptCpt = here.component "completionsCpt" cpt
completionsCptCpt = here.component "completionsCpt" cpt
where
where
cpt { completions, onAutocompleteClick, state } _ = do
cpt { completions, onAutocompleteClick, state } _ = do
-- State
completions' <- T.useLive T.unequal completions
completions' <- T.useLive T.unequal completions
let className = "completions " <> (if completions' == [] then "d-none" else "")
let className = "completions " <> (if completions' == [] then "d-none" else "")
pure $ H.div { className }
-- Render
pure $
H.div
{ className }
[
[
H.div { className: "list-group" } (cCpt <$> completions')
H.div { className: "list-group" } (cCpt <$> completions')
]
]
-- Helpers
where
where
cCpt c =
cCpt c =
H.button { type: "button"
H.button { type: "button"
, className: "list-group-item"
, className: "list-group-item"
, on: { click: onClick c } } [ H.text c ]
, on: { click: onClick c } } [ H.text c ]
onClick c _ = do
onClick c _ = do
T.write_ c state
T.write_ c state
T.write_ [] completions
onAutocompleteClick c
onAutocompleteClick c
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment