summaryrefslogtreecommitdiff
path: root/elm
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2019-10-21 14:35:07 +0200
committerYorhel <git@yorhel.nl>2019-10-21 14:35:07 +0200
commit83fdd388e335ed60aa9ec9f47d3110ae8da5aeea (patch)
treeef2130eebcc56134dcd3f8eacc2b91d98f04f133 /elm
parentf7dfacedf5a55596eabe3c30543a2ff2482063b4 (diff)
Elm: Add text preview framework + BBCode preview in forms
Diffstat (limited to 'elm')
-rw-r--r--elm/DocEdit.elm40
-rw-r--r--elm/Lib/Editsum.elm18
-rw-r--r--elm/Lib/TextPreview.elm90
-rw-r--r--elm/StaffEdit/Main.elm21
4 files changed, 120 insertions, 49 deletions
diff --git a/elm/DocEdit.elm b/elm/DocEdit.elm
index 1dcd174c..0d654e59 100644
--- a/elm/DocEdit.elm
+++ b/elm/DocEdit.elm
@@ -7,6 +7,7 @@ import Browser
import Browser.Navigation exposing (load)
import Json.Encode as JE
import Lib.Html exposing (..)
+import Lib.TextPreview as TP
import Lib.Api as Api
import Lib.Ffi as Ffi
import Lib.Editsum as Editsum
@@ -27,30 +28,28 @@ type alias Model =
{ state : Api.State
, editsum : Editsum.Model
, title : String
- , content : String
+ , content : TP.Model
, id : Int
- , preview : String
}
init : GD.Recv -> Model
init d =
{ state = Api.Normal
- , editsum = { authmod = True, editsum = d.editsum, locked = d.locked, hidden = d.hidden }
+ , editsum = { authmod = True, editsum = TP.bbcode d.editsum, locked = d.locked, hidden = d.hidden }
, title = d.title
- , content = d.content
+ , content = TP.markdown d.content
, id = d.id
- , preview = ""
}
encode : Model -> GD.Send
encode model =
- { editsum = model.editsum.editsum
+ { editsum = model.editsum.editsum.data
, hidden = model.editsum.hidden
, locked = model.editsum.locked
, title = model.title
- , content = model.content
+ , content = model.content.data
}
@@ -59,17 +58,15 @@ type Msg
| Submit
| Submitted GApi.Response
| Title String
- | Content String
- | Preview
- | HandlePreview GApi.Response
+ | Content TP.Msg
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
- Editsum e -> ({ model | editsum = Editsum.update e model.editsum }, Cmd.none)
+ Editsum m -> let (nm,nc) = Editsum.update m model.editsum in ({ model | editsum = nm }, Cmd.map Editsum nc)
Title s -> ({ model | title = s }, Cmd.none)
- Content s -> ({ model | content = s }, Cmd.none)
+ Content m -> let (nm,nc) = TP.update m model.content in ({ model | content = nm }, Cmd.map Content nc)
Submit ->
let
@@ -80,16 +77,6 @@ update msg model =
Submitted (GApi.Changed id rev) -> (model, load <| "/d" ++ String.fromInt id ++ "." ++ String.fromInt rev)
Submitted r -> ({ model | state = Api.Error r }, Cmd.none)
- Preview ->
- if model.preview /= "" then ( { model | preview = "" }, Cmd.none )
- else
- ( { model | state = Api.Loading, preview = "" }
- , Api.post "/js/markdown.json" (JE.object [("content", JE.string model.content)]) HandlePreview
- )
-
- HandlePreview (GApi.Content s) -> ({ model | state = Api.Normal, preview = s }, Cmd.none)
- HandlePreview r -> ({ model | state = Api.Error r }, Cmd.none)
-
view : Model -> Html Msg
view model =
@@ -107,14 +94,7 @@ view model =
, text " with some "
, a [ href "http://fletcher.github.io/MultiMarkdown-5/syntax.html", target "_blank" ][ text "extensions" ]
, text "."
- , a [ href "#", style "float" "right", onClickN Preview ]
- [ text <| if model.preview == "" then "Preview" else "Edit"
- , if model.state == Api.Loading then div [ class "spinner" ] [] else text ""
- ]
- , br_ 1
- , if model.preview == ""
- then inputTextArea "content" model.content Content ([rows 50, cols 90, style "width" "850px"] ++ GD.valContent)
- else div [ class "docs preview", style "width" "850px", Ffi.innerHtml model.preview ] []
+ , TP.view "content" model.content Content 850 ([rows 50, cols 90] ++ GD.valContent)
]
]
]
diff --git a/elm/Lib/Editsum.elm b/elm/Lib/Editsum.elm
index 7ab1f994..99a4be29 100644
--- a/elm/Lib/Editsum.elm
+++ b/elm/Lib/Editsum.elm
@@ -6,20 +6,21 @@ module Lib.Editsum exposing (Model, Msg, new, update, view)
import Html exposing (..)
import Html.Attributes exposing (..)
import Lib.Html exposing (..)
+import Lib.TextPreview as TP
type alias Model =
{ authmod : Bool
, locked : Bool
, hidden : Bool
- , editsum : String
+ , editsum : TP.Model
}
type Msg
= Locked Bool
| Hidden Bool
- | Editsum String
+ | Editsum TP.Msg
new : Model
@@ -27,16 +28,16 @@ new =
{ authmod = False
, locked = False
, hidden = False
- , editsum = ""
+ , editsum = TP.bbcode ""
}
-update : Msg -> Model -> Model
+update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
- Locked b -> { model | locked = b }
- Hidden b -> { model | hidden = b }
- Editsum s -> { model | editsum = s }
+ Locked b -> ({ model | locked = b }, Cmd.none)
+ Hidden b -> ({ model | hidden = b }, Cmd.none)
+ Editsum m -> let (nm,nc) = TP.update m model.editsum in ({ model | editsum = nm }, Cmd.map Editsum nc)
view : Model -> Html Msg
@@ -60,6 +61,5 @@ view model =
[ text "Edit summary"
, b [class "standout"] [text " (English please!)"]
]
- -- TODO: BBCode preview
- , inputTextArea "editsum" model.editsum Editsum [rows 4, cols 50, minlength 2, maxlength 5000, required True]
+ , TP.view "" model.editsum Editsum 600 [rows 4, cols 50, minlength 2, maxlength 5000, required True]
]
diff --git a/elm/Lib/TextPreview.elm b/elm/Lib/TextPreview.elm
new file mode 100644
index 00000000..8c9e3287
--- /dev/null
+++ b/elm/Lib/TextPreview.elm
@@ -0,0 +1,90 @@
+module Lib.TextPreview exposing (..)
+
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (..)
+import Json.Encode as JE
+import Lib.Html exposing (..)
+import Lib.Ffi as Ffi
+import Lib.Api as Api
+import Gen.Api as GApi
+
+
+type alias Model =
+ { state : Api.State
+ , data : String -- contents of the textarea
+ , preview : String -- Rendered HTML, "" if not in sync with data
+ , display : Bool -- False = textarea is displayed, True = preview is displayed
+ , apiUrl : String
+ , class : String
+ }
+
+
+bbcode : String -> Model
+bbcode data =
+ { state = Api.Normal
+ , data = data
+ , preview = ""
+ , display = False
+ , apiUrl = "/js/bbcode.json"
+ , class = "preview bbcode"
+ }
+
+
+markdown : String -> Model
+markdown data =
+ { state = Api.Normal
+ , data = data
+ , preview = ""
+ , display = False
+ , apiUrl = "/js/markdown.json"
+ , class = "preview docs"
+ }
+
+
+type Msg
+ = Edit String
+ | TextArea
+ | Preview
+ | HandlePreview GApi.Response
+
+
+update : Msg -> Model -> (Model, Cmd Msg)
+update msg model =
+ case msg of
+ Edit s -> ({ model | preview = "", data = s, display = False, state = Api.Normal }, Cmd.none)
+ TextArea -> ({ model | display = False }, Cmd.none)
+
+ Preview ->
+ if model.preview /= ""
+ then ( { model | display = True }, Cmd.none)
+ else ( { model | display = True, state = Api.Loading }
+ , Api.post model.apiUrl (JE.object [("content", JE.string model.data)]) HandlePreview
+ )
+
+ HandlePreview (GApi.Content s) -> ({ model | state = Api.Normal, preview = s }, Cmd.none)
+ HandlePreview r -> ({ model | state = Api.Error r }, Cmd.none)
+
+
+view : String -> Model -> (Msg -> m) -> Int -> List (Attribute m) -> Html m
+view name model cmdmap width attr =
+ let
+ display = model.display && model.preview /= ""
+ in
+ div [ class "textpreview", style "width" (String.fromInt width ++ "px") ]
+ [ p (class "head" :: (if model.data == "" then [class "invisible"] else []))
+ [ case model.state of
+ Api.Loading -> div [ class "spinner" ] []
+ Api.Error _ -> b [ class "grayedout" ] [ text "Error loading preview. " ]
+ Api.Normal -> text ""
+ , if display
+ then a [ onClickN (cmdmap TextArea) ] [ text "Edit" ]
+ else i [] [text "Edit"]
+ , if display
+ then i [] [text "Preview"]
+ else a [ onClickN (cmdmap Preview) ] [ text "Preview" ]
+ ]
+ , inputTextArea name model.data (cmdmap << Edit) (class (if display then "hidden" else "") :: attr)
+ , if not display then text ""
+ else div [ class model.class, Ffi.innerHtml model.preview ] []
+ ]
diff --git a/elm/StaffEdit/Main.elm b/elm/StaffEdit/Main.elm
index 909cfd82..2eeaea27 100644
--- a/elm/StaffEdit/Main.elm
+++ b/elm/StaffEdit/Main.elm
@@ -7,6 +7,7 @@ import Browser
import Browser.Navigation exposing (load)
import Lib.Util exposing (..)
import Lib.Html exposing (..)
+import Lib.TextPreview as TP
import Lib.Api as Api
import Lib.Editsum as Editsum
import Gen.StaffEdit as GSE
@@ -29,7 +30,7 @@ type alias Model =
, alias : List GSE.RecvAlias
, aliasDup : Bool
, aid : Int
- , desc : String
+ , desc : TP.Model
, gender : String
, lang : String
, l_site : String
@@ -44,11 +45,11 @@ type alias Model =
init : GSE.Recv -> Model
init d =
{ state = Api.Normal
- , editsum = { authmod = d.authmod, editsum = d.editsum, locked = d.locked, hidden = d.hidden }
+ , editsum = { authmod = d.authmod, editsum = TP.bbcode d.editsum, locked = d.locked, hidden = d.hidden }
, alias = d.alias
, aliasDup = False
, aid = d.aid
- , desc = d.desc
+ , desc = TP.bbcode d.desc
, gender = d.gender
, lang = d.lang
, l_site = d.l_site
@@ -67,7 +68,7 @@ new =
, alias = [ { aid = -1, name = "", original = "", inuse = False } ]
, aliasDup = False
, aid = -1
- , desc = ""
+ , desc = TP.bbcode ""
, gender = "unknown"
, lang = "ja"
, l_site = ""
@@ -81,12 +82,12 @@ new =
encode : Model -> GSE.Send
encode model =
- { editsum = model.editsum.editsum
+ { editsum = model.editsum.editsum.data
, hidden = model.editsum.hidden
, locked = model.editsum.locked
, aid = model.aid
, alias = List.map (\e -> { aid = e.aid, name = e.name, original = e.original }) model.alias
- , desc = model.desc
+ , desc = model.desc.data
, gender = model.gender
, lang = model.lang
, l_site = model.l_site
@@ -114,7 +115,7 @@ type Msg
| LTwitter String
| LAnidb String
| LPixiv String
- | Desc String
+ | Desc TP.Msg
| AliasDel Int
| AliasName Int String
| AliasOrig Int String
@@ -129,7 +130,7 @@ validate model = { model | aliasDup = hasDuplicates <| List.map (\e -> (e.name,
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
- Editsum m -> ({ model | editsum = Editsum.update m model.editsum }, Cmd.none)
+ Editsum m -> let (nm,nc) = Editsum.update m model.editsum in ({ model | editsum = nm }, Cmd.map Editsum nc)
Lang s -> ({ model | lang = s }, Cmd.none)
Gender s -> ({ model | gender = s }, Cmd.none)
Website s -> ({ model | l_site = s }, Cmd.none)
@@ -137,7 +138,7 @@ update msg model =
LTwitter s -> ({ model | l_twitter = s }, Cmd.none)
LAnidb s -> ({ model | l_anidb = if s == "" then Nothing else String.toInt s }, Cmd.none)
LPixiv s -> ({ model | l_pixiv = Maybe.withDefault model.l_pixiv (String.toInt s) }, Cmd.none)
- Desc s -> ({ model | desc = s }, Cmd.none)
+ Desc m -> let (nm,nc) = TP.update m model.desc in ({ model | desc = nm }, Cmd.map Desc nc)
AliasDel i -> (validate { model | alias = delidx i model.alias }, Cmd.none)
AliasName i s -> (validate { model | alias = modidx i (\e -> { e | name = s }) model.alias }, Cmd.none)
@@ -204,7 +205,7 @@ view model =
[ h1 [] [ text "General info" ]
, table [ class "formtable" ]
[ formField "Names" [ names, br_ 1 ]
- , formField "desc::Biography#eng" [ inputTextArea "desc" model.desc Desc GSE.valDesc ]
+ , formField "desc::Biography#eng" [ TP.view "desc" model.desc Desc 500 GSE.valDesc ]
, formField "gender::Gender" [ inputSelect "gender" model.gender Gender []
[ ("unknown", "Unknown or N/A")
, ("f", "Female")