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

Merge branch 'dev-markdown' into dev

parents 95101b7f e5a045a8
...@@ -3336,4 +3336,4 @@ ...@@ -3336,4 +3336,4 @@
"repo": "https://github.com/paf31/purescript-yargs.git", "repo": "https://github.com/paf31/purescript-yargs.git",
"version": "v4.0.0" "version": "v4.0.0"
} }
} }
\ No newline at end of file
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
.code-editor .editor .code-area { .code-editor .editor .code-area {
flex-grow: 1; flex-grow: 1;
max-height: 200px; max-height: 200px;
min-width: 25%;
overflow: auto; overflow: auto;
} }
.code-editor .editor .code-area .code-container { .code-editor .editor .code-area .code-container {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
.code-area .code-area
flex-grow: 1 flex-grow: 1
max-height: 200px max-height: 200px
min-width: 25%
overflow: auto overflow: auto
.code-container .code-container
background-color: #fafafa background-color: #fafafa
......
module Gargantext.Components.CodeEditor where module Gargantext.Components.CodeEditor where
import DOM.Simple.Types (Element)
import Data.Argonaut.Parser (jsonParser) import Data.Argonaut.Parser (jsonParser)
import Data.Either (either, Either(..)) import Data.Either (either, Either(..))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
...@@ -8,11 +9,10 @@ import Data.Generic.Rep.Show (genericShow) ...@@ -8,11 +9,10 @@ import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe) import Data.Nullable (Nullable, null, toMaybe)
import Data.String.Utils (endsWith) import Data.String.Utils (endsWith)
import Data.Tuple (fst) import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import DOM.Simple.Types (Element)
import Effect (Effect) import Effect (Effect)
import FFI.Simple ((.=), delay) import FFI.Simple ((.=))
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Text.Markdown.SlamDown.Parser (parseMd) import Text.Markdown.SlamDown.Parser (parseMd)
...@@ -99,17 +99,10 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt ...@@ -99,17 +99,10 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
cpt {code, defaultCodeType, onChange} _ = do cpt {code, defaultCodeType, onChange} _ = do
controls <- initControls code defaultCodeType controls <- initControls code defaultCodeType
-- Initial rendering of elements with given data R.useEffect2' (fst controls.codeS) (fst controls.codeType) $ do
let code' = fst controls.codeS
-- Note: delay is necessary here, otherwise initially the HTML won't get setCodeOverlay controls code'
-- rendered (DOM Element refs are still null) renderHtml code' controls
R.useEffectOnce $ delay unit $ \_ -> do
_ <- renderHtml code controls
pure $ pure unit
R.useEffectOnce $ delay unit $ \_ -> do
_ <- setCodeOverlay controls code
pure $ pure unit
pure $ H.div { className: "code-editor" } [ pure $ H.div { className: "code-editor" } [
toolbar {controls, onChange} toolbar {controls, onChange}
...@@ -127,7 +120,7 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt ...@@ -127,7 +120,7 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
-- , contentEditable: "true" -- , contentEditable: "true"
, ref: controls.codeOverlayElRef , ref: controls.codeOverlayElRef
, rows: 30 , 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 ...@@ -158,11 +151,9 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
previewHidden _ = " hidden" previewHidden _ = " hidden"
onEditChange :: forall e. Record Controls -> (CodeType -> Code -> Effect Unit) -> e -> Effect Unit 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 let code = R2.unsafeEventValue e
R.setRef editorCodeRef code snd codeS $ const code
setCodeOverlay controls code
renderHtml (R.readRef controls.editorCodeRef) controls
onChange codeType code onChange codeType code
setCodeOverlay :: Record Controls -> Code -> Effect Unit setCodeOverlay :: Record Controls -> Code -> Effect Unit
...@@ -214,11 +205,9 @@ toolbarCpt = R.hooksComponent "G.C.CE.toolbar" cpt ...@@ -214,11 +205,9 @@ toolbarCpt = R.hooksComponent "G.C.CE.toolbar" cpt
-- Handle rerendering of preview when viewType changed -- Handle rerendering of preview when viewType changed
onChangeCodeType :: forall e. Record ToolbarProps -> e -> Effect Unit onChangeCodeType :: forall e. Record ToolbarProps -> e -> Effect Unit
onChangeCodeType {controls, onChange} _ = do onChangeCodeType {controls, onChange} _ = do
setCodeOverlay controls code
renderHtml code controls
onChange (fst controls.codeType) code onChange (fst controls.codeType) code
where where
code = R.readRef controls.editorCodeRef code = fst controls.codeS
type ErrorComponentProps = type ErrorComponentProps =
...@@ -310,9 +299,9 @@ viewTypeSelectorCpt = R.hooksComponent "G.C.CE.ViewTypeSelector" cpt ...@@ -310,9 +299,9 @@ viewTypeSelectorCpt = R.hooksComponent "G.C.CE.ViewTypeSelector" cpt
type Controls = type Controls =
( (
codeElRef :: R.Ref (Nullable Element) codeElRef :: R.Ref (Nullable Element)
, codeS :: R.State Code
, codeType :: R.State CodeType , codeType :: R.State CodeType
, codeOverlayElRef :: R.Ref (Nullable Element) , codeOverlayElRef :: R.Ref (Nullable Element)
, editorCodeRef :: R.Ref Code
, error :: R.State (Maybe Error) , error :: R.State (Maybe Error)
, htmlElRef :: R.Ref (Nullable Element) , htmlElRef :: R.Ref (Nullable Element)
, viewType :: R.State ViewType , viewType :: R.State ViewType
...@@ -321,19 +310,25 @@ type Controls = ...@@ -321,19 +310,25 @@ type Controls =
initControls :: Code -> CodeType -> R.Hooks (Record Controls) initControls :: Code -> CodeType -> R.Hooks (Record Controls)
initControls code defaultCodeType = do initControls code defaultCodeType = do
htmlElRef <- R.useRef null htmlElRef <- R.useRef null
codeS <- R.useState' code
codeElRef <- R.useRef null codeElRef <- R.useRef null
codeOverlayElRef <- R.useRef null codeOverlayElRef <- R.useRef null
codeType <- R.useState' defaultCodeType codeType <- R.useState' defaultCodeType
editorCodeRef <- R.useRef code
error <- R.useState' Nothing error <- R.useState' Nothing
viewType <- R.useState' Both viewType <- R.useState' Both
pure $ { pure $ {
codeElRef codeElRef
, codeS
, codeType , codeType
, codeOverlayElRef , codeOverlayElRef
, editorCodeRef
, error , error
, htmlElRef , htmlElRef
, viewType , 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 ...@@ -6,7 +6,7 @@ import Data.Array as A
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.List as List import Data.List as List
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..), fst) import Data.Tuple (Tuple(..), fst, snd)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2) import DOM.Simple.Console (log2)
import Effect (Effect) import Effect (Effect)
...@@ -69,6 +69,15 @@ corpusLayoutViewCpt = R.hooksComponent "G.C.N.C.corpusLayoutView" cpt ...@@ -69,6 +69,15 @@ corpusLayoutViewCpt = R.hooksComponent "G.C.N.C.corpusLayoutView" cpt
cpt {corpus: (NodePoly {hyperdata: Hyperdata {fields}}), nodeId, reload, session} _ = do cpt {corpus: (NodePoly {hyperdata: Hyperdata {fields}}), nodeId, reload, session} _ = do
let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields
fieldsS <- R.useState' fieldsWithIndex 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 {} [ pure $ H.div {} [
H.div { className: "row" } [ H.div { className: "row" } [
...@@ -122,19 +131,22 @@ fieldsCodeEditorCpt :: R.Component FieldsCodeEditorProps ...@@ -122,19 +131,22 @@ fieldsCodeEditorCpt :: R.Component FieldsCodeEditorProps
fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt
where where
cpt {nodeId, fields: fS@(fields /\ _), session} _ = do 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 where
editors = (\idxField@(Tuple idx field) -> editors masterKey =
fieldCodeEditorWrapper { canMoveDown: idx < (List.length fields - 1) (\(Tuple idx field) ->
, canMoveUp: idx > 0 fieldCodeEditorWrapper { canMoveDown: idx < (List.length fields - 1)
, field , canMoveUp: idx > 0
, hash: hash idxField , field
, onChange: onChange fS idx , key: (show $ fst masterKey) <> "-" <> (show idx)
, onMoveDown: onMoveDown fS idx , onChange: onChange fS idx
, onMoveUp: onMoveUp fS idx , onMoveDown: onMoveDown masterKey fS idx
, onRemove: onRemove fS idx , onMoveUp: onMoveUp masterKey fS idx
, onRename: onRename fS idx , onRemove: onRemove fS idx
}) <$> fields , onRename: onRename fS idx
}) <$> fields
onChange :: R.State FTFieldsWithIndex -> Index -> FieldType -> Effect Unit onChange :: R.State FTFieldsWithIndex -> Index -> FieldType -> Effect Unit
onChange (_ /\ setFields) idx typ = do onChange (_ /\ setFields) idx typ = do
...@@ -143,12 +155,14 @@ fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt ...@@ -143,12 +155,14 @@ fieldsCodeEditorCpt = R.hooksComponent "G.C.N.C.fieldsCodeEditorCpt" cpt
Nothing -> fields Nothing -> fields
Just newFields -> newFields Just newFields -> newFields
onMoveDown :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit onMoveDown :: R.State Int -> R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveDown (fs /\ setFields) idx _ = do onMoveDown (_ /\ setMasterKey) (fs /\ setFields) idx _ = do
setMasterKey $ (+) 1
setFields $ recomputeIndices <<< (GDA.swapList idx (idx + 1)) setFields $ recomputeIndices <<< (GDA.swapList idx (idx + 1))
onMoveUp :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit onMoveUp :: R.State Int -> R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
onMoveUp (_ /\ setFields) idx _ = do onMoveUp (_ /\ setMasterKey) (_ /\ setFields) idx _ = do
setMasterKey $ (+) 1
setFields $ recomputeIndices <<< (GDA.swapList idx (idx - 1)) setFields $ recomputeIndices <<< (GDA.swapList idx (idx - 1))
onRemove :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit onRemove :: R.State FTFieldsWithIndex -> Index -> Unit -> Effect Unit
...@@ -176,7 +190,7 @@ type FieldCodeEditorProps = ...@@ -176,7 +190,7 @@ type FieldCodeEditorProps =
canMoveDown :: Boolean canMoveDown :: Boolean
, canMoveUp :: Boolean , canMoveUp :: Boolean
, field :: FTField , field :: FTField
, hash :: Hash , key :: String
, onChange :: FieldType -> Effect Unit , onChange :: FieldType -> Effect Unit
, onMoveDown :: Unit -> Effect Unit , onMoveDown :: Unit -> Effect Unit
, onMoveUp :: Unit -> Effect Unit , onMoveUp :: Unit -> Effect Unit
...@@ -190,8 +204,8 @@ fieldCodeEditorWrapper props = R.createElement fieldCodeEditorWrapperCpt props [ ...@@ -190,8 +204,8 @@ fieldCodeEditorWrapper props = R.createElement fieldCodeEditorWrapperCpt props [
fieldCodeEditorWrapperCpt :: R.Component FieldCodeEditorProps fieldCodeEditorWrapperCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorWrapperCpt = R.hooksComponent "G.C.N.C.fieldCodeEditorWrapperCpt" cpt fieldCodeEditorWrapperCpt = R.hooksComponent "G.C.N.C.fieldCodeEditorWrapperCpt" cpt
where where
cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, hash, onMoveDown, onMoveUp, onRemove, onRename} _ = do cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, onMoveDown, onMoveUp, onRemove, onRename} _ = do
pure $ H.div { className: "row panel panel-default hash-" <> hash } [ pure $ H.div { className: "row panel panel-default" } [
H.div { className: "panel-heading" } [ H.div { className: "panel-heading" } [
H.div { className: "code-editor-heading" } [ H.div { className: "code-editor-heading" } [
renameable {onRename, text: name} renameable {onRename, text: name}
...@@ -241,30 +255,53 @@ renameableCpt = R.hooksComponent "G.C.N.C.renameableCpt" cpt ...@@ -241,30 +255,53 @@ renameableCpt = R.hooksComponent "G.C.N.C.renameableCpt" cpt
cpt {onRename, text} _ = do cpt {onRename, text} _ = do
isEditing <- R.useState' false isEditing <- R.useState' false
state <- R.useState' text 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" } [ pure $ H.div { className: "renameable" } [
textCpt isEditing state renameableText {isEditing, onRename, state}
] ]
where
textCpt :: R.State Boolean -> R.State String -> R.Element type RenameableTextProps =
textCpt (false /\ setIsEditing) (text /\ _) = H.div {} [ (
H.span { className: "text" } [ H.text text ] isEditing :: R.State Boolean
, H.span { className: "btn btn-default" , onRename :: String -> Effect Unit
, on: { click: \_ -> setIsEditing $ const true } } [ , state :: R.State String
H.span { className: "glyphicon glyphicon-pencil" } [] )
]
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 {} [ cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do
H.input { defaultValue: text pure $ H.div {} [
, className: "form-control text" H.input { defaultValue: text
, on: { change: \e -> setText $ const $ R2.unsafeEventValue e } } , className: "form-control text"
, H.span { className: "btn btn-default" , on: { change: \e -> setText $ const $ R2.unsafeEventValue e } }
, on: { click: \_ -> do , H.span { className: "btn btn-default"
setIsEditing $ const false , on: { click: \_ -> do
onRename text setIsEditing $ const false
} } [ onRename text
H.span { className: "glyphicon glyphicon-floppy-disk" } [] } } [
] H.span { className: "glyphicon glyphicon-floppy-disk" } []
]
] ]
fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element 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