Simplify part7

This commit is contained in:
Richard Feldman
2016-08-21 12:58:52 -07:00
parent f08599de5e
commit bc860d73fd
2 changed files with 130 additions and 143 deletions

View File

@@ -1,132 +0,0 @@
module ElmHub exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue)
import Html.Events exposing (..)
import Auth
import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (..)
getQueryString : String -> String
getQueryString query =
-- See https://developer.github.com/v3/search/#example for how to customize!
"access_token="
++ Auth.token
++ "&q="
++ query
++ "+language:elm&sort=stars&order=desc"
responseDecoder : Decoder (List SearchResult)
responseDecoder =
Json.Decode.at [ "items" ] (Json.Decode.list searchResultDecoder)
searchResultDecoder : Decoder SearchResult
searchResultDecoder =
decode SearchResult
|> required "id" Json.Decode.int
|> required "full_name" Json.Decode.string
|> required "stargazers_count" Json.Decode.int
type alias Model =
{ query : String
, results : List SearchResult
, errorMessage : Maybe String
}
type alias SearchResult =
{ id : Int
, name : String
, stars : Int
}
initialModel : Model
initialModel =
{ query = "tutorial"
, results = []
, errorMessage = Nothing
}
view : Model -> Html Msg
view model =
div [ class "content" ]
[ header []
[ h1 [] [ text "ElmHub" ]
, span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
]
, input [ class "search-query", onInput SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick Search ] [ text "Search" ]
, viewErrorMessage model.errorMessage
, ul [ class "results" ] (List.map viewSearchResult model.results)
]
viewErrorMessage : Maybe String -> Html a
viewErrorMessage errorMessage =
case errorMessage of
Just message ->
div [ class "error" ] [ text message ]
Nothing ->
text ""
viewSearchResult : SearchResult -> Html Msg
viewSearchResult result =
li []
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a [ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, button [ class "hide-result", onClick (DeleteById result.id) ]
[ text "X" ]
]
type Msg
= Search
| SetQuery String
| DeleteById Int
| HandleSearchResponse (List SearchResult)
| HandleSearchError (Maybe String)
update : (String -> Cmd Msg) -> Msg -> Model -> ( Model, Cmd Msg )
update searchFeed msg model =
case msg of
Search ->
( model, searchFeed (getQueryString model.query) )
SetQuery query ->
( { model | query = query }, Cmd.none )
HandleSearchResponse results ->
( { model | results = results }, Cmd.none )
HandleSearchError error ->
( { model | errorMessage = error }, Cmd.none )
DeleteById idToDelete ->
let
newResults =
model.results
|> List.filter (\{ id } -> id /= idToDelete)
newModel =
{ model | results = newResults }
in
( newModel, Cmd.none )
decodeGithubResponse : Json.Decode.Value -> Msg
decodeGithubResponse value =
-- TODO use Json.Decode.DecodeValue to decode the response into a Msg.
--
-- Hint: look at the definition of Msg and
-- the definition of responseDecoder
HandleSearchError (Just "TODO decode the response!")

View File

@@ -1,31 +1,150 @@
port module Main exposing (..) port module Main exposing (..)
import ElmHub exposing (..)
import Html.App as Html import Html.App as Html
import Json.Decode import Json.Decode exposing (..)
import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue)
import Html.Events exposing (..)
import Auth
import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (..)
main : Program Never main : Program Never
main = main =
Html.program Html.program
{ view = view { view = view
, update = update githubSearch , update = update
, init = ( initialModel, githubSearch (getQueryString initialModel.query) ) , init = ( initialModel, githubSearch (getQueryString initialModel.query) )
, subscriptions = \_ -> githubResponse decodeResponse , subscriptions = \_ -> githubResponse decodeResponse
} }
decodeResponse : Json.Decode.Value -> Msg getQueryString : String -> String
decodeResponse json = getQueryString query =
case Json.Decode.decodeValue responseDecoder json of -- See https://developer.github.com/v3/search/#example for how to customize!
Err err -> "access_token="
HandleSearchError (Just err) ++ Auth.token
++ "&q="
++ query
++ "+language:elm&sort=stars&order=desc"
Ok results ->
HandleSearchResponse results responseDecoder : Decoder (List SearchResult)
responseDecoder =
Json.Decode.at [ "items" ] (Json.Decode.list searchResultDecoder)
searchResultDecoder : Decoder SearchResult
searchResultDecoder =
decode SearchResult
|> required "id" Json.Decode.int
|> required "full_name" Json.Decode.string
|> required "stargazers_count" Json.Decode.int
type alias Model =
{ query : String
, results : List SearchResult
, errorMessage : Maybe String
}
type alias SearchResult =
{ id : Int
, name : String
, stars : Int
}
initialModel : Model
initialModel =
{ query = "tutorial"
, results = []
, errorMessage = Nothing
}
view : Model -> Html Msg
view model =
div [ class "content" ]
[ header []
[ h1 [] [ text "ElmHub" ]
, span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
]
, input [ class "search-query", onInput SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick Search ] [ text "Search" ]
, viewErrorMessage model.errorMessage
, ul [ class "results" ] (List.map viewSearchResult model.results)
]
viewErrorMessage : Maybe String -> Html a
viewErrorMessage errorMessage =
case errorMessage of
Just message ->
div [ class "error" ] [ text message ]
Nothing ->
text ""
viewSearchResult : SearchResult -> Html Msg
viewSearchResult result =
li []
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a [ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, button [ class "hide-result", onClick (DeleteById result.id) ]
[ text "X" ]
]
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Search ->
( model, githubSearch (getQueryString model.query) )
SetQuery query ->
( { model | query = query }, Cmd.none )
HandleSearchResponse results ->
( { model | results = results }, Cmd.none )
HandleSearchError error ->
( { model | errorMessage = error }, Cmd.none )
DeleteById idToDelete ->
let
newResults =
model.results
|> List.filter (\{ id } -> id /= idToDelete)
newModel =
{ model | results = newResults }
in
( newModel, Cmd.none )
type Msg
= Search
| SetQuery String
| DeleteById Int
| HandleSearchResponse (List SearchResult)
| HandleSearchError (Maybe String)
decodeResponse : Value -> Msg
decodeResponse json =
-- TODO use decodeValue to decode the response into a Msg.
--
-- Hint: look at the definition of Msg and
-- the definition of responseDecoder
HandleSearchError (Just "TODO decode the response!")
port githubSearch : String -> Cmd msg port githubSearch : String -> Cmd msg
port githubResponse : (Json.Decode.Value -> msg) -> Sub msg port githubResponse : (Value -> msg) -> Sub msg