From bc860d73fd43dab339fab08a06818277f9aee308 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 21 Aug 2016 12:58:52 -0700 Subject: [PATCH] Simplify part7 --- part7/ElmHub.elm | 132 -------------------------------------------- part7/Main.elm | 141 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 130 insertions(+), 143 deletions(-) delete mode 100644 part7/ElmHub.elm diff --git a/part7/ElmHub.elm b/part7/ElmHub.elm deleted file mode 100644 index 7c37af4..0000000 --- a/part7/ElmHub.elm +++ /dev/null @@ -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!") diff --git a/part7/Main.elm b/part7/Main.elm index 6c8a8fe..3e4fd9f 100644 --- a/part7/Main.elm +++ b/part7/Main.elm @@ -1,31 +1,150 @@ port module Main exposing (..) -import ElmHub exposing (..) 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 = Html.program { view = view - , update = update githubSearch + , update = update , init = ( initialModel, githubSearch (getQueryString initialModel.query) ) , subscriptions = \_ -> githubResponse decodeResponse } -decodeResponse : Json.Decode.Value -> Msg -decodeResponse json = - case Json.Decode.decodeValue responseDecoder json of - Err err -> - HandleSearchError (Just err) +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" - 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 githubResponse : (Json.Decode.Value -> msg) -> Sub msg +port githubResponse : (Value -> msg) -> Sub msg