module ElmHub exposing (..) import Html exposing (..) import Html.Attributes exposing (class, target, href, property, defaultValue) import Html.Events exposing (..) import Html.App as Html import Auth import Json.Decode exposing (Decoder) import Json.Decode.Pipeline exposing (..) import SearchOptions 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 , searchOptions : SearchOptions.Model } type alias SearchResult = { id : Int , name : String , stars : Int } initialModel : Model initialModel = { query = "tutorial" , results = [] , errorMessage = Nothing , searchOptions = SearchOptions.initialModel } viewAdvancedSearch : Model -> Html Msg viewAdvancedSearch model = SearchOptions.view model.searchOptions |> Html.map SearchOptionsMsg 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 | SearchOptionsMsg SearchOptions.Msg | SetQuery String | DeleteById Int | HandleSearchResponse (List SearchResult) | HandleSearchError (Maybe String) | DoNothing update : (String -> Cmd Msg) -> Msg -> Model -> ( Model, Cmd Msg ) update searchFeed msg model = case msg of Search -> ( model, searchFeed (getQueryString model.query) ) SearchOptionsMsg advancedSearchMsg -> let newSearchOptions = -- TODO call SearchOptions.update -- to determine our new searchOptions value. -- -- model.searchOptions SearchOptions.update advancedSearchMsg model.searchOptions in -- TODO update our model to use the newSearchOptions value above. -- ( model, Cmd.none ) ( { model | searchOptions = newSearchOptions }, Cmd.none ) SetQuery query -> ( { model | query = query }, Cmd.none ) HandleSearchResponse results -> ( { model | results = results }, Cmd.none ) HandleSearchError error -> ( { model | errorMessage = error }, Cmd.none ) DeleteById idToHide -> let newResults = model.results |> List.filter (\{ id } -> id /= idToHide) newModel = { model | results = newResults } in ( newModel, Cmd.none ) DoNothing -> ( model, Cmd.none ) decodeGithubResponse : Json.Decode.Value -> Msg decodeGithubResponse value = case Json.Decode.decodeValue responseDecoder value of Ok results -> HandleSearchResponse results Err err -> HandleSearchError (Just err)