Commit 88ba14e3 authored by Nicolas Pouillard's avatar Nicolas Pouillard Committed by Alexandre Delanoë

[Document] refactor the annotated field menu

parent 2d431463
...@@ -13,9 +13,9 @@ module Gargantext.Components.Annotation.AnnotatedField where ...@@ -13,9 +13,9 @@ module Gargantext.Components.Annotation.AnnotatedField where
import Prelude import Prelude
import Data.Maybe ( Maybe(..), maybe ) import Data.Maybe ( Maybe(..), maybe )
import Data.Tuple ( Tuple(..) ) import Data.Tuple ( Tuple )
import Data.Tuple.Nested ( (/\) ) import Data.Tuple.Nested ( (/\) )
import DOM.Simple.Console (log2) --import DOM.Simple.Console (log2)
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import Effect ( Effect ) import Effect ( Effect )
import Reactix as R import Reactix as R
...@@ -25,7 +25,7 @@ import Reactix.SyntheticEvent as E ...@@ -25,7 +25,7 @@ import Reactix.SyntheticEvent as E
import Gargantext.Types (CTabNgramType(..), TermList) import Gargantext.Types (CTabNgramType(..), TermList)
import Gargantext.Components.Annotation.Utils ( termBootstrapClass ) import Gargantext.Components.Annotation.Utils ( termBootstrapClass )
import Gargantext.Components.NgramsTable.Core (NgramsTable, NgramsTerm, findNgramTermList, highlightNgrams, normNgram) import Gargantext.Components.NgramsTable.Core (NgramsTable, NgramsTerm, findNgramTermList, highlightNgrams, normNgram)
import Gargantext.Components.Annotation.Menu ( AnnotationMenu, annotationMenu, MenuType(..) ) import Gargantext.Components.Annotation.Menu ( annotationMenu, MenuType(..) )
import Gargantext.Utils.Selection as Sel import Gargantext.Utils.Selection as Sel
thisModule :: String thisModule :: String
...@@ -48,110 +48,65 @@ annotatedField p = R.createElement annotatedFieldComponent p [] ...@@ -48,110 +48,65 @@ annotatedField p = R.createElement annotatedFieldComponent p []
annotatedFieldComponent :: R.Component Props annotatedFieldComponent :: R.Component Props
annotatedFieldComponent = R.hooksComponentWithModule thisModule "annotatedField" cpt annotatedFieldComponent = R.hooksComponentWithModule thisModule "annotatedField" cpt
where where
cpt {ngrams,setTermList,text} _ = do cpt {ngrams,setTermList,text: fieldText} _ = do
mMenu@(_ /\ setMenu) <- R.useState' Nothing (_ /\ setRedrawMenu) <- R.useState' false
menuRef <- R.useRef Nothing menuRef <- R.useRef Nothing
let wrapperProps = { className: "annotated-field-wrapper" } let wrapperProps = { className: "annotated-field-wrapper" }
onSelect :: String -> Maybe TermList -> MouseEvent -> Effect Unit redrawMenu = setRedrawMenu not
onSelect text' Nothing event = do
--log2 "[onSelect] text'" text' hideMenu = do
maybeShowMenu setMenu menuRef setTermList ngrams event R.setRef menuRef Nothing
onSelect text' (Just list) event = do redrawMenu
--log2 "[onSelect] text'" text'
--log2 "[onSelect] list" (show list) showMenu { event, text, getList, menuType } = do
let x = E.clientX event let x = E.clientX event
y = E.clientY event y = E.clientY event
n = normNgram CTabTerms text
list = getList n
setList t = do setList t = do
R.setRef menuRef Nothing setTermList n list t
setTermList (normNgram CTabTerms text') (Just list) t hideMenu
--setMenu (const Nothing) E.preventDefault event
menu = Just { --range <- Sel.getRange sel 0
x --log2 "[showMenu] selection range" $ Sel.rangeToTuple range
let menu = Just
{ x
, y , y
, list: Just list , list
, menuType: SetTermListItem , menuType
, onClose: \_ -> R.setRef menuRef Nothing , onClose: hideMenu
, setList , setList
} }
R.setRef menuRef menu R.setRef menuRef menu
setMenu $ const menu redrawMenu
mapCompile (Tuple t l) = {text: t, list: l, onSelect}
compiled = map mapCompile $ compile ngrams text
runs =
HTML.div { className: "annotated-field-runs" } $ map annotateRun compiled
--pure $ HTML.div wrapperProps [maybeAddMenu mMenu runs]
pure $ HTML.div wrapperProps [ addMenu { menuRef }, runs ]
type AddMenuProps = (
menuRef :: R.Ref (Maybe AnnotationMenu)
)
onSelect :: String -> Maybe TermList -> MouseEvent -> Effect Unit
addMenu :: Record AddMenuProps -> R.Element onSelect text mList event =
addMenu p = R.createElement addMenuCpt p [] case mList of
Just list ->
addMenuCpt :: R.Component AddMenuProps showMenu { event, text, getList: const (Just list), menuType: SetTermListItem }
addMenuCpt = R.hooksComponentWithModule thisModule "addMenu" cpt Nothing -> do
where s <- Sel.getSelection
cpt { menuRef } _ = do case s of
(mMenu /\ setmMenu) <- R.useState' (Nothing :: Maybe AnnotationMenu) Just sel -> do
case Sel.selectionToString sel of
R.useEffect' $ do "" -> hideMenu
let m = R.readRef menuRef sel' -> do
--log2 "[addMenu] menuRef" m showMenu { event, text: sel', getList: findNgramTermList ngrams, menuType: NewNgram }
--log2 "[addMenu] mMenu" mMenu Nothing -> hideMenu
setmMenu $ const m
wrap (text /\ list) = {text, list, onSelect}
pure $ case mMenu of
Nothing -> HTML.div {} [] pure $ HTML.div wrapperProps
Just menu -> annotationMenu setmMenu menu [ maybe (HTML.div {} []) annotationMenu $ R.readRef menuRef
, HTML.div { className: "annotated-field-runs" }
-- forall e. IsMouseEvent e => R.Setter (Maybe AnnotationMenu) -> R.Setter ? -> ? -> e -> Effect Unit $ annotateRun
maybeShowMenu setMenu menuRef setTermList ngrams event = do <$> wrap
s <- Sel.getSelection <$> compile ngrams fieldText
--log2 "[maybeShowMenu] s" s ]
case s of
Just sel -> do
case Sel.selectionToString sel of
"" -> pure unit
sel' -> do
let x = E.clientX event
y = E.clientY event
n = normNgram CTabTerms sel'
list = findNgramTermList ngrams n
setList t = do
setTermList n list t
R.setRef menuRef Nothing
--setMenu (const Nothing)
E.preventDefault event
range <- Sel.getRange sel 0
--log2 "[maybeShowMenu] selection range" $ Sel.rangeToTuple range
let menu = Just {
x
, y
, list
, menuType: NewNgram
, onClose: \_ -> R.setRef menuRef Nothing
, setList
}
R.setRef menuRef menu
setMenu $ const $ menu
Nothing -> pure unit
-- Nothing -> do
-- R.setRef menuRef Nothing
maybeAddMenu
:: R.State (Maybe AnnotationMenu)
-> R.Element
-> R.Element
maybeAddMenu (Just props /\ setMenu) e = annotationMenu setMenu props <> e
maybeAddMenu _ e = e
compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList)) compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList))
compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams) compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams)
...@@ -170,13 +125,11 @@ annotateRun p = R.createElement annotatedRunComponent p [] ...@@ -170,13 +125,11 @@ annotateRun p = R.createElement annotatedRunComponent p []
annotatedRunComponent :: R.Component Run annotatedRunComponent :: R.Component Run
annotatedRunComponent = R.staticComponent "AnnotatedRun" cpt annotatedRunComponent = R.staticComponent "AnnotatedRun" cpt
where where
cpt { list: Nothing, onSelect, text } _ = cpt { list, onSelect, text } _ = elt [ HTML.text text ]
HTML.span { on: { mouseUp: \e -> onSelect text Nothing e } } [ HTML.text text ]
cpt { list: (Just list), onSelect, text } _ =
HTML.span { className: className list
, on: { click: \e -> onSelect text (Just list) e } } [ HTML.text text ]
where where
className list' = "annotation-run bg-" <> termBootstrapClass list' cb = onSelect text list
elt =
case list of
Nothing -> HTML.span { on: { mouseUp: cb } }
Just l -> HTML.span { className: "annotation-run bg-" <> termBootstrapClass l
, on: { click: cb } }
\ No newline at end of file
...@@ -30,16 +30,16 @@ type Props = ...@@ -30,16 +30,16 @@ type Props =
type AnnotationMenu = { type AnnotationMenu = {
x :: Number x :: Number
, y :: Number , y :: Number
, onClose :: Unit -> Effect Unit , onClose :: Effect Unit
| Props | Props
} }
-- | An Annotation Menu is parameterised by a Maybe Termlist of the -- | An Annotation Menu is parameterised by a Maybe Termlist of the
-- | TermList the currently selected text belongs to -- | TermList the currently selected text belongs to
annotationMenu :: R.Setter (Maybe AnnotationMenu) -> AnnotationMenu -> R.Element annotationMenu :: AnnotationMenu -> R.Element
annotationMenu setMenu { x,y,list,menuType, onClose,setList } = annotationMenu {x, y, list, menuType, onClose, setList} =
CM.contextMenu { x,y, onClose, setMenu } [ CM.contextMenu {x, y, onClose} [
R.createElement annotationMenuCpt {list,menuType,setList} [] R.createElement annotationMenuCpt {list, menuType, setList} []
] ]
annotationMenuCpt :: R.Component Props annotationMenuCpt :: R.Component Props
......
...@@ -26,8 +26,7 @@ thisModule = "Gargantext.Components.ContextMenu.ContextMenu" ...@@ -26,8 +26,7 @@ thisModule = "Gargantext.Components.ContextMenu.ContextMenu"
type Props t = ( type Props t = (
x :: Number x :: Number
, y :: Number , y :: Number
, onClose :: Unit -> Effect Unit , onClose :: Effect Unit
, setMenu :: R.Setter (Maybe t)
) )
contextMenu :: forall t. Record (Props t) -> Array R.Element -> R.Element contextMenu :: forall t. Record (Props t) -> Array R.Element -> R.Element
...@@ -36,7 +35,7 @@ contextMenu = R.createElement contextMenuCpt ...@@ -36,7 +35,7 @@ contextMenu = R.createElement contextMenuCpt
contextMenuCpt :: forall t. R.Component (Props t) contextMenuCpt :: forall t. R.Component (Props t)
contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt
where where
cpt menu@{ x, y, onClose, setMenu } children = do cpt menu@{ x, y, onClose } children = do
host <- R2.getPortalHost host <- R2.getPortalHost
root <- R.useRef null root <- R.useRef null
rect /\ setRect <- R.useState $ \_ -> Nothing rect /\ setRect <- R.useState $ \_ -> Nothing
...@@ -45,7 +44,7 @@ contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt ...@@ -45,7 +44,7 @@ contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt
(\r -> setRect (\_ -> Just (Element.boundingRect r))) (\r -> setRect (\_ -> Just (Element.boundingRect r)))
(toMaybe $ R.readRef root) (toMaybe $ R.readRef root)
pure $ pure unit pure $ pure unit
R.useLayoutEffect2 root rect (contextMenuEffect onClose setMenu root) R.useLayoutEffect2 root rect (contextMenuEffect onClose root)
let cs = [ let cs = [
HTML.div { className: "popover-content" } HTML.div { className: "popover-content" }
[ HTML.div { className: "panel panel-default" } [ HTML.div { className: "panel panel-default" }
...@@ -57,27 +56,28 @@ contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt ...@@ -57,27 +56,28 @@ contextMenuCpt = R.hooksComponentWithModule thisModule "contextMenu" cpt
pure $ R.createPortal [ elems root menu rect $ cs ] host pure $ R.createPortal [ elems root menu rect $ cs ] host
elems ref menu (Just rect) = HTML.div elems ref menu (Just rect) = HTML.div
{ ref { ref
, key: "context-menu"
, className: "context-menu" , className: "context-menu"
, style: position menu rect , style: position menu rect
, data: {toggle: "popover", placement: "right"} , data: {toggle: "popover", placement: "right"}
} }
elems ref _ _ = HTML.div elems ref _ _ = HTML.div
{ ref { ref
, key: "context-menu"
, className: "context-menu" , className: "context-menu"
, data: {toggle: "popover", placement: "right"} , data: {toggle: "popover", placement: "right"}
} }
contextMenuEffect contextMenuEffect
:: forall t. :: forall t.
(Unit -> Effect Unit) Effect Unit
-> R.Setter (Maybe t)
-> R.Ref (Nullable DOM.Element) -> R.Ref (Nullable DOM.Element)
-> Effect (Effect Unit) -> Effect (Effect Unit)
contextMenuEffect onClose setMenu rootRef = contextMenuEffect onClose rootRef =
case R.readNullableRef rootRef of case R.readNullableRef rootRef of
Just root -> do Just root -> do
let onClick = documentClickHandler onClose setMenu root let onClick = documentClickHandler onClose root
let onScroll = documentScrollHandler setMenu let onScroll = documentScrollHandler onClose
DOM.addEventListener document "click" onClick DOM.addEventListener document "click" onClick
DOM.addEventListener document "scroll" onScroll DOM.addEventListener document "scroll" onScroll
pure $ do pure $ do
...@@ -85,18 +85,14 @@ contextMenuEffect onClose setMenu rootRef = ...@@ -85,18 +85,14 @@ contextMenuEffect onClose setMenu rootRef =
DOM.removeEventListener document "scroll" onScroll DOM.removeEventListener document "scroll" onScroll
Nothing -> pure R.nothing Nothing -> pure R.nothing
documentClickHandler :: forall t. (Unit -> Effect Unit) -> R.Setter (Maybe t) -> DOM.Element -> Callback DE.MouseEvent documentClickHandler :: Effect Unit -> DOM.Element -> Callback DE.MouseEvent
documentClickHandler onClose hide menu = documentClickHandler onClose menu =
R2.named "hideMenuOnClickOutside" $ callback $ \e -> R2.named "hideMenuOnClickOutside" $ callback $ \e ->
if Element.contains menu (DE.target e) when (Element.contains menu (DE.target e)) onClose
then pure unit
else do documentScrollHandler :: Effect Unit -> Callback DE.MouseEvent
hide (const Nothing) documentScrollHandler onClose =
onClose unit R2.named "hideMenuOnScroll" $ callback $ \e -> onClose
documentScrollHandler :: forall t. R.Setter (Maybe t) -> Callback DE.MouseEvent
documentScrollHandler hide =
R2.named "hideMenuOnScroll" $ callback $ \e -> hide (const Nothing)
position :: forall t. Record (Props t) -> DOMRect -> { left :: Number, top :: Number } position :: forall t. Record (Props t) -> DOMRect -> { left :: Number, top :: Number }
position mouse {width: menuWidth, height: menuHeight} = {left, top} position mouse {width: menuWidth, height: menuHeight} = {left, top}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment