From 9c278e2574f3b4f3d73d5bed692b74670fb62050 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 6 Sep 2016 00:33:00 -0700 Subject: [PATCH] Update part10 to do advanced search options --- part10/ElmHub.elm | 138 +++++++++++++++++++++++++++++----------------- part10/Main.elm | 2 +- part10/style.css | 38 +++++++++++++ 3 files changed, 127 insertions(+), 51 deletions(-) diff --git a/part10/ElmHub.elm b/part10/ElmHub.elm index a4be55d..06bf04e 100644 --- a/part10/ElmHub.elm +++ b/part10/ElmHub.elm @@ -1,23 +1,12 @@ module ElmHub exposing (..) import Html exposing (..) -import Html.Attributes exposing (class, target, href, defaultValue, type', checked) +import Html.Attributes exposing (class, target, href, defaultValue, type', checked, placeholder, value) import Html.Events exposing (..) import Html.App as Html import Auth import Json.Decode exposing (Decoder) import Json.Decode.Pipeline exposing (..) -import String - - -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) @@ -43,9 +32,9 @@ type alias Model = type alias SearchOptions = { sort : String - , order : String + , ascending : Bool , searchIn : List String - , includeForks : Bool + , searchInDescription : Bool , userFilter : String } @@ -63,10 +52,10 @@ initialModel = , results = [] , errorMessage = Nothing , options = - { sort = "" - , order = "" + { sort = "stars" + , ascending = False , searchIn = [] - , includeForks = True + , searchInDescription = True , userFilter = "" } } @@ -89,7 +78,7 @@ update searchFeed msg model = -- -- HINT: calling updateOptions will save a lot of time here! Search -> - ( model, searchFeed (getQueryString model.query) ) + ( model, searchFeed (getQueryString model) ) SetQuery query -> ( { model | query = query }, Cmd.none ) @@ -115,6 +104,22 @@ update searchFeed msg model = ( model, Cmd.none ) +updateOptions : OptionsMsg -> SearchOptions -> SearchOptions +updateOptions optionsMsg options = + case optionsMsg of + SetSort sort -> + { options | sort = sort } + + SetAscending ascending -> + { options | ascending = ascending } + + SetSearchInDescription searchInDescription -> + { options | searchInDescription = searchInDescription } + + SetUserFilter userFilter -> + { options | userFilter = userFilter } + + view : Model -> Html Msg view model = div [ class "content" ] @@ -122,9 +127,13 @@ view model = [ h1 [] [ text "ElmHub" ] , span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ] ] - -- TODO call viewOptions here. Use Html.map to avoid a type mismatch! - , input [ class "search-query", onInput SetQuery, defaultValue model.query ] [] - , button [ class "search-button", onClick Search ] [ text "Search" ] + , div [ class "search" ] + [ text "TODO replace this text node with a call to viewOptions. Use Html.map to avoid a type mismatch!" + , div [ class "search-input" ] + [ 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) ] @@ -153,39 +162,40 @@ viewSearchResult result = type OptionsMsg = SetSort String - | SetOrder String - | SetSearchIn (List String) - | SetIncludeForks Bool + | SetAscending Bool + | SetSearchInDescription Bool | SetUserFilter String -updateOptions : OptionsMsg -> SearchOptions -> SearchOptions -updateOptions optionsMsg options = - case optionsMsg of - SetSort sort -> - { options | sort = sort } - - SetOrder order -> - { options | order = order } - - SetSearchIn searchIn -> - { options | searchIn = searchIn } - - SetIncludeForks includeForks -> - { options | includeForks = includeForks } - - SetUserFilter userFilter -> - { options | userFilter = userFilter } - - viewOptions : SearchOptions -> Html OptionsMsg -viewOptions model = - div [] - [ input [ type' "text", defaultValue model.sort, onInput SetSort ] [] - , input [ type' "text", defaultValue model.order, onInput SetOrder ] [] - , input [ type' "text", defaultValue (String.join " " model.searchIn) ] [] - , input [ type' "checkbox", checked model.includeForks ] [] - , input [ type' "text", defaultValue model.userFilter, onInput SetUserFilter ] [] +viewOptions opts = + div [ class "search-options" ] + [ div [ class "search-option" ] + [ label [ class "top-label" ] [ text "Sort by" ] + , select [ onChange SetSort, value opts.sort ] + [ option [ value "stars" ] [ text "Stars" ] + , option [ value "forks" ] [ text "Forks" ] + , option [ value "updated" ] [ text "Updated" ] + ] + ] + , div [ class "search-option" ] + [ label [ class "top-label" ] [ text "Owned by" ] + , input + [ type' "text" + , placeholder "Enter a username" + , defaultValue opts.userFilter + , onInput SetUserFilter + ] + [] + ] + , label [ class "search-option" ] + [ input [ type' "checkbox", checked opts.ascending, onCheck SetAscending ] [] + , text "Sort ascending" + ] + , label [ class "search-option" ] + [ input [ type' "checkbox", checked opts.searchInDescription, onCheck SetSearchInDescription ] [] + , text "Search in description" + ] ] @@ -197,3 +207,31 @@ decodeGithubResponse value = Err err -> HandleSearchError (Just err) + + +onChange : (String -> msg) -> Attribute msg +onChange toMsg = + on "change" (Json.Decode.map toMsg Html.Events.targetValue) + + +getQueryString : Model -> String +getQueryString model = + -- See https://developer.github.com/v3/search/#example for how to customize! + "access_token=" + ++ Auth.token + ++ "&q=" + ++ model.query + ++ (if model.options.searchInDescription then + "+in:name,description" + else + "+in:name" + ) + ++ "+language:elm" + ++ "&sort=" + ++ model.options.sort + ++ "&order=" + ++ (if model.options.ascending then + "asc" + else + "desc" + ) diff --git a/part10/Main.elm b/part10/Main.elm index 6c8a8fe..10bb678 100644 --- a/part10/Main.elm +++ b/part10/Main.elm @@ -10,7 +10,7 @@ main = Html.program { view = view , update = update githubSearch - , init = ( initialModel, githubSearch (getQueryString initialModel.query) ) + , init = ( initialModel, githubSearch (getQueryString initialModel) ) , subscriptions = \_ -> githubResponse decodeResponse } diff --git a/part10/style.css b/part10/style.css index d030733..26acacd 100644 --- a/part10/style.css +++ b/part10/style.css @@ -99,3 +99,41 @@ button:focus, input:focus { font-family: monospace; font-size: 18px; } + +.search-input { + display: block; + float: left; + width: 50%; +} + +.search-options { + position: relative; + float: right; + width: 50%; + box-sizing: border-box; + padding: 20px; +} + +.search-option { + display: block; + float: left; + width: 50%; + box-sizing: border-box; +} + +.search-option input[type="text"] { + padding: 5px; + box-sizing: border-box; + width: 90%; +} + +.search:after { + content: ""; + display: table; + clear: both; +} + +.top-label { + display: block; + color: #555; +}