Skip to content

Instantly share code, notes, and snippets.

@yogsototh
Created May 28, 2015 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yogsototh/d051974ca4549171dd33 to your computer and use it in GitHub Desktop.
Save yogsototh/d051974ca4549171dd33 to your computer and use it in GitHub Desktop.
Error: the notify function has been called synchronously!
import Signal exposing (Address,Mailbox,mailbox)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick,on,targetValue)
import Task exposing (Task,andThen)
import Http exposing (multipart,stringData)
import Time exposing (every,second)
main : Signal Html
main = start app
type alias App model action taskAction taskErr =
{ model : model
, view : Address action -> Address (Maybe taskAction) -> model -> Html
, update : action -> model -> model
-- Add timer signals
, externalSignals : Signal action
-- Add tasks
, tasksBox : Mailbox (Maybe taskAction)
, taskIntBox : Mailbox (Maybe action)
, handleTasks : taskAction -> Task taskErr action
}
type alias Error = Http.RawError
app : App Model Action TaskAction Error
app = { model = model
, view = view
, update = update
, externalSignals = initSignals
, tasksBox = mailbox Nothing
, taskIntBox = mailbox Nothing
, handleTasks = handleTasks
}
start : App model action taskAction taskErr -> Signal Html
start app =
let
actions = Signal.mailbox Nothing
address = Signal.forwardTo actions.address Just
model = Signal.foldp (\(Just action) model -> app.update action model)
app.model
(Signal.merge app.taskIntBox.signal
(Signal.merge actions.signal
(Signal.map Just app.externalSignals)))
in
Signal.map (app.view address app.tasksBox.address) model
isJust : Maybe a -> Bool
isJust m = case m of
Nothing -> False
_ -> True
port taskRunner : Signal (Task Error ())
port taskRunner = Signal.map runTask (Signal.filter isJust Nothing app.tasksBox.signal)
runTask : Maybe TaskAction -> Task Error ()
runTask t = case t of
(Just taskAction) -> app.handleTasks taskAction `andThen` report app.taskIntBox.address
Nothing -> Task.succeed DoNothing `andThen` report app.taskIntBox.address
type TaskAction = Login String String
crossOriginGet : String -> String -> Task Http.RawError Http.Response
crossOriginGet origin url =
Http.send Http.defaultSettings { verb = "GET"
, headers = [ ("Origin", origin)
, ("Content-Type", "application/json; charset=UTF-8")
]
, url = url
, body = Http.empty
}
crossOriginPost : String -> String -> Http.Body -> Task Http.RawError Http.Response
crossOriginPost origin url body =
Http.send Http.defaultSettings { verb = "GET"
, headers = [ ("Origin", origin)
, ("Content-Type", "application/json; charset=UTF-8")
]
, url = url
, body = body
}
handleTasks : TaskAction -> Task Error Action
handleTasks taskAction = case taskAction of
Login user pass -> crossOriginPost "http://localhost:8000"
"http://example.com/api/login"
(multipart [ stringData "username" user
, stringData "password" pass ])
`Task.andThen` \_ -> Task.succeed Call
report : Address (Maybe a) -> a -> Task x ()
report addr act = Signal.send addr (Just act)
initSignals : Signal Action
initSignals = Signal.map (\_ -> TimePassed) (every second)
-- MODEL
type alias Model = { counter : Int, user : String, pass : String, msg : String }
model : Model
model = { counter = 0, user = "", pass = "", msg = "" }
-- UPDATE
type Action = TimePassed
| WrongPass
| DoNothing
| Call
| UpdateUser String
| UpdatePass String
update : Action -> Model -> Model
update action model =
case action of
TimePassed -> { model | counter <- model.counter + 1 }
WrongPass -> { model | msg <- "Wrong pass" }
DoNothing -> model
Call -> { model | counter <- 0 }
UpdateUser str -> { model | user <- str }
UpdatePass str -> { model | pass <- str }
-- VIEW
view : Address Action -> Address (Maybe TaskAction) -> Model -> Html
view address taskAddr model =
div []
[ text (toString model.counter)
, button [ onClick address TimePassed ] [ text "+" ]
, loginView address taskAddr model
, div [] [ text model.msg ]
]
divs : List Html -> List Html
divs l = List.map (\e -> div [] [e]) l
loginView : Address Action -> Address (Maybe TaskAction) -> Model -> Html
loginView address taskAddr model =
div [] (divs [ input [ on "input" targetValue (Signal.message address << UpdateUser)
, placeholder "login"
] []
, input [ type' "password"
, placeholder "Password"
, on "input" targetValue (Signal.message address << UpdatePass)] []
, text (model.user ++ ":" ++ model.pass)
, button [ onClick taskAddr (Just (Login model.user model.pass)) ] [ text "Login" ]])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment