Commit c3bba506 authored by Alexandre Delanoë's avatar Alexandre Delanoë

[FIX] merge.

parents 6fe64380 4c9ce917
......@@ -3336,4 +3336,4 @@
"repo": "https://github.com/paf31/purescript-yargs.git",
"version": "v4.0.0"
}
}
}
\ No newline at end of file
......@@ -24,6 +24,7 @@
.code-editor .editor .code-area {
flex-grow: 1;
max-height: 200px;
min-width: 25%;
overflow: auto;
}
.code-editor .editor .code-area .code-container {
......
......@@ -41,6 +41,7 @@
.code-area
flex-grow: 1
max-height: 200px
min-width: 25%
overflow: auto
.code-container
background-color: #fafafa
......
module Gargantext.Components.CodeEditor where
import DOM.Simple.Types (Element)
import Data.Argonaut.Parser (jsonParser)
import Data.Either (either, Either(..))
import Data.Generic.Rep (class Generic)
......@@ -8,11 +9,10 @@ import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe)
import Data.String.Utils (endsWith)
import Data.Tuple (fst)
import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\))
import DOM.Simple.Types (Element)
import Effect (Effect)
import FFI.Simple ((.=), delay)
import FFI.Simple ((.=))
import Reactix as R
import Reactix.DOM.HTML as H
import Text.Markdown.SlamDown.Parser (parseMd)
......@@ -99,17 +99,10 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
cpt {code, defaultCodeType, onChange} _ = do
controls <- initControls code defaultCodeType
-- Initial rendering of elements with given data
-- Note: delay is necessary here, otherwise initially the HTML won't get
-- rendered (DOM Element refs are still null)
R.useEffectOnce $ delay unit $ \_ -> do
_ <- renderHtml code controls
pure $ pure unit
R.useEffectOnce $ delay unit $ \_ -> do
_ <- setCodeOverlay controls code
pure $ pure unit
R.useEffect2' (fst controls.codeS) (fst controls.codeType) $ do
let code' = fst controls.codeS
setCodeOverlay controls code'
renderHtml code' controls
pure $ H.div { className: "code-editor" } [
toolbar {controls, onChange}
......@@ -127,7 +120,7 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
-- , contentEditable: "true"
, ref: controls.codeOverlayElRef
, rows: 30
--, on: { input: onEditChange (fst codeType) codeElRef htmlRef editorCodeRef error }
--, on: { input: onEditChange (fst codeType) codeElRef htmlRef codeRef error }
} []
]
]
......@@ -158,11 +151,9 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
previewHidden _ = " hidden"
onEditChange :: forall e. Record Controls -> (CodeType -> Code -> Effect Unit) -> e -> Effect Unit
onEditChange controls@{codeElRef, codeOverlayElRef, codeType: (codeType /\ _), editorCodeRef} onChange e = do
onEditChange controls@{codeElRef, codeOverlayElRef, codeType: (codeType /\ _), codeS} onChange e = do
let code = R2.unsafeEventValue e
R.setRef editorCodeRef code
setCodeOverlay controls code
renderHtml (R.readRef controls.editorCodeRef) controls
snd codeS $ const code
onChange codeType code
setCodeOverlay :: Record Controls -> Code -> Effect Unit
......@@ -214,11 +205,9 @@ toolbarCpt = R.hooksComponent "G.C.CE.toolbar" cpt
-- Handle rerendering of preview when viewType changed
onChangeCodeType :: forall e. Record ToolbarProps -> e -> Effect Unit
onChangeCodeType {controls, onChange} _ = do
setCodeOverlay controls code
renderHtml code controls
onChange (fst controls.codeType) code
where
code = R.readRef controls.editorCodeRef
code = fst controls.codeS
type ErrorComponentProps =
......@@ -310,9 +299,9 @@ viewTypeSelectorCpt = R.hooksComponent "G.C.CE.ViewTypeSelector" cpt
type Controls =
(
codeElRef :: R.Ref (Nullable Element)
, codeS :: R.State Code
, codeType :: R.State CodeType
, codeOverlayElRef :: R.Ref (Nullable Element)
, editorCodeRef :: R.Ref Code
, error :: R.State (Maybe Error)
, htmlElRef :: R.Ref (Nullable Element)
, viewType :: R.State ViewType
......@@ -321,19 +310,25 @@ type Controls =
initControls :: Code -> CodeType -> R.Hooks (Record Controls)
initControls code defaultCodeType = do
htmlElRef <- R.useRef null
codeS <- R.useState' code
codeElRef <- R.useRef null
codeOverlayElRef <- R.useRef null
codeType <- R.useState' defaultCodeType
editorCodeRef <- R.useRef code
error <- R.useState' Nothing
viewType <- R.useState' Both
pure $ {
codeElRef
, codeS
, codeType
, codeOverlayElRef
, editorCodeRef
, error
, htmlElRef
, viewType
}
reinitControls :: Record Controls -> Code -> CodeType -> Effect Unit
reinitControls c@{codeType, codeS, error} code defaultCodeType = do
snd codeType $ const defaultCodeType
snd codeS $ const code
snd error $ const Nothing
......@@ -9,6 +9,7 @@ import Data.Set as Set
import Data.Tuple (fst)
import Data.Tuple.Nested ((/\))
import Gargantext.Components.Forest.Tree (treeView)
import Gargantext.Components.Forest.Tree.Node.Action (Reload)
import Gargantext.Components.Login.Types (TreeId)
import Gargantext.Ends (Frontends)
import Gargantext.Routes (AppRoute)
......@@ -30,21 +31,18 @@ forest props = R.createElement forestCpt props []
forestCpt :: R.Component Props
forestCpt = R.hooksComponent "G.C.Forest.forest" cpt where
cpt {frontends, route, sessions, showLogin } _ = do
-- NOTE: this is a hack to reload the tree view on demand
reload <- R.useState' (0 :: Reload)
openNodes <- R2.useLocalStorageState R2.openNodesKey (Set.empty :: Set TreeId)
reload <- R.useState' (0 :: Int)
R2.useCache (frontends /\ route /\ sessions /\ fst openNodes) (cpt' reload openNodes showLogin)
cpt' reload openNodes showLogin (frontends /\ route /\ sessions /\ openNodesState) = do
R2.useCache
(frontends /\ route /\ sessions /\ fst openNodes /\ fst reload)
(cpt' openNodes reload showLogin)
cpt' openNodes reload showLogin (frontends /\ route /\ sessions /\ _ /\ _) = do
pure $ R.fragment $ A.cons (plus showLogin) trees
where
trees = tree <$> unSessions sessions
tree s@(Session {treeId}) =
treeView { root: treeId
, frontends
, mCurrentRoute: Just route
, session: s
, openNodes
, reload
}
treeView { root: treeId, frontends, mCurrentRoute: Just route, session: s, openNodes, reload }
plus :: R2.Setter Boolean -> R.Element
plus showLogin =
......
......@@ -31,7 +31,7 @@ type Props = ( root :: ID
, session :: Session
, frontends :: Frontends
, openNodes :: R.State (Set TreeId)
, reload :: R.State Int
, reload :: R.State Reload
)
treeView :: Record Props -> R.Element
......@@ -40,9 +40,7 @@ treeView props = R.createElement treeViewCpt props []
treeViewCpt :: R.Component Props
treeViewCpt = R.hooksComponent "G.C.Tree.treeView" cpt
where
cpt { root, mCurrentRoute, session, frontends, openNodes } _children = do
-- NOTE: this is a hack to reload the tree view on demand
reload <- R.useState' (0 :: Reload)
cpt { root, mCurrentRoute, session, frontends, openNodes, reload } _children = do
pure $ treeLoadView
{ root, mCurrentRoute, session, frontends, openNodes, reload }
......@@ -69,7 +67,7 @@ type TreeViewProps = ( tree :: FTree
, frontends :: Frontends
, session :: Session
, openNodes :: R.State (Set TreeId)
, reload :: R.State Reload
, reload :: R.State Reload
)
......@@ -96,7 +94,7 @@ toHtml :: R.State Reload
toHtml reload treeState@(ts@{tree: (NTree (LNode {id, name, nodeType}) ary), asyncTasks} /\ setTreeState) session frontends mCurrentRoute openNodes = R.createElement el {} []
where
el = R.hooksComponent "NodeView" cpt
pAction = performAction session reload treeState
pAction = performAction session reload openNodes treeState
cpt props _ = do
let folderIsOpen = Set.member id (fst openNodes)
......@@ -148,26 +146,50 @@ childNodes session frontends reload (true /\ _) mCurrentRoute openNodes ary =
performAction :: Session
-> R.State Int
-> R.State (Set TreeId)
-> R.State Tree
-> Action
-> Aff Unit
-- <<<<<<< HEAD
{-
performAction session (_ /\ setReload) (s@{tree: NTree (LNode {id}) _} /\ setTree) (CreateSubmit name nodeType) = do
void $ createNode session id $ CreateValue {name, nodeType}
liftEffect $ setReload (_ + 1)
performAction session (_ /\ setReload) (s@{tree: NTree (LNode {id}) _} /\ setTree) DeleteNode = do
-}
-- performAction session (_ /\ setReload) (s@{tree: NTree (LNode {id}) _} /\ setTree) DeleteNode = do
-- =======
performAction session (_ /\ setReload) (_ /\ setOpenNodes) (s@{tree: NTree (LNode {id}) _} /\ setTree) DeleteNode = do
-- >>>>>>> dev
void $ deleteNode session id
liftEffect $ setReload (_ + 1)
liftEffect do
setOpenNodes (Set.delete id)
setReload (_ + 1)
performAction session _ ({tree: NTree (LNode {id}) _} /\ setTree) (SearchQuery task) = do
-- <<<<<<< HEAD
performAction session (_ /\ setReload) _ ({tree: NTree (LNode {id}) _} /\ setTree) (SearchQuery task) = do
liftEffect $ setTree $ \t@{asyncTasks} -> t { asyncTasks = A.cons task asyncTasks }
liftEffect $ log2 "[performAction] SearchQuery task:" task
liftEffect $ setReload (_ + 1)
{-
performAction session _ ({tree: NTree (LNode {id}) _} /\ setTree) (Submit name) = do
void $ renameNode session id $ RenameValue {name}
liftEffect $ setTree $ \s@{tree: NTree (LNode node) arr} -> s {tree = NTree (LNode node {name = name}) arr}
-- =======
--}
performAction session _ _ ({tree: NTree (LNode {id}) _} /\ setTree) (Submit name) = do
void $ renameNode session id $ RenameValue {name}
liftEffect $ setTree $ \s@{tree: NTree (LNode node) arr} -> s {tree = NTree (LNode node {name = name}) arr}
performAction session (_ /\ setReload) (_ /\ setOpenNodes) (s@{tree: NTree (LNode {id}) _} /\ setTree) (CreateSubmit name nodeType) = do
void $ createNode session id $ CreateValue {name, nodeType}
liftEffect do
setOpenNodes (Set.insert id)
setReload (_ + 1)
performAction session _ ({tree: NTree (LNode {id}) _} /\ setTree) (UploadFile fileType contents) = do
-- performAction session _ ({tree: NTree (LNode {id}) _} /\ setTree) (UploadFile fileType contents) = do
performAction session _ _ ({tree: NTree (LNode {id}) _} /\ setTree) (UploadFile fileType contents) = do
-- >>>>>>> dev
task <- uploadFile session id fileType contents
liftEffect $ setTree $ \t@{asyncTasks} -> t { asyncTasks = A.cons task asyncTasks }
liftEffect $ log2 "uploaded, task:" task
......@@ -6,7 +6,7 @@ import Data.Array as A
import Data.Either (Either(..))
import Data.List as List
import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..), fst)
import Data.Tuple (Tuple(..), fst, snd)
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Effect (Effect)
......@@ -69,6 +69,15 @@ corpusLayoutViewCpt = R.hooksComponent "G.C.N.C.corpusLayoutView" cpt
cpt {corpus: (NodePoly {hyperdata: Hyperdata {fields}}), nodeId, reload, session} _ = do
let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields
fieldsS <- R.useState' fieldsWithIndex
fieldsRef <- R.useRef fields
-- handle props change of fields
R.useEffect1' fields $ do
if R.readRef fieldsRef == fields then
pure unit
else do
R.setRef fieldsRef fields
snd fieldsS $ const fieldsWithIndex
pure $ H.div {} [
H.div { className: "row" } [
......@@ -122,19 +131,22 @@ fieldsCodeEditorCpt :: R.Component FieldsCodeEditorProps
fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt
where
cpt {nodeId, fields: fS@(fields /\ _), session} _ = do
pure $ H.div {} $ List.toUnfoldable editors
masterKey <- R.useState' 0
pure $ H.div {} $ List.toUnfoldable (editors masterKey)
where
editors = (\idxField@(Tuple idx field) ->
fieldCodeEditorWrapper { canMoveDown: idx < (List.length fields - 1)
, canMoveUp: idx > 0
, field
, hash: hash idxField
, onChange: onChange fS idx
, onMoveDown: onMoveDown fS idx
, onMoveUp: onMoveUp fS idx
, onRemove: onRemove fS idx
, onRename: onRename fS idx
}) <$> fields
editors masterKey =
(\(Tuple idx field) ->
fieldCodeEditorWrapper { canMoveDown: idx < (List.length fields - 1)
, canMoveUp: idx > 0
, field
, key: (show $ fst masterKey) <> "-" <> (show idx)
, onChange: onChange fS idx
, onMoveDown: onMoveDown masterKey fS idx
, onMoveUp: onMoveUp masterKey fS idx
, onRemove: onRemove fS idx
, onRename: onRename fS idx
}) <$> fields
onChange :: R.State FTFieldsWithIndex -> Index -> FieldType -> Effect Unit
onChange (_ /\ setFields) idx typ = do
......@@ -143,12 +155,14 @@ fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt
Nothing -> fields
Just newFields -> newFields
onMoveDown :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveDown (fs /\ setFields) idx _ = do
onMoveDown :: R.State Int -> R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveDown (_ /\ setMasterKey) (fs /\ setFields) idx _ = do
setMasterKey $ (+) 1
setFields $ recomputeIndices <<< (GDA.swapList idx (idx + 1))
onMoveUp :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveUp (_ /\ setFields) idx _ = do
onMoveUp :: R.State Int -> R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveUp (_ /\ setMasterKey) (_ /\ setFields) idx _ = do
setMasterKey $ (+) 1
setFields $ recomputeIndices <<< (GDA.swapList idx (idx - 1))
onRemove :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
......@@ -176,7 +190,7 @@ type FieldCodeEditorProps =
canMoveDown :: Boolean
, canMoveUp :: Boolean
, field :: FTField
, hash :: Hash
, key :: String
, onChange :: FieldType -> Effect Unit
, onMoveDown :: Unit -> Effect Unit
, onMoveUp :: Unit -> Effect Unit
......@@ -190,8 +204,8 @@ fieldCodeEditorWrapper props = R.createElement fieldCodeEditorWrapperCpt props [
fieldCodeEditorWrapperCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorWrapperCpt = R.hooksComponent "G.C.N.C.fieldCodeEditorWrapperCpt" cpt
where
cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, hash, onMoveDown, onMoveUp, onRemove, onRename} _ = do
pure $ H.div { className: "row panel panel-default hash-" <> hash } [
cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, onMoveDown, onMoveUp, onRemove, onRename} _ = do
pure $ H.div { className: "row panel panel-default" } [
H.div { className: "panel-heading" } [
H.div { className: "code-editor-heading" } [
renameable {onRename, text: name}
......@@ -241,30 +255,53 @@ renameableCpt = R.hooksComponent "G.C.N.C.renameableCpt" cpt
cpt {onRename, text} _ = do
isEditing <- R.useState' false
state <- R.useState' text
textRef <- R.useRef text
-- handle props change of text
R.useEffect1' text $ do
if R.readRef textRef == text then
pure unit
else do
R.setRef textRef text
snd state $ const text
pure $ H.div { className: "renameable" } [
textCpt isEditing state
renameableText {isEditing, onRename, state}
]
where
textCpt :: R.State Boolean -> R.State String -> R.Element
textCpt (false /\ setIsEditing) (text /\ _) = H.div {} [
H.span { className: "text" } [ H.text text ]
, H.span { className: "btn btn-default"
, on: { click: \_ -> setIsEditing $ const true } } [
H.span { className: "glyphicon glyphicon-pencil" } []
]
type RenameableTextProps =
(
isEditing :: R.State Boolean
, onRename :: String -> Effect Unit
, state :: R.State String
)
renameableText :: Record RenameableTextProps -> R.Element
renameableText props = R.createElement renameableTextCpt props []
renameableTextCpt :: R.Component RenameableTextProps
renameableTextCpt = R.hooksComponent "G.C.N.C.renameableTextCpt" cpt
where
cpt {isEditing: (false /\ setIsEditing), state: (text /\ _)} _ = do
pure $ H.div {} [
H.span { className: "text" } [ H.text text ]
, H.span { className: "btn btn-default"
, on: { click: \_ -> setIsEditing $ const true } } [
H.span { className: "glyphicon glyphicon-pencil" } []
]
]
textCpt (true /\ setIsEditing) (text /\ setText) = H.div {} [
H.input { defaultValue: text
, className: "form-control text"
, on: { change: \e -> setText $ const $ R2.unsafeEventValue e } }
, H.span { className: "btn btn-default"
, on: { click: \_ -> do
setIsEditing $ const false
onRename text
} } [
H.span { className: "glyphicon glyphicon-floppy-disk" } []
]
cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do
pure $ H.div {} [
H.input { defaultValue: text
, className: "form-control text"
, on: { change: \e -> setText $ const $ R2.unsafeEventValue e } }
, H.span { className: "btn btn-default"
, on: { click: \_ -> do
setIsEditing $ const false
onRename text
} } [
H.span { className: "glyphicon glyphicon-floppy-disk" } []
]
]
fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element
......
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