Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions Main.elm
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
module Main exposing (..)
module Main exposing (main)


import Html.App as App
import Html
import Time exposing (second, every)

import Model exposing (model)
import Model exposing (Chat, model)
import Update exposing (update)
import View exposing (view)
import Types exposing (Chat, Msg(PollMessages))

import Messages exposing (Msg(PollMessages))
import Task

init = (model, Cmd.none)
init : (Chat, Cmd Msg)
init = (model, prefetchMessages)

prefetchMessages : Cmd Msg
prefetchMessages =
Task.perform
(always PollMessages)
(Task.succeed ())

messageSubscription : Chat -> Sub Msg
messageSubscription _ =
subscriptions : Chat -> Sub Msg
subscriptions _ =
every (5 * second) (always PollMessages)


main : Program Never
main : Program Never Chat Msg
main =
App.program
{ init = init, update = update, view = view, subscriptions = messageSubscription }
Html.program
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ main = Main.elm
sources = \
src/Api.elm \
src/Model.elm \
src/Types.elm \
src/Messages.elm \
src/Update.elm \
src/View.elm
cc = elm make
Expand Down
10 changes: 5 additions & 5 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ h1 {
}

img {
float: right;
height: 135px;
position: absolute;
right: 30%;
width: auto;
margin-bottom: -36px;
}

.btn {
width: 100px;
margin-top: 25px;
float: right;
}

label {
font-size: 18px;
}

#say, #name {
font-size: 16px;
width: 90%;
border-radius: 20px;
height: 40px;

}
}
10 changes: 5 additions & 5 deletions elm-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
],
"exposed-modules": [],
"dependencies": {
"circuithub/elm-html-shorthand": "11.0.0 <= v < 12.0.0",
"elm-lang/core": "4.0.5 <= v < 5.0.0",
"elm-lang/html": "1.1.0 <= v < 2.0.0",
"evancz/elm-http": "3.0.1 <= v < 4.0.0"
"elm-lang/core": "5.0.0 <= v < 6.0.0",
"elm-lang/html": "2.0.0 <= v < 3.0.0",
"elm-lang/http": "1.0.0 <= v < 2.0.0",
"krisajenkins/remotedata": "4.0.0 <= v < 5.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
"elm-version": "0.18.0 <= v < 0.19.0"
}
113 changes: 31 additions & 82 deletions src/Api.elm
Original file line number Diff line number Diff line change
@@ -1,99 +1,48 @@
module Api exposing (pollMessages, sendMessage)
module Api exposing (fetchMessages, sendMessage)

import Http exposing (Body)
import Json.Decode as JD exposing (Decoder)
import Json.Encode as JE exposing (Value)

import Dict
import Http exposing (Error, Response, RawError(RawNetworkError))
import Json.Decode as Json exposing ((:=))
import Json.Encode exposing (Value, encode, object, string)
import Task exposing (Task)

import Types exposing
( ChatMessage
, Msg(Incoming, PollMessages, ShowError)
)
import RemoteData exposing (WebData)

import Model exposing (ChatMessage, ChatList)
import Messages exposing (Msg)

endpoint : String
endpoint = "http://localhost:3000/messages"


-- GET

fetchMessages : (ChatList -> Msg) -> Cmd Msg
fetchMessages callback =
Http.get endpoint incomingMessagesDecoder
|> Http.send (callback << RemoteData.fromResult)

pollMessages : Cmd Msg
pollMessages =
Task.perform onError onReceive getMessages


getMessages : Task Http.Error (List ChatMessage)
getMessages =
Http.get messagesDecoder endpoint


messagesDecoder : Json.Decoder (List ChatMessage)
messagesDecoder = Json.list messageDecoder


messageDecoder : Json.Decoder ChatMessage
messageDecoder =
Json.object2 (\name message -> { name = name, message = message })
("name" := Json.string)
("message" := Json.string)
incomingMessagesDecoder : Decoder (List ChatMessage)
incomingMessagesDecoder =
JD.list incomingMessageDecoder

incomingMessageDecoder : Decoder ChatMessage
incomingMessageDecoder =
JD.map2 (\name message -> ChatMessage name message)
(JD.field "name" JD.string)
(JD.field "message" JD.string)

-- POST

sendMessage : ChatMessage -> (WebData JD.Value -> Msg) -> Cmd Msg
sendMessage chatMessage callback =
Http.post endpoint (bodyToSend chatMessage) JD.value
|> Http.send (callback << RemoteData.fromResult)

sendMessage : ChatMessage -> Cmd Msg
sendMessage msg =
Task.perform onError onSent (postMessage msg)


postMessage : ChatMessage -> Task RawError ()
postMessage msg =
Http.send Http.defaultSettings
{ verb = "POST"
, headers = []
, url = endpoint
, body =
messageEncoder msg
|> encode 0
|> Http.string
}
`Task.andThen` handlePostResponse

bodyToSend : ChatMessage -> Body
bodyToSend chatMessage =
Http.jsonBody <| sendEncoder chatMessage

messageEncoder : ChatMessage -> Json.Value
messageEncoder msg =
object
[ ("name", string msg.name)
, ("message", string msg.message)
sendEncoder : ChatMessage -> JE.Value
sendEncoder msg =
JE.object
[ ("name", JE.string msg.name)
, ("message", JE.string msg.message)
]


-- Response handlers


onError : err -> Msg
onError err = ShowError (toString err)


-- About the weird type... if we get here then the Http POST worked, now
-- we just refresh messages so the person posting can see their new message.
onSent : () -> Msg
onSent _ = PollMessages


handlePostResponse : Response -> Task RawError ()
handlePostResponse resp =
case Dict.get "Location" resp.headers of
Nothing ->
Task.fail RawNetworkError

Just _ ->
Task.succeed ()


onReceive : List ChatMessage -> Msg
onReceive msgs =
Incoming msgs
10 changes: 10 additions & 0 deletions src/Messages.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Messages exposing (Msg(..))

import Model exposing (..)

type Msg
= SendMessage Name Message
| Incoming ChatList
| Input String
| PollMessages
| SetName String
24 changes: 19 additions & 5 deletions src/Model.elm
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
module Model exposing (..)

import RemoteData exposing (RemoteData(NotAsked), WebData)

import Types exposing (Chat)

type alias Chat =
{ messages : ChatList
, saying : String
, name : String
}

model : Chat
model =
{ messages = []
, field = ""
{ messages = NotAsked
, saying = ""
, name = ""
, errorMessage = ""
}

type alias ChatList =
WebData (List ChatMessage)

type alias Name = String
type alias Message = String

type alias ChatMessage =
{ name : Name
, message : Message
}
26 changes: 0 additions & 26 deletions src/Types.elm

This file was deleted.

42 changes: 13 additions & 29 deletions src/Update.elm
Original file line number Diff line number Diff line change
@@ -1,42 +1,26 @@
module Update exposing (..)

module Update exposing (update)

import Api
import Task
import Types exposing (Msg(..), Chat, ChatMessage)

import Messages exposing (Msg(..))
import Model exposing (Chat, ChatMessage)

update : Msg -> Chat -> (Chat, Cmd Msg)
update msg model =
case msg of
SendMessage msg ->
( { model | field = "" }
, Api.sendMessage msg
)
SendMessage name saying ->
let
message = ChatMessage name saying
in
({ model | saying = "" }, Api.sendMessage message (always PollMessages))

Incoming msgs ->
( { model | messages = msgs, errorMessage = "" }
, Cmd.none
)
Incoming msgsResult ->
({model | messages = msgsResult}, Cmd.none)

PollMessages ->
( model
, Api.pollMessages
)
(model, Api.fetchMessages Incoming)

Input say ->
( { model | field = say }
, Cmd.none
)
({ model | saying = say }, Cmd.none)

SetName name ->
( { model | name = name }
, Cmd.none
)

ShowError err ->
( { model | errorMessage = err }
, Cmd.none
)

NoOp -> (model, Cmd.none)
({ model | name = name }, Cmd.none)
Loading