first commit
This is the first commit. With stuff on several lines.
This commit is contained in:
commit
899087ed49
11 changed files with 1101 additions and 0 deletions
702
src/App.elm
Normal file
702
src/App.elm
Normal file
|
@ -0,0 +1,702 @@
|
|||
port module App exposing (..)
|
||||
|
||||
import Browser
|
||||
import Browser.Navigation
|
||||
import File exposing (File)
|
||||
import Html as H exposing (Html)
|
||||
import Html.Attributes as HA
|
||||
import Html.Events as HE
|
||||
import Http exposing (Error(..))
|
||||
import Json.Decode as JD
|
||||
import Json.Decode.Extra exposing (andMap)
|
||||
import Json.Encode as JE
|
||||
import Process
|
||||
import Task
|
||||
import Url.Builder as UB
|
||||
|
||||
port reload_preview : () -> Cmd msg
|
||||
|
||||
port show_modal : String -> Cmd msg
|
||||
|
||||
delayMsg : Float -> msg -> Cmd msg
|
||||
delayMsg delay msg =
|
||||
Task.perform (always msg) (Process.sleep delay)
|
||||
|
||||
main = Browser.document
|
||||
{ init = init
|
||||
, update = update
|
||||
, subscriptions = subscriptions
|
||||
, view = view
|
||||
}
|
||||
|
||||
type alias FileInfo =
|
||||
{ name : String
|
||||
, is_dir : Bool
|
||||
, path : String
|
||||
}
|
||||
|
||||
type alias ElmPackage =
|
||||
{ name : String
|
||||
, summary : String
|
||||
, version : String
|
||||
, license : String
|
||||
}
|
||||
|
||||
decode_elm_package =
|
||||
JD.map4
|
||||
ElmPackage
|
||||
(JD.field "name" JD.string)
|
||||
(JD.field "summary" JD.string)
|
||||
(JD.field "version" JD.string)
|
||||
(JD.field "license" JD.string)
|
||||
|
||||
file_info name = { name = name, path = name, is_dir = False }
|
||||
dir_info name = { name = name, path = name, is_dir = True }
|
||||
|
||||
file_edit_url f = (UB.relative [] [UB.string "path" f.path])
|
||||
|
||||
type Log
|
||||
= NotLoaded
|
||||
| HttpError Http.Error
|
||||
| MakeResult String String
|
||||
| MakeError String
|
||||
| CommandResult String String
|
||||
|
||||
type alias CommandResult = Result String { stdout : String, stderr : String }
|
||||
|
||||
type alias Model =
|
||||
{ show_preview : Bool
|
||||
, show_log : Bool
|
||||
, editor_size : Float
|
||||
, content_changed : Bool
|
||||
, log : Log
|
||||
, command_to_run : String
|
||||
, selected_package : String
|
||||
, jj_status : String
|
||||
, commit_message : String
|
||||
|
||||
, csrf_token : String
|
||||
, preview_url : String
|
||||
, slug : String
|
||||
, files : List FileInfo
|
||||
, file_path : String
|
||||
, file_content : String
|
||||
, is_dir : Bool
|
||||
, elm_packages : List ElmPackage
|
||||
}
|
||||
|
||||
init_model : Model
|
||||
init_model =
|
||||
{ show_preview = True
|
||||
, show_log = False
|
||||
, editor_size = 0.5
|
||||
, content_changed = False
|
||||
, log = NotLoaded
|
||||
, command_to_run = ""
|
||||
, selected_package = ""
|
||||
, jj_status = ""
|
||||
, commit_message = ""
|
||||
|
||||
, csrf_token = ""
|
||||
, preview_url = ""
|
||||
, slug = "not-a-real-thing"
|
||||
, files = []
|
||||
, file_path = "Oops!"
|
||||
, file_content = "The editor has not loaded successfully."
|
||||
, is_dir = False
|
||||
, elm_packages = []
|
||||
}
|
||||
|
||||
type DropFileAction
|
||||
= Upload
|
||||
| Content
|
||||
|
||||
type Msg
|
||||
= SetFileContent String
|
||||
| SaveContent String
|
||||
| FileSaved String (Result Http.Error CommandResult)
|
||||
| SetLog (Result Http.Error String)
|
||||
| ReloadLog
|
||||
| ReloadPreview
|
||||
| SetEditorSize Float
|
||||
| TogglePreview Bool
|
||||
| ToggleLog Bool
|
||||
| DropFiles DropFileAction (List File)
|
||||
| NoOp
|
||||
| UploadFile File String
|
||||
| FileUploaded File
|
||||
| SetCommand String
|
||||
| RunCommand String
|
||||
| ReceiveCommandResult (Result Http.Error CommandResult)
|
||||
| SelectPackage String
|
||||
| ShowCommitModal
|
||||
| ReceiveJJStatus String
|
||||
| SetCommitMessage String
|
||||
| JJCommit
|
||||
| JJCommitResponse (Result Http.Error CommandResult)
|
||||
|
||||
init : JE.Value -> (Model, Cmd Msg)
|
||||
init flags = (load_flags flags, reload_log)
|
||||
|
||||
load_flags =
|
||||
JD.decodeValue
|
||||
( JD.succeed
|
||||
(Model
|
||||
init_model.show_preview
|
||||
init_model.show_log
|
||||
init_model.editor_size
|
||||
init_model.content_changed
|
||||
init_model.log
|
||||
init_model.command_to_run
|
||||
init_model.selected_package
|
||||
init_model.jj_status
|
||||
init_model.commit_message
|
||||
)
|
||||
|> andMap (JD.field "csrf_token" JD.string)
|
||||
|> andMap (JD.field "preview_url" JD.string)
|
||||
|> andMap (JD.field "slug" JD.string)
|
||||
|> andMap (JD.field "files" (JD.list decode_file_info))
|
||||
|> andMap (JD.field "file_path" JD.string)
|
||||
|> andMap (JD.field "file_content" JD.string)
|
||||
|> andMap (JD.field "is_dir" JD.bool)
|
||||
|> andMap (JD.oneOf [JD.field "elm_packages" (JD.list decode_elm_package), JD.succeed []])
|
||||
)
|
||||
>> Result.withDefault init_model
|
||||
|
||||
decode_file_info =
|
||||
JD.map3
|
||||
FileInfo
|
||||
(JD.field "name" JD.string)
|
||||
(JD.field "is_dir" JD.bool)
|
||||
(JD.field "path" JD.string)
|
||||
|
||||
decode_command_response =aq
|
||||
JD.oneOf
|
||||
[ JD.field "error" JD.string |> JD.map Err
|
||||
, JD.map2 (\stdout stderr -> Ok { stdout = stdout, stderr = stderr })
|
||||
(JD.field "stdout" JD.string)
|
||||
(JD.field "stderr" JD.string)
|
||||
]
|
||||
|
||||
set_log : Log -> Model -> Model
|
||||
set_log log model = { model | log = log, show_log = True }
|
||||
|
||||
nocmd model = (model, Cmd.none)
|
||||
|
||||
update : Msg -> Model -> (Model, Cmd Msg)
|
||||
update msg model = case msg of
|
||||
SetFileContent content -> ({ model | file_content = content, content_changed = True }, delayMsg 1000 (SaveContent content))
|
||||
|
||||
SaveContent content ->
|
||||
if content == model.file_content then
|
||||
( model
|
||||
, Http.post
|
||||
{ url = "save-file"
|
||||
, body = Http.multipartBody
|
||||
[ Http.stringPart "path" model.file_path
|
||||
, Http.stringPart "content" model.file_content
|
||||
, Http.stringPart "csrfmiddlewaretoken" model.csrf_token
|
||||
]
|
||||
, expect = Http.expectJson (FileSaved content) decode_command_response
|
||||
}
|
||||
)
|
||||
else
|
||||
(model, Cmd.none)
|
||||
|
||||
FileSaved content response -> case response of
|
||||
Ok (Ok res) -> ({ model | content_changed = content /= model.file_content, log = MakeResult res.stdout res.stderr }, delayMsg 1 ReloadPreview)
|
||||
Ok (Err errmsg) -> ({ model | content_changed = content /= model.file_content, log = MakeError errmsg }, delayMsg 1 ReloadPreview)
|
||||
Err err -> { model | log = HttpError err } |> nocmd
|
||||
|
||||
ReloadLog ->
|
||||
(model
|
||||
, reload_log
|
||||
)
|
||||
|
||||
SetLog response -> case response of
|
||||
Ok log ->
|
||||
{ model | log = (MakeResult log "") } |> nocmd
|
||||
Err errmsg -> model |> set_log (HttpError errmsg) |> nocmd
|
||||
|
||||
ReloadPreview -> (model, reload_preview ())
|
||||
|
||||
SetEditorSize size -> { model | editor_size = size } |> nocmd
|
||||
|
||||
TogglePreview show -> { model | show_preview = show } |> nocmd
|
||||
|
||||
ToggleLog show -> { model | show_log = show } |> nocmd
|
||||
|
||||
DropFiles action files -> case List.head files of
|
||||
Just file -> case action of
|
||||
Content -> (model, Task.perform SetFileContent (File.toString file))
|
||||
Upload -> (model, Task.perform (UploadFile file) (File.toString file))
|
||||
Nothing -> (model, Cmd.none)
|
||||
|
||||
UploadFile file contents ->
|
||||
( model
|
||||
, Http.post
|
||||
{ url = "save-file"
|
||||
, body = Http.multipartBody
|
||||
[ Http.stringPart "path" (File.name file)
|
||||
, Http.stringPart "content" contents
|
||||
, Http.stringPart "csrfmiddlewaretoken" model.csrf_token
|
||||
]
|
||||
, expect = Http.expectWhatever
|
||||
(\r -> case r of
|
||||
Ok _ -> FileUploaded file
|
||||
Err _ -> NoOp
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
FileUploaded file ->
|
||||
let
|
||||
name = File.name file
|
||||
url = file_edit_url { name = name, path = name, is_dir = False }
|
||||
in
|
||||
(model, Browser.Navigation.load url)
|
||||
|
||||
SetCommand cmd -> { model | command_to_run = cmd } |> nocmd
|
||||
|
||||
RunCommand cmd ->
|
||||
(model
|
||||
, Http.post
|
||||
{ url = "run-command"
|
||||
, body = Http.multipartBody
|
||||
[ Http.stringPart "command" cmd
|
||||
, Http.stringPart "csrfmiddlewaretoken" model.csrf_token
|
||||
]
|
||||
, expect = Http.expectJson ReceiveCommandResult decode_command_response
|
||||
}
|
||||
)
|
||||
|
||||
SelectPackage name -> { model | selected_package = name } |> nocmd
|
||||
|
||||
ReceiveCommandResult response -> case response of
|
||||
Ok (Ok res) -> model |> set_log (MakeResult res.stdout res.stderr) |> nocmd
|
||||
Ok (Err errmsg) -> model |> set_log (MakeError errmsg) |> nocmd
|
||||
Err err -> model |> set_log (HttpError err) |> nocmd
|
||||
|
||||
ShowCommitModal -> (model, Cmd.batch [fetch_jj_status, show_modal "commit-modal"])
|
||||
|
||||
SetCommitMessage message -> { model | commit_message = message } |> nocmd
|
||||
|
||||
ReceiveJJStatus status -> { model | jj_status = status, commit_message = "" } |> nocmd
|
||||
|
||||
JJCommit ->
|
||||
( model
|
||||
, Http.post
|
||||
{ url = "jj/commit"
|
||||
, body = Http.multipartBody
|
||||
[ Http.stringPart "message" model.commit_message
|
||||
, Http.stringPart "csrfmiddlewaretoken" model.csrf_token
|
||||
]
|
||||
, expect = Http.expectJson JJCommitResponse
|
||||
decode_command_response
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
JJCommitResponse response -> case response of
|
||||
Ok (Ok res) -> { model | log = MakeResult res.stdout res.stderr } |> nocmd
|
||||
Ok (Err errmsg) -> { model | log = MakeError errmsg } |> nocmd
|
||||
Err err -> { model | log = HttpError err } |> nocmd
|
||||
|
||||
NoOp -> (model, Cmd.none)
|
||||
|
||||
reload_log =
|
||||
Http.get
|
||||
{ url = "log"
|
||||
, expect = Http.expectString SetLog
|
||||
}
|
||||
|
||||
fetch_jj_status =
|
||||
Http.get
|
||||
{ url = "jj/status"
|
||||
, expect = Http.expectJson
|
||||
(\r -> case r of
|
||||
Ok response -> ReceiveJJStatus response
|
||||
Err _ -> NoOp
|
||||
)
|
||||
(JD.field "status" JD.string)
|
||||
}
|
||||
|
||||
subscriptions model = Sub.none
|
||||
|
||||
link url text =
|
||||
H.a
|
||||
[ HA.href url]
|
||||
[ H.text text ]
|
||||
|
||||
|
||||
form : Model -> List (H.Attribute Msg) -> List (Html Msg) -> Html Msg
|
||||
form model attrs children =
|
||||
H.form
|
||||
attrs
|
||||
( children
|
||||
++ [ H.input
|
||||
[ HA.type_ "hidden"
|
||||
, HA.name "csrfmiddlewaretoken"
|
||||
, HA.value model.csrf_token
|
||||
]
|
||||
[]
|
||||
]
|
||||
)
|
||||
|
||||
as_percentage : Float -> String
|
||||
as_percentage amount = (String.fromInt <| round (100 * amount)) ++ "%"
|
||||
|
||||
view : Model -> Browser.Document Msg
|
||||
view model =
|
||||
{
|
||||
title = model.file_path ++ " - " ++ model.slug ++ " - Thinks",
|
||||
body =
|
||||
[ header model
|
||||
|
||||
, H.main_
|
||||
[ HA.classList
|
||||
[ ("think-editor", True)
|
||||
]
|
||||
, HA.attribute "style" <| ("--editor-size: " ++ (String.fromFloat model.editor_size)++"fr"++";--preview-size: "++(String.fromFloat (1-model.editor_size))++"fr")
|
||||
]
|
||||
[ main_nav model
|
||||
, log_pane model
|
||||
, if model.is_dir then H.text "" else editor_pane model
|
||||
, preview_pane model
|
||||
]
|
||||
|
||||
, commit_modal model
|
||||
]
|
||||
}
|
||||
|
||||
header model =
|
||||
H.header
|
||||
[]
|
||||
[ link "/" "thinks"
|
||||
, H.h1
|
||||
[]
|
||||
[ H.text model.slug ]
|
||||
, H.p
|
||||
[ HA.id "think-controls" ]
|
||||
[ H.a
|
||||
[ HA.target "preview"
|
||||
, HA.href model.preview_url
|
||||
]
|
||||
[ H.text "Preview" ]
|
||||
, link "rename" "Rename"
|
||||
, link "delete" "Delete"
|
||||
, link ("/new/"++model.slug) "Remix"
|
||||
, H.label
|
||||
[ HA.for "editor-size-input"
|
||||
]
|
||||
[ H.text "File editor size" ]
|
||||
, H.input
|
||||
[ HA.type_ "range"
|
||||
, HA.id "editor-size-input"
|
||||
, HA.min "0"
|
||||
, HA.max "1"
|
||||
, HA.step "0.05"
|
||||
, HA.value <| String.fromFloat model.editor_size
|
||||
, HE.on "input" (JD.at ["target", "valueAsNumber"] JD.float |> JD.map SetEditorSize)
|
||||
, HA.list "size-values"
|
||||
]
|
||||
[]
|
||||
, H.output
|
||||
[ HA.for "editor-size-input" ]
|
||||
[ H.text <| as_percentage model.editor_size ]
|
||||
, H.datalist
|
||||
[ HA.id "size-values" ]
|
||||
[ H.option [ HA.value "0.5" ] [] ]
|
||||
]
|
||||
]
|
||||
|
||||
main_nav model =
|
||||
H.details
|
||||
[ HA.attribute "open" ""
|
||||
, HA.id "main-nav"
|
||||
, HE.preventDefaultOn "drop" (JD.at ["dataTransfer", "files"] (JD.list File.decoder) |> JD.map (\f -> (DropFiles Upload f, True)) )
|
||||
, HE.preventDefaultOn "dragover" (JD.succeed (NoOp,True))
|
||||
]
|
||||
[ H.summary
|
||||
[]
|
||||
[ H.text "Files" ]
|
||||
, H.nav
|
||||
[]
|
||||
[ H.ul
|
||||
[ HA.id "file-tree" ]
|
||||
(List.map (\f ->
|
||||
H.li
|
||||
[ HA.classList
|
||||
[ ("dir", f.is_dir)
|
||||
, ("file", not f.is_dir)
|
||||
, ("file-path", True)
|
||||
]
|
||||
]
|
||||
[ link (file_edit_url f) f.name ]
|
||||
) model.files
|
||||
)
|
||||
, form model
|
||||
[ HA.id "file-form"
|
||||
, HA.method "GET"
|
||||
, HA.action "edit"
|
||||
]
|
||||
[ H.input
|
||||
[ HA.attribute "aria-labelledby" "new-file-button"
|
||||
, HA.id "new-file-path"
|
||||
, HA.type_ "text"
|
||||
, HA.name "path"
|
||||
, HA.value <| (if model.is_dir then model.file_path else String.join "/" <| List.reverse <| List.drop 1 <| List.reverse <| String.split "/" model.file_path)++"/"
|
||||
]
|
||||
[]
|
||||
, H.button
|
||||
[ HA.id "new-file-button"
|
||||
, HA.type_ "submit"
|
||||
]
|
||||
[ H.text "New file" ]
|
||||
]
|
||||
, form model
|
||||
[ HE.onSubmit <| RunCommand model.command_to_run
|
||||
]
|
||||
[ H.input
|
||||
[ HA.attribute "aria-labelledby" "run-command-button"
|
||||
, HE.onInput SetCommand
|
||||
, HA.name "command"
|
||||
, HA.value model.command_to_run
|
||||
]
|
||||
[]
|
||||
, H.button
|
||||
[ HA.id "run-command-button"
|
||||
, HA.type_ "submit"
|
||||
]
|
||||
[ H.text "Run" ]
|
||||
]
|
||||
, if String.right 4 model.file_path == ".elm" then
|
||||
form model
|
||||
[ HE.onSubmit <| case model.selected_package of
|
||||
"" -> NoOp
|
||||
p -> RunCommand <| "bash -c \"echo 'Y' | elm install " ++ p ++ "\""
|
||||
]
|
||||
[ H.input
|
||||
[ HA.list "elm-packages"
|
||||
, HE.onInput SelectPackage
|
||||
, HA.value <| model.selected_package
|
||||
]
|
||||
[]
|
||||
, H.node "datalist"
|
||||
[ HA.id "elm-packages"]
|
||||
(List.map (\p -> H.option [HA.value p.name] [H.text p.name]) model.elm_packages)
|
||||
, H.button
|
||||
[ HA.id "install-package-button"
|
||||
, HA.type_ "submit"
|
||||
]
|
||||
[ H.text "Install" ]
|
||||
]
|
||||
else
|
||||
H.text ""
|
||||
, H.button
|
||||
[ HA.id "start-commit-button"
|
||||
, HA.type_ "button"
|
||||
, HE.onClick ShowCommitModal
|
||||
]
|
||||
[ H.text "Commit" ]
|
||||
]
|
||||
]
|
||||
|
||||
editor_pane model =
|
||||
H.section
|
||||
[ HA.id "editor"
|
||||
, HE.preventDefaultOn "drop" (JD.at ["dataTransfer", "files"] (JD.list File.decoder) |> JD.map (\f -> (DropFiles Content f, True)) )
|
||||
, HE.preventDefaultOn "dragover" (JD.succeed (NoOp,True))
|
||||
]
|
||||
[ H.nav
|
||||
[ HA.id "editor-controls" ]
|
||||
[ H.span
|
||||
[ HA.id "file-path"
|
||||
, HA.class "file-path"
|
||||
]
|
||||
[ H.text model.file_path ]
|
||||
, H.span
|
||||
[ HA.id "file-changed-status"
|
||||
, HA.classList
|
||||
[ ("changed", model.content_changed) ]
|
||||
]
|
||||
[ H.text <| if model.content_changed then "changed" else "saved" ]
|
||||
, H.details
|
||||
[]
|
||||
[ H.summary
|
||||
[]
|
||||
[ H.text "Actions" ]
|
||||
, form model
|
||||
[ HA.method "POST"
|
||||
, HA.action "delete-file"
|
||||
]
|
||||
[ H.input
|
||||
[ HA.type_ "hidden"
|
||||
, HA.name "path"
|
||||
, HA.value model.file_path
|
||||
]
|
||||
[]
|
||||
, H.button
|
||||
[ HA.type_ "submit" ]
|
||||
[ H.text "Delete" ]
|
||||
]
|
||||
, form model
|
||||
[ HA.method "POST"
|
||||
, HA.action "rename-file"
|
||||
]
|
||||
[ H.input
|
||||
[ HA.type_ "hidden"
|
||||
, HA.name "path"
|
||||
, HA.value model.file_path
|
||||
]
|
||||
[]
|
||||
, H.input
|
||||
[ HA.type_ "text"
|
||||
, HA.name "newpath"
|
||||
, HA.value model.file_path
|
||||
]
|
||||
[]
|
||||
, H.button
|
||||
[ HA.type_ "submit" ]
|
||||
[ H.text "Rename" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
, form model
|
||||
[ HA.id "file-form"
|
||||
, HA.method "POST"
|
||||
, HA.action "save-file"
|
||||
]
|
||||
[ H.node "code-editor"
|
||||
[ HE.on "change" (JD.at ["target", "value"] JD.string |> JD.map SetFileContent)
|
||||
, HA.attribute "content" model.file_content
|
||||
]
|
||||
[ H.text model.file_content ]
|
||||
, H.input
|
||||
[ HA.name "path"
|
||||
, HA.value model.file_path
|
||||
, HA.type_ "hidden"
|
||||
]
|
||||
[]
|
||||
, H.input
|
||||
[ HA.name "content"
|
||||
, HA.value model.file_content
|
||||
, HA.type_ "hidden"
|
||||
]
|
||||
[]
|
||||
]
|
||||
]
|
||||
|
||||
log_pane : Model -> Html Msg
|
||||
log_pane model =
|
||||
H.details
|
||||
([HA.id "log"
|
||||
, HE.on "toggle" (JD.at ["target", "open"] JD.bool |> JD.map ToggleLog)
|
||||
]++(if model.show_log then [ HA.attribute "open" ""] else [])
|
||||
)
|
||||
[ H.summary
|
||||
[]
|
||||
[ H.text "Log" ]
|
||||
, case model.log of
|
||||
NotLoaded -> H.text "Not loaded"
|
||||
|
||||
MakeResult stdout stderr ->
|
||||
H.dl
|
||||
[]
|
||||
[ H.dt [] [H.text "stdout" ]
|
||||
, H.dd [] [H.pre [] [ H.text stdout ]]
|
||||
, H.dt [] [H.text "stderr" ]
|
||||
, H.dd [] [H.pre [] [ H.text stderr ]]
|
||||
]
|
||||
|
||||
CommandResult stdout stderr ->
|
||||
H.dl
|
||||
[]
|
||||
[ H.dt [] [H.text "stdout" ]
|
||||
, H.dd [] [H.pre [] [ H.text stdout ]]
|
||||
, H.dt [] [H.text "stderr" ]
|
||||
, H.dd [] [H.pre [] [ H.text stderr ]]
|
||||
]
|
||||
|
||||
MakeError err ->
|
||||
H.div
|
||||
[]
|
||||
[ H.h2 [] [ H.text "Error"]
|
||||
, H.pre [] [H.text err]
|
||||
]
|
||||
|
||||
HttpError err ->
|
||||
let
|
||||
text = case err of
|
||||
BadUrl url -> "Bad URL " ++ url
|
||||
Timeout -> "Timeout"
|
||||
NetworkError -> "Network error"
|
||||
BadStatus code -> "Bad response code " ++ (String.fromInt code)
|
||||
BadBody body -> "Bad body " ++ body
|
||||
in
|
||||
H.div
|
||||
[]
|
||||
[ H.h2 [] [ H.text "Network error"]
|
||||
, H.pre [] [H.text text]
|
||||
]
|
||||
]
|
||||
|
||||
preview_pane model =
|
||||
H.details
|
||||
[ HA.attribute "open" ""
|
||||
, HA.id "preview"
|
||||
, HE.on "toggle" (JD.at ["target", "open"] JD.bool |> JD.map TogglePreview)
|
||||
]
|
||||
( [ H.summary
|
||||
[]
|
||||
[ H.text "Preview"
|
||||
]
|
||||
]
|
||||
++ if model.show_preview then
|
||||
[ H.iframe
|
||||
[ HA.id "preview-frame"
|
||||
, HA.src model.preview_url
|
||||
]
|
||||
[]
|
||||
]
|
||||
else
|
||||
[]
|
||||
)
|
||||
|
||||
commit_modal model =
|
||||
let
|
||||
view_status status =
|
||||
H.tr
|
||||
[]
|
||||
[ H.td [] [ H.text <| status.path ] ]
|
||||
in
|
||||
H.node "dialog"
|
||||
[ HA.id "commit-modal" ]
|
||||
[ H.h2 [] [H.text "Commit"]
|
||||
, H.pre [ HA.id "jj-status" ] [H.text model.jj_status]
|
||||
, H.form
|
||||
[ HE.on "submit"
|
||||
( JD.at ["submitter","value"] JD.string
|
||||
|> JD.map (\v -> case v of
|
||||
"cancel" -> NoOp
|
||||
_ -> JJCommit
|
||||
)
|
||||
)
|
||||
, HA.method "dialog"
|
||||
]
|
||||
[ H.textarea
|
||||
[ HA.value model.commit_message
|
||||
, HE.onInput SetCommitMessage
|
||||
]
|
||||
[]
|
||||
, H.button
|
||||
[ HA.value "cancel"
|
||||
, HA.attribute "formmethod" "dialog"
|
||||
]
|
||||
[ H.text "Cancel"]
|
||||
, H.button
|
||||
[ HA.type_ "submit"
|
||||
]
|
||||
[ H.text "Commit"]
|
||||
]
|
||||
]
|
Loading…
Add table
Add a link
Reference in a new issue