import Html exposing (..) import Html.Events exposing (..) import Html.Attributes exposing (href, style, src) import Task exposing (Task) import Http exposing (Error) import JavaScript.Decode exposing (..) -- Operator from Clojure (>!) : a -> Stream.Input a -> Stream.Message (>!) a input' = Stream.message input'.address a -- Javascript Decoding Helper andMap : Decoder (a -> b) -> Decoder a -> Decoder b andMap = object2 (<|) -- Model + Javascript Parsing type alias RedditPostData = { url : String , title : String , score : Int } redditPostData : Decoder RedditPostData redditPostData = RedditPostData `map` ("url" := string) `andMap` ("title" := string) `andMap` ("score" := int) type alias RedditPost = { data : RedditPostData } redditPost : Decoder RedditPost redditPost = RedditPost `map` ("data" := redditPostData ) type alias RedditListingData = { children : List RedditPost } redditListingData : Decoder RedditListingData redditListingData = RedditListingData `map` ("children" := list redditPost) type alias RedditListing = { data : RedditListingData } redditListing : Decoder RedditListing redditListing = RedditListing `map` ("data" := redditListingData) testRedditListing : RedditListing testRedditListing = { data = { children = [] } } -- The Reddit Homepage! redditUrl : String redditUrl = "https://www.reddit.com/.json" -- The main promise requestListing : String -> Task Error RedditListing requestListing url = Http.get redditListing url -- The query we send input query : Stream.Input String -- The results from the query input results : Stream (Result Error RedditListing) input results from Stream.map requestListing query.stream -- VIEW -- View an individual Reddit post viewPost : RedditPost -> Html viewPost { data } = let scoreStyle = style [("height", "50px") ,("flex", "1") ,("align-self", "center") ] itemStyle = style [("display", "flex") ,("margin-bottom", "10px") ] linkStyle = style [("flex", "8") ,("align-self", "flex-start") ] in li [ itemStyle ] [ div [ scoreStyle ] [ text (toString data.score) ] , a [ linkStyle , href data.url ] [ div [] [text data.title] ] ] elmLogo : Html elmLogo = let logoStyle = style [("height", "50px") ,("width", "50px") ,("min-height", "40px") ,("min-width", "40px") ,("flex", "1") ] in img [ src "http://elm-lang.org/logo.svg" , logoStyle ][] clientHeader : Html clientHeader = let headerStyle = style [ ("display", "flex") , ("align-items", "center") ] textStyle = style [ ("flex", "8") ] in header [ headerStyle ] [ elmLogo , div [ textStyle ] [ text "Reddit Client in Elm" ] ] -- Global view function view : Result Error RedditListing -> Html view listingResult = case listingResult of Err error -> button [ onClick (redditUrl >! query) ] [ text "Get Reddit Front Page" ] Ok listing -> div [] [ clientHeader , ul [] (List.map viewPost listing.data.children) ] -- Main Function main : Varying Html main = Varying.map view (Varying.fromStream (Err Http.Timeout) results)