Created
October 27, 2017 20:14
-
-
Save masonjeffreys/40f83a0ef4e5391b4691e48242f7c128 to your computer and use it in GitHub Desktop.
File Upload Elm 0.18
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Important parts of file upload through a HTTP Post form in Elm | |
-- This example reflects an application like a Facebook Post Feed | |
-- Each post has a comment form at the bottom of the post | |
-- A comment can be text or attaching a photo | |
module TopicView exposing (..) | |
import Html exposing (..) | |
import Html.Attributes exposing (..) | |
import Html.Events exposing (..) | |
import Http | |
import Post.Model exposing (Post) | |
import Comment.Model exposing (Comment) | |
import FileReader as FR exposing (readAsArrayBuffer, NativeFile, parseSelectedFiles) | |
import Json.Encode as JE | |
import Json.Decode as JD exposing (field) | |
import Task exposing (..) | |
-- Msg TypeComment is sent when user types in the comment <input text_field> box. | |
-- Msg of FilesSelect is sent on change of file from <input file>. FileReader library is Key!! | |
-- Msg SubmitComment is fired when user clicks submit button on new comment | |
type Msg = | |
| TypeComment Int String | |
| FilesSelect (FR.FileGroup) | |
| SubmitComment Int String | |
| SaveResponse (Result Http.Error String) | |
| FileData Int (Result FR.Error String) | |
update : Msg -> Topic -> (Topic, Cmd Msg) | |
update msg model = | |
case msg of | |
TypeComment id currentString -> | |
let | |
updateCommentForPost p = | |
if p.id == id then | |
{ p | comment = updateComment p.comment currentString} | |
else | |
p | |
in | |
( { model | posts = List.map updateCommentForPost model.posts}, Cmd.none ) | |
ToggleComments id -> | |
let | |
updatePost p = | |
if p.id == id then | |
{ p | showing_comments = not p.showing_comments} | |
else | |
p | |
in | |
( { model | posts = List.map updatePost model.posts}, Cmd.none ) | |
SubmitComment id csrfToken -> | |
maybeSavePost model id csrfToken | |
FilesSelect fileGroup -> | |
let | |
fileInputId = fileGroup.targetId | |
file = List.head fileGroup.files | |
cmdList = [] | |
addFileToComment p = | |
if ( "file-input-" ++ (toString p.id) ) == fileInputId then | |
let | |
(newComment, cmd) = replaceFile p.comment p.id file | |
in | |
({ p | comment = newComment }, cmd) | |
else | |
(p, Cmd.none) | |
newPostList = List.map addFileToComment model.posts | |
(newPosts, cmds) = List.unzip newPostList | |
in | |
Debug.log (toString cmds) | |
{ model | posts = newPosts } ! cmds | |
SaveResponse (Ok id) -> | |
({ model | error = Just "saved successfully" }, Cmd.none ) | |
SaveResponse (Err err) -> | |
let | |
errMsg = | |
case err of | |
Http.BadStatus response -> | |
response.body | |
_ -> | |
"Error Saving!" | |
in | |
( { model | error = Just errMsg }, Cmd.none ) | |
FileData postId (Ok str) -> | |
let | |
addFileContentsToComment p = | |
if p.id == postId then | |
{ p | comment = replaceFileContents p.comment p.id str } | |
else | |
p | |
in | |
Debug.log str | |
( { model | posts = List.map addFileContentsToComment model.posts }, Cmd.none ) | |
FileData postId (Err err) -> | |
Debug.log ("errror ") | |
Debug.log (FR.prettyPrint err) | |
{ model | error = Just (FR.prettyPrint err) } ! [] | |
updateComment : Comment -> String -> Comment | |
updateComment comment str = | |
{ comment | body = Just str } | |
replaceFile : Comment -> Int -> Maybe NativeFile -> (Comment, Cmd Msg) | |
replaceFile comment postId file = | |
case file of | |
Just file -> | |
let | |
cmdToReadFile = Cmd.none --readFile postId file | |
in | |
({ comment | fileToUpload = Just file }, cmdToReadFile) | |
Nothing -> | |
({ comment | fileToUpload = Nothing }, Cmd.none) | |
replaceFileContents : Comment -> Int -> String -> Comment | |
replaceFileContents comment postId fileContents = | |
{ comment | fileContents = Just fileContents } | |
commentEncoder : Comment -> JE.Value | |
commentEncoder comment = | |
JE.object[ | |
( "post_comment[body]", JE.string (Maybe.withDefault "" comment.body)) | |
, ("post_comment[document]", JE.string (Maybe.withDefault "" comment.fileContents)) | |
] | |
maybeSavePost : Topic -> Int -> String -> (Topic, Cmd Msg) | |
maybeSavePost model postId csrfToken = | |
let | |
matchesId post = | |
post.id == postId | |
postToSave = | |
List.filter matchesId model.posts |> List.head | |
in | |
case postToSave of | |
Just p -> | |
let | |
( newPost, cmd ) = savePost p csrfToken | |
in | |
( model, cmd ) | |
Nothing -> | |
( model, Cmd.none) | |
--readFile : Int -> NativeFile -> Cmd Msg | |
--readFile postId fileValue = | |
-- FR.readAsArrayBuffer fileValue.blob | |
-- |> Task.attempt (FileData postId) | |
savePost : Post -> String -> ( Post, Cmd Msg ) | |
savePost model csrfToken = | |
--{ model | message = Basics.toString model.selected } ! List.map readTextFile model.selected | |
--{ p | comment = Comment.Model.initialComment} | |
let | |
--event_topic_post_comment_path(@conn, :create, @event.id, @post.topic_id, @post.id) | |
url = | |
"http://127.0.0.1:4000/events/1-example-event/topics/1/posts/" ++ ( toString model.id ) ++ "/comments" | |
headers = | |
[ | |
Http.header "Authorization" ("Bearer " ++ "xyz"), | |
Http.header "X-CSRF-Token" csrfToken | |
-- `Content-Type` - `"application/json"` | |
-- `Accept` - `"application/json, text/javascript, */*; q=0.01"` | |
-- `X-Requested-With` - `"XMLHttpRequest"` | |
] | |
body = | |
case model.comment.fileToUpload of | |
Just file -> | |
Http.multipartBody [ | |
Http.stringPart "comment[body]" (Maybe.withDefault "" model.comment.body), | |
FR.filePart "comment[document]" file | |
] | |
Nothing -> | |
Http.multipartBody [ | |
Http.stringPart "comment[body]" (Maybe.withDefault "" model.comment.body) | |
] | |
decoder = | |
field "id" JD.string | |
request = | |
post url headers body decoder | |
cmd = | |
Http.send SaveResponse request | |
in | |
Debug.log (toString request) | |
( model, cmd ) | |
post : String -> List Http.Header -> Http.Body -> JD.Decoder a -> Http.Request a | |
post url headers body decoder = | |
Http.request | |
{ method = "POST" | |
, headers = headers | |
, url = url | |
, body = body | |
, expect = Http.expectJson decoder | |
, timeout = Nothing | |
, withCredentials = False | |
} | |
onPostFileChange : (FR.FileGroup -> msg) -> Attribute msg | |
onPostFileChange msg = | |
on "change" (JD.map msg parseSelectedFiles) | |
commentFormView : Comment -> Int -> String -> Html Msg | |
commentFormView comment postId csrfToken = | |
let | |
fileBtnId = | |
"file-input-" ++ toString postId | |
commentText = | |
case comment.body of | |
Just bdy -> | |
bdy | |
Nothing -> | |
"" | |
in | |
div [ class "comment-form-holder"][ | |
input [ class "inputfile", name "post_comment[document]", type_ "file", id fileBtnId, onPostFileChange FilesSelect ][ | |
] | |
, label [ class "file-input-label", for fileBtnId ][ | |
i [ class "fa fa-camera" ][ | |
] | |
, text " attach photo" | |
] | |
, Html.form [ class "add-runner", onSubmit (SubmitComment postId csrfToken) ][ | |
input [ class "form-control", type_ "text", value commentText, placeholder "Write a comment...", onInput ( TypeComment postId )][ | |
] | |
, button [ class "btn btn-primary comment-submit", type_ "submit"][ | |
text "post" | |
] | |
] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment