Commit 59af3f6f authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[CodeEditor] view type toggle (code/preview/both) + some refactoring

parent a1108e5b
.code-editor {
.code-editor .toolbar {
display: flex;
justify-content: flex-start;
width: 100%;
}
.code-editor .code {
width: 40%;
.code-editor .editor {
display: flex;
width: 100%;
}
.code-editor .editor .code {
flex-grow: 1;
}
.code-editor .code code {
.code-editor .editor .code code {
background-color: #f7f7f9;
color: #000;
display: block;
height: 500px;
}
.code-editor .html {
.code-editor .editor .html {
flex-grow: 2;
margin-left: 25px;
padding-left: 25px;
width: 60%;
}
.code-editor .html ul li {
.code-editor .editor .html ul li {
list-style: disc !important;
}
.code-editor .html ol li {
.code-editor .editor .html ol li {
list-style: decimal !important;
}
/*# sourceMappingURL=MarkdownEditor.css.map */
/*# sourceMappingURL=CodeEditor.css.map */
.code-editor
.toolbar
display: flex
justify-content: flex-start
width: 100%
.editor
display: flex
width: 100%
.code
flex-grow: 1
code
background-color: #f7f7f9
color: #000
display: block
height: 500px
.html
flex-grow: 2
margin-left: 25px
padding-left: 25px
ul
li
list-style: disc !important
ol
li
list-style: decimal !important
.code-editor
display: flex
width: 100%
.code
code
background-color: #f7f7f9
color: #000
display: block
height: 500px
width: 40%
.html
margin-left: 25px
padding-left: 25px
width: 60%
ul
li
list-style: disc !important
ol
li
list-style: decimal !important
......@@ -9,7 +9,9 @@ import DOM.Simple.Console (log, log2)
import DOM.Simple.Types (Element)
import Effect (Effect)
import FFI.Simple ((.=), delay)
import Prelude (($), (>>>), Unit, bind, const, discard, identity, pure, unit)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Reactix as R
import Reactix.DOM.HTML as H
import Text.Markdown.SlamDown.Parser (parseMd)
......@@ -17,9 +19,22 @@ import Text.Markdown.SlamDown.Smolder as MD
import Text.Markdown.SlamDown.Syntax (SlamDownP(..))
import Text.Smolder.Renderer.String (render)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
data CodeType = Markdown
data CodeType = JSON | Markdown
derive instance genericCodeType :: Generic CodeType _
instance eqCodeType :: Eq CodeType where
eq = genericEq
instance showCodeType :: Show CodeType where
show = genericShow
data ViewType = Code | Preview | Both
derive instance genericViewType :: Generic ViewType _
instance eqViewType :: Eq ViewType where
eq = genericEq
instance showViewType :: Show ViewType where
show = genericShow
type Props =
( code :: String
......@@ -27,6 +42,10 @@ type Props =
, onChange :: String -> Effect Unit
)
compile :: CodeType -> String -> String
compile JSON code = code
compile Markdown code = compileMd code
compileMd' :: forall e. MD.ToMarkupOptions e -> String -> String
compileMd' options input =
either identity (MD.toMarkup' options >>> render)
......@@ -45,6 +64,8 @@ codeEditorCpt = R.hooksComponent "G.C.CodeEditor" cpt
htmlRef <- R.useRef null
codeRef <- R.useRef null
editorCodeRef <- R.useRef code
codeTypeS <- R.useState' codeType
viewType <- R.useState' Both
-- Note: delay is necessary here, otherwise initially the HTML won't get
-- rendered (mDiv is still null)
......@@ -53,7 +74,7 @@ codeEditorCpt = R.hooksComponent "G.C.CodeEditor" cpt
case mHtmlEl of
Nothing -> pure $ pure unit
Just htmlEl -> do
_ <- pure $ (htmlEl .= "innerHTML") $ compileMd code
_ <- pure $ (htmlEl .= "innerHTML") $ compile codeType code
pure $ pure unit
R.useEffectOnce $ delay unit $ \_ -> do
......@@ -65,20 +86,39 @@ codeEditorCpt = R.hooksComponent "G.C.CodeEditor" cpt
pure $ pure unit
pure $ H.div { className: "code-editor" } [
H.div { className: "code" } [
H.code { className: ""
, contentEditable: "true"
, ref: codeRef
, rows: 30
, on: { change: onEditChange codeRef htmlRef editorCodeRef
, input: onEditChange codeRef htmlRef editorCodeRef }
} []
H.div { className: "row toolbar" } [
codeTypeSelector {codeType: codeTypeS}
, H.div { className: "btn-group" } [
viewTypeButton {viewType: Code, state: viewType}
, viewTypeButton {viewType: Both, state: viewType}
, viewTypeButton {viewType: Preview, state: viewType}
]
]
, H.div { className: "row editor" } [
H.div { className: "code " <> (codeHidden $ fst viewType) } [
H.code { className: ""
, contentEditable: "true"
, ref: codeRef
, rows: 30
, on: { input: onEditChange codeType codeRef htmlRef editorCodeRef }
} []
]
, H.div { ref: htmlRef, className: "html " <> (previewHidden $ fst viewType) } []
]
]
, H.div { ref: htmlRef, className: "html" } []
]
onEditChange :: forall e. R.Ref (Nullable Element) -> R.Ref (Nullable Element) -> R.Ref String -> e -> Effect Unit
onEditChange codeRef htmlRef editorCodeRef e = do
codeHidden :: ViewType -> String
codeHidden Code = ""
codeHidden Both = ""
codeHidden _ = "hidden"
previewHidden :: ViewType -> String
previewHidden Preview = ""
previewHidden Both = ""
previewHidden _ = "hidden"
onEditChange :: forall e. CodeType -> R.Ref (Nullable Element) -> R.Ref (Nullable Element) -> R.Ref String -> e -> Effect Unit
onEditChange codeType codeRef htmlRef editorCodeRef e = do
log2 "[onChange] e" e
let mCode = toMaybe $ R.readRef codeRef
case mCode of
......@@ -90,6 +130,65 @@ codeEditorCpt = R.hooksComponent "G.C.CodeEditor" cpt
case mHtml of
Nothing -> pure unit
Just html -> do
_ <- pure $ (html .= "innerHTML") $ compileMd $ R.readRef editorCodeRef
_ <- pure $ (html .= "innerHTML") $ compile codeType $ R.readRef editorCodeRef
pure unit
pure unit
type CodeTypeSelectorProps =
(
codeType :: R.State CodeType
)
codeTypeSelector :: Record CodeTypeSelectorProps -> R.Element
codeTypeSelector p = R.createElement codeTypeSelectorCpt p []
codeTypeSelectorCpt :: R.Component CodeTypeSelectorProps
codeTypeSelectorCpt = R.hooksComponent "G.C.CodeTypeSelector" cpt
where
cpt {codeType} _ = do
pure $ R2.select { className: "form-control"
, on: { change: onSelectChange codeType }
, style: { width: "150px" }
, value: show $ fst codeType }
(option <$> [JSON, Markdown])
option :: CodeType -> R.Element
option value = H.option { value: show value } [ H.text $ show value ]
onSelectChange (_ /\ setCodeType) e = do
let codeType = case value of
"JSON" -> JSON
"Markdown" -> Markdown
_ -> Markdown
setCodeType $ const codeType
where
value = R2.unsafeEventValue e
type ViewTypeProps =
(
viewType :: ViewType
, state :: R.State ViewType
)
viewTypeButton :: Record ViewTypeProps -> R.Element
viewTypeButton p = R.createElement viewTypeButtonCpt p []
viewTypeButtonCpt :: R.Component ViewTypeProps
viewTypeButtonCpt = R.hooksComponent "G.C.ViewTypeButton" cpt
where
cpt {viewType, state: (state /\ setState)} _ =
pure $ H.label {
className: "btn btn-default" <> (active viewType state)
, on: { click: onClick viewType setState }
} [
H.i { className: "glyphicon " <> (icon viewType) } []
]
active viewType state = if viewType == state then " active" else ""
icon Preview = "glyphicon-eye-open"
icon Both = "glyphicon-transfer"
icon Code = "glyphicon-pencil"
onClick viewType setState _ = setState $ const viewType
......@@ -9,12 +9,13 @@ import Effect.Aff (Aff, throwError)
import Effect.Exception (error)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Prelude
import Gargantext.Components.CodeEditor as CE
import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Types (NodeType(..), AffTableResult)
import Gargantext.Routes (SessionRoute(NodeAPI, Children))
import Gargantext.Sessions (Session, get)
import Gargantext.Types (NodeType(..), AffTableResult)
type Props = ( nodeId :: Int )
......@@ -22,15 +23,15 @@ corpusLayout :: Record Props -> R.Element
corpusLayout props = R.createElement corpusLayoutCpt props []
corpusLayoutCpt :: R.Component Props
corpusLayoutCpt = R.staticComponent "G.P.Corpus.corpusLayout" cpt
corpusLayoutCpt = R.hooksComponent "G.P.Corpus.corpusLayout" cpt
where
cpt {nodeId} _ =
H.div {}
[
CE.codeEditor {code, codeType: CE.Markdown, onChange}
--H.iframe { src: gargMd , width: "100%", height: "100%", style: {"border-style": "none"}} []
]
gargMd = "https://hackmd.iscpif.fr/g9Aah4iwQtCayIzsKQjA0Q#"
cpt {nodeId} _ = do
pure $ H.div {}
[
CE.codeEditor {code, codeType: CE.Markdown, onChange}
--H.iframe { src: gargMd , width: "100%", height: "100%", style: {"border-style": "none"}} []
]
--gargMd = "https://hackmd.iscpif.fr/g9Aah4iwQtCayIzsKQjA0Q#"
code = "# Hello world\n\n## subtitle\n\n- item 1\n- item 2\n\n1. num 1\n2. num 2\n\n[purescript link](https://purescript.org)"
onChange c = do
log2 "[corpusLayoutCpt] c" c
......
......@@ -13,7 +13,7 @@
<link rel="stylesheet" type="text/css" href="styles/menu.css"/>
<link href="styles/Graph.css" rel="stylesheet" type="text/css" />
<link href="styles/Login.css" rel="stylesheet" type="text/css" />
<link href="styles/MarkdownEditor.css" rel="stylesheet" type="text/css" />
<link href="styles/CodeEditor.css" rel="stylesheet" type="text/css" />
<link href="styles/range-slider.css" rel="stylesheet" type="text/css" />
<style>
* {margin: 0; padding: 0; list-style: none;}
......
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