Commit cb227644 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[ui] inputWithEnter component

Changed contacts, rename node, corpus code file name to use input field
where enter confirms the edition.
parent b2ba68f5
...@@ -6,17 +6,17 @@ import Data.Set (Set) ...@@ -6,17 +6,17 @@ import Data.Set (Set)
import Data.Set as Set import Data.Set as Set
import Data.String as S import Data.String as S
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Gargantext.Types (Name)
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff) import Effect.Aff (Aff, launchAff, launchAff_)
import Effect.Uncurried (mkEffectFn1) import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.Forest.Tree.Node.Action import Gargantext.Components.Forest.Tree.Node.Action
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Prelude (Unit, bind, const, discard, pure, show, ($), (<<<), (<>), read, map, class Read, class Show, not, class Ord) import Gargantext.Prelude (Unit, bind, const, discard, pure, show, ($), (<<<), (<>), read, map, class Read, class Show, not, class Ord)
import Gargantext.Types (ID) import Gargantext.Types (ID, Name)
import Gargantext.Utils (toggleSet) import Gargantext.Utils (toggleSet)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -67,31 +67,42 @@ textInputBox p@{ boxName, boxAction, dispatch, isOpen: (true /\ setIsOpen) } = R ...@@ -67,31 +67,42 @@ textInputBox p@{ boxName, boxAction, dispatch, isOpen: (true /\ setIsOpen) } = R
, cancelBtn , cancelBtn
] ]
where where
textInput (_ /\ setRenameNodeName) = textInput (newName /\ setNewName) =
H.div {className: "col-md-8"} H.div {className: "col-md-8"}
[ H.input { type: "text" [
, placeholder: (boxName <> " Node") inputWithEnter {
, defaultValue: text onEnter: submit newName
, className: "form-control" , onValueChanged: setNewName <<< const
, onInput: mkEffectFn1 $ setRenameNodeName , autoFocus: false
<<< const , className: "form-control"
<<< R2.unsafeEventValue , defaultValue: text
} , placeholder: (boxName <> " Node")
, type: "text"
}
-- [ H.input { type: "text"
-- , placeholder: (boxName <> " Node")
-- , defaultValue: text
-- , className: "form-control"
-- , on: { input: setRenameNodeName
-- <<< const
-- <<< R2.unsafeEventValue }
-- }
] ]
submitBtn (newName /\ _) = submitBtn (newName /\ _) =
H.a {className: "btn glyphitem glyphicon glyphicon-ok col-md-2 pull-left" H.a {className: "btn glyphitem glyphicon glyphicon-ok col-md-2 pull-left"
, type: "button" , type: "button"
, onClick: mkEffectFn1 $ \_ -> do , on: { click: submit newName }
setIsOpen $ const false
launchAff $ dispatch ( boxAction newName )
, title: "Submit" , title: "Submit"
} [] } []
cancelBtn = cancelBtn =
H.a {className: "btn text-danger glyphitem glyphicon glyphicon-remove col-md-2 pull-left" H.a {className: "btn text-danger glyphitem glyphicon glyphicon-remove col-md-2 pull-left"
, type: "button" , type: "button"
, onClick: mkEffectFn1 $ \_ -> setIsOpen $ const false , on: { click: \_ -> setIsOpen $ const false }
, title: "Cancel" , title: "Cancel"
} [] } []
submit newName _ = do
setIsOpen $ const false
launchAff_ $ dispatch ( boxAction newName )
textInputBox p@{ boxName, isOpen: (false /\ _) } = R.createElement el p [] textInputBox p@{ boxName, isOpen: (false /\ _) } = R.createElement el p []
where where
el = R.hooksComponent (boxName <> "Box") cpt el = R.hooksComponent (boxName <> "Box") cpt
...@@ -119,10 +130,9 @@ formEdit defaultValue setter = ...@@ -119,10 +130,9 @@ formEdit defaultValue setter =
, placeholder : defaultValue , placeholder : defaultValue
, defaultValue: "Write" <> defaultValue , defaultValue: "Write" <> defaultValue
, className : "form-control" , className : "form-control"
, onInput : mkEffectFn1 , on: { input: \_ -> setter
$ setter <<< const
<<< const <<< R2.unsafeEventValue }
<<< R2.unsafeEventValue
} }
] ]
...@@ -154,12 +164,11 @@ formChoice :: forall a b c d ...@@ -154,12 +164,11 @@ formChoice :: forall a b c d
formChoice nodeTypes defaultNodeType setNodeType = formChoice nodeTypes defaultNodeType setNodeType =
H.div { className: "form-group"} H.div { className: "form-group"}
[ R2.select { className: "form-control" [ R2.select { className: "form-control"
, onChange : mkEffectFn1 , on: { change: \_ -> setNodeType
$ setNodeType <<< const
<<< const <<< fromMaybe defaultNodeType
<<< fromMaybe defaultNodeType <<< read
<<< read <<< R2.unsafeEventValue }
<<< R2.unsafeEventValue
} }
(map (\opt -> H.option {} [ H.text $ show opt ]) nodeTypes) (map (\opt -> H.option {} [ H.text $ show opt ]) nodeTypes)
] ]
...@@ -180,8 +189,7 @@ formButton nodeType setNodeType = ...@@ -180,8 +189,7 @@ formButton nodeType setNodeType =
, type : "button" , type : "button"
, title: "Form Button" , title: "Form Button"
, style : { width: "100%" } , style : { width: "100%" }
, onClick : mkEffectFn1 , on: { click: \_ -> setNodeType ( const nodeType ) }
$ \_ -> setNodeType ( const nodeType )
} [H.text $ "Confirmation"] } [H.text $ "Confirmation"]
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
module Gargantext.Components.InputWithEnter where
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
type Props a = (
onEnter :: Unit -> Effect Unit
, onValueChanged :: String -> Effect Unit
, autoFocus :: Boolean
, className :: String
, defaultValue :: String
, placeholder :: String
, type :: String
)
inputWithEnter :: forall a. Record (Props a) -> R.Element
inputWithEnter props = R.createElement inputWithEnterCpt props []
inputWithEnterCpt :: forall a. R.Component (Props a)
inputWithEnterCpt = R.hooksComponent "G.C.IWE.inputWithEnter" cpt
where
cpt props@{ onEnter, onValueChanged
, autoFocus, className, defaultValue, placeholder } _ = do
pure $ H.input { on: { input: onInput
, keyPress: onKeyPress }
, autoFocus
, className
, defaultValue
, placeholder
, type: props.type }
where
onInput e = do
onValueChanged $ R2.unsafeEventValue e
onKeyPress e = do
char <- R2.keyCode e
if char == 13 then
onEnter unit
else
pure unit
...@@ -12,18 +12,19 @@ import Data.Tuple.Nested ((/\)) ...@@ -12,18 +12,19 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff_) import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs as Tabs import Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs as Tabs
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (Contact(..), ContactData, ContactTouch(..), ContactWhere(..), ContactWho(..), HyperdataContact(..), HyperdataUser(..), _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role, _shared, _touch, _who, defaultContactTouch, defaultContactWhere, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser) import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (Contact(..), ContactData, ContactTouch(..), ContactWhere(..), ContactWho(..), HyperdataContact(..), HyperdataUser(..), _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role, _shared, _touch, _who, defaultContactTouch, defaultContactWhere, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser)
import Gargantext.Ends (Frontends) import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Unit, bind, const, discard, pure, show, unit, ($), (+), (<$>), (<<<), (<>), (==)) import Gargantext.Prelude (Unit, bind, const, discard, pure, show, unit, ($), (+), (<$>), (<<<), (<>), (==))
import Gargantext.Routes as Routes import Gargantext.Routes as Routes
import Gargantext.Ends (Frontends)
import Gargantext.Sessions (Session, get, put, sessionId) import Gargantext.Sessions (Session, get, put, sessionId)
import Gargantext.Types (NodeType(..)) import Gargantext.Types (NodeType(..))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
display :: String -> Array R.Element -> R.Element display :: String -> Array R.Element -> R.Element
display title elems = display title elems =
...@@ -109,11 +110,15 @@ contactInfoItemCpt = R.hooksComponent "G.C.N.A.U.C.contactInfoItem" cpt ...@@ -109,11 +110,15 @@ contactInfoItemCpt = R.hooksComponent "G.C.N.A.U.C.contactInfoItem" cpt
onClick _ = setIsEditing $ const true onClick _ = setIsEditing $ const true
item (true /\ setIsEditing) valueRef = item (true /\ setIsEditing) valueRef =
H.span {} [ H.span {} [
H.input { autoFocus: true inputWithEnter {
, className: "form-control" onEnter: onClick
, defaultValue: R.readRef valueRef , onValueChanged: R.setRef valueRef
, on: {change: \e -> R.setRef valueRef $ R2.unsafeEventValue e} , autoFocus: true
, placeholder } , className: "form-control"
, defaultValue: R.readRef valueRef
, placeholder
, type: "text"
}
, H.span { className: "fa fa-floppy-o" , H.span { className: "fa fa-floppy-o"
, on: {click: onClick} } [] , on: {click: onClick} } []
] ]
......
...@@ -19,6 +19,7 @@ import Reactix.DOM.HTML as H ...@@ -19,6 +19,7 @@ import Reactix.DOM.HTML as H
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Components.CodeEditor as CE import Gargantext.Components.CodeEditor as CE
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Node (NodePoly(..), HyperdataList) import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Nodes.Corpus.Types (CorpusData, FTField, Field(..), FieldType(..), Hash, Hyperdata(..), defaultField, defaultHaskell', defaultPython', defaultJSON', defaultMarkdown') import Gargantext.Components.Nodes.Corpus.Types (CorpusData, FTField, Field(..), FieldType(..), Hash, Hyperdata(..), defaultField, defaultHaskell', defaultPython', defaultJSON', defaultMarkdown')
import Gargantext.Data.Array as GDA import Gargantext.Data.Array as GDA
...@@ -278,7 +279,7 @@ renameableCpt = R.hooksComponent "G.C.N.C.renameableCpt" cpt ...@@ -278,7 +279,7 @@ renameableCpt = R.hooksComponent "G.C.N.C.renameableCpt" cpt
snd state $ const text snd state $ const text
pure $ H.div { className: "renameable" } [ pure $ H.div { className: "renameable" } [
renameableText {isEditing, onRename, state} renameableText { isEditing, onRename, state }
] ]
type RenameableTextProps = type RenameableTextProps =
...@@ -304,17 +305,24 @@ renameableTextCpt = R.hooksComponent "G.C.N.C.renameableTextCpt" cpt ...@@ -304,17 +305,24 @@ renameableTextCpt = R.hooksComponent "G.C.N.C.renameableTextCpt" cpt
] ]
cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do
pure $ H.div {} [ pure $ H.div {} [
H.input { defaultValue: text inputWithEnter {
, className: "form-control text" onEnter: submit
, on: { change: \e -> setText $ const $ R2.unsafeEventValue e } } , onValueChanged: setText <<< const
, autoFocus: false
, className: "form-control text"
, defaultValue: text
, placeholder: ""
, type: "text"
}
, H.span { className: "btn btn-default" , H.span { className: "btn btn-default"
, on: { click: \_ -> do , on: { click: submit } } [
setIsEditing $ const false
onRename text
} } [
H.span { className: "fa fa-floppy-o" } [] H.span { className: "fa fa-floppy-o" } []
] ]
] ]
where
submit _ = do
setIsEditing $ const false
onRename text
fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element
fieldCodeEditor props = R.createElement fieldCodeEditorCpt props [] fieldCodeEditor props = R.createElement fieldCodeEditorCpt props []
......
...@@ -28,3 +28,8 @@ exports._getSelection = getSelection; ...@@ -28,3 +28,8 @@ exports._getSelection = getSelection;
exports._stringify = stringify; exports._stringify = stringify;
exports._postMessage = postMessage; exports._postMessage = postMessage;
exports._setCookie = setCookie; exports._setCookie = setCookie;
exports._keyCode = function(e) {
// https://www.w3schools.com/jsref/event_key_keycode.asp
return e.which || e.keyCode;
}
...@@ -112,11 +112,17 @@ menu :: ElemFactory ...@@ -112,11 +112,17 @@ menu :: ElemFactory
menu = createDOM "menu" menu = createDOM "menu"
effToggler :: forall e. R.State Boolean -> EffectFn1 e Unit effToggler :: forall e. R.State Boolean -> EffectFn1 e Unit
effToggler (value /\ setValue) = mkEffectFn1 $ \e -> setValue $ const $ not value effToggler (value /\ setValue) = mkEffectFn1 $ \_ -> setValue $ const $ not value
unsafeEventValue :: forall event. event -> String unsafeEventValue :: forall event. event -> String
unsafeEventValue e = (unsafeCoerce e).target.value unsafeEventValue e = (unsafeCoerce e).target.value
keyCode :: forall event. event -> Effect Int
keyCode = runEffectFn1 _keyCode
foreign import _keyCode
:: forall e. EffectFn1 e Int
nullRef :: forall t. R.Hooks (R.Ref (Nullable t)) nullRef :: forall t. R.Hooks (R.Ref (Nullable t))
nullRef = R.useRef null nullRef = R.useRef null
......
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