Skip to content

Instantly share code, notes, and snippets.

@dillonchanis
Created July 25, 2017 10:58
Show Gist options
  • Save dillonchanis/ba7942e65eca2496616ac3c9e101eb33 to your computer and use it in GitHub Desktop.
Save dillonchanis/ba7942e65eca2496616ac3c9e101eb33 to your computer and use it in GitHub Desktop.
Elm HN Client
module HackerNews exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Http
import Json.Decode as Decode exposing (Decoder, field)
-- MODELS
type AppState
= ViewingAll
| Reading
type alias Model =
{ stories : List Story
, appState : AppState
, storyIds : List Int
}
type alias Story =
{ by : String
, descendants : Int
, id : Int
, kids : List Int
, score : Int
, time : Int
, title : String
, url : String
}
initialModel : Model
initialModel =
{ stories =
[ { by = "dhouston"
, descendants = 71
, id = 8863
, kids = [ 8952, 9224, 8917, 8884, 8887, 8943, 8869, 8958, 9005, 9671, 8940, 9067, 8908, 9055, 8865, 8881, 8872, 8873, 8955, 10403, 8903, 8928, 9125, 8998, 8901, 8902, 8907, 8894, 8878, 8870, 8980, 8934, 8876 ]
, score = 111
, time = 1175714200
, title = "My YC app: Dropbox - Throw away your USB drive"
, url = "http://www.getdropbox.com/u/2/screencast.html"
}
, { by = "thelarkinn"
, descendants = 257
, id = 14779881
, kids = []
, score = 845
, time = 1500165816
, title = "Apache Foundation disallows use of the Facebook “BSD+Patent” license"
, url = "https://issues.apache.org/jira/browse/LEGAL-303?focusedCommentId=16088663&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16088663"
}
]
, appState = ViewingAll
, storyIds = []
}
-- API CONSTANTS
apiGetItem : Int -> String
apiGetItem id =
"https://hacker-news.firebaseio.com/v0/item/" ++ (toString id) ++ ".json"
apiTopStoriesUrl : String
apiTopStoriesUrl =
"https://hacker-news.firebaseio.com/v0/topstories.json"
-- UPDATES
type Msg
= Top (Result Http.Error (List Int))
| TopStories (Result Http.Error (List Story))
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Top (Ok topStories) ->
( model, Cmd.batch (fetchTopStories topStories) )
Top (Err error) ->
let
_ =
Debug.log "ERROR: " error
in
( model, Cmd.none )
TopStories (Ok allStories) ->
let
_ =
Debug.log "All Stories: " allStories
in
model ! [ Cmd.none ]
TopStories (Err error) ->
let
_ =
Debug.log "ERROR: " error
in
model ! [ Cmd.none ]
-- DECODERS/ENCODERS
storyDecoder : Decoder Story
storyDecoder =
Decode.map8 Story
(field "by" Decode.string)
(field "descendants" Decode.int)
(field "id" Decode.int)
(field "kids" (Decode.list Decode.int))
(field "score" Decode.int)
(field "time" Decode.int)
(field "title" Decode.string)
(field "url" Decode.string)
-- COMMANDS
fetchStoryById topStoryId =
(Decode.list storyDecoder)
|> Http.get (apiGetItem topStoryId)
|> Http.send TopStories
fetchTopStories topStoriesIds =
List.map fetchStoryById topStoriesIds
getTopStories : Cmd Msg
getTopStories =
(Decode.list Decode.int)
|> Http.get apiTopStoriesUrl
|> Http.send Top
-- VIEW
viewHeader : Html msg
viewHeader =
header []
[ h1 [ class "h1" ] [ text "Hacker News" ]
]
viewFooter : Html msg
viewFooter =
footer [ class "footer" ]
[ div [ class "has-text-centered" ]
[ p [] [ text "Visit ", a [ href "https://news.ycombinator.com/", target "_blank" ] [ text "Hacker News" ] ]
, p [] [ text "Powered by ", a [ href "http://elm-lang.org/", target "_blank" ] [ text "Elm" ], text "." ]
, p [] [ a [ href "https://github.com/dillonchanis", class "icon" ] [ i [ class "fa fa-github" ] [] ] ]
]
]
viewStoryPostInfo : Story -> Html msg
viewStoryPostInfo story =
div []
[ p [ class "text-muted" ]
[ text ((toString story.score) ++ " points by ")
, a [ href ("https://news.ycombinator.com/user?id=" ++ story.by) ] [ text story.by ]
, span [ class "text-muted" ] [ text (" | " ++ (toString story.descendants) ++ " comments") ]
]
]
viewSingleStory : Story -> Html msg
viewSingleStory story =
li [ class "story-item elevation" ]
[ h2 [ class "h2" ] [ text story.title ]
, viewStoryPostInfo story
]
viewStoryList : List Story -> Html msg
viewStoryList stories =
let
storyList =
List.map viewSingleStory stories
in
ul [] storyList
view : Model -> Html msg
view model =
div []
[ section [ class "section" ]
[ div [ class "container" ] [ viewHeader, viewStoryList model.stories, viewStory model.storyIds ] ]
, viewFooter
]
init : ( Model, Cmd Msg )
init =
( initialModel, getTopStories )
main : Program Never Model Msg
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = (always Sub.none)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment