diff options
author | Yorhel <git@yorhel.nl> | 2019-10-21 14:35:07 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2019-10-21 14:35:07 +0200 |
commit | 83fdd388e335ed60aa9ec9f47d3110ae8da5aeea (patch) | |
tree | ef2130eebcc56134dcd3f8eacc2b91d98f04f133 /elm | |
parent | f7dfacedf5a55596eabe3c30543a2ff2482063b4 (diff) |
Elm: Add text preview framework + BBCode preview in forms
Diffstat (limited to 'elm')
-rw-r--r-- | elm/DocEdit.elm | 40 | ||||
-rw-r--r-- | elm/Lib/Editsum.elm | 18 | ||||
-rw-r--r-- | elm/Lib/TextPreview.elm | 90 | ||||
-rw-r--r-- | elm/StaffEdit/Main.elm | 21 |
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") |