Commit 2c5f796d authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge branch 'dev-markdown' into dev

parents 95101b7f e5a045a8
......@@ -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
......@@ -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