Created
July 25, 2017 10:58
-
-
Save dillonchanis/ba7942e65eca2496616ac3c9e101eb33 to your computer and use it in GitHub Desktop.
Elm HN Client
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
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