Update part10 to do advanced search options

This commit is contained in:
Richard Feldman
2016-09-06 00:33:00 -07:00
parent 5c162a8d39
commit 9c278e2574
3 changed files with 127 additions and 51 deletions

View File

@@ -1,23 +1,12 @@
module ElmHub exposing (..) module ElmHub exposing (..)
import Html 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.Events exposing (..)
import Html.App as Html import Html.App as Html
import Auth import Auth
import Json.Decode exposing (Decoder) import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (..) 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) responseDecoder : Decoder (List SearchResult)
@@ -43,9 +32,9 @@ type alias Model =
type alias SearchOptions = type alias SearchOptions =
{ sort : String { sort : String
, order : String , ascending : Bool
, searchIn : List String , searchIn : List String
, includeForks : Bool , searchInDescription : Bool
, userFilter : String , userFilter : String
} }
@@ -63,10 +52,10 @@ initialModel =
, results = [] , results = []
, errorMessage = Nothing , errorMessage = Nothing
, options = , options =
{ sort = "" { sort = "stars"
, order = "" , ascending = False
, searchIn = [] , searchIn = []
, includeForks = True , searchInDescription = True
, userFilter = "" , userFilter = ""
} }
} }
@@ -89,7 +78,7 @@ update searchFeed msg model =
-- --
-- HINT: calling updateOptions will save a lot of time here! -- HINT: calling updateOptions will save a lot of time here!
Search -> Search ->
( model, searchFeed (getQueryString model.query) ) ( model, searchFeed (getQueryString model) )
SetQuery query -> SetQuery query ->
( { model | query = query }, Cmd.none ) ( { model | query = query }, Cmd.none )
@@ -115,6 +104,22 @@ update searchFeed msg model =
( model, Cmd.none ) ( 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 -> Html Msg
view model = view model =
div [ class "content" ] div [ class "content" ]
@@ -122,9 +127,13 @@ view model =
[ h1 [] [ text "ElmHub" ] [ h1 [] [ text "ElmHub" ]
, span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ] , span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
] ]
-- TODO call viewOptions here. Use Html.map to avoid a type mismatch! , div [ class "search" ]
, input [ class "search-query", onInput SetQuery, defaultValue model.query ] [] [ text "TODO replace this text node with a call to viewOptions. Use Html.map to avoid a type mismatch!"
, button [ class "search-button", onClick Search ] [ text "Search" ] , div [ class "search-input" ]
[ input [ class "search-query", onInput SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick Search ] [ text "Search" ]
]
]
, viewErrorMessage model.errorMessage , viewErrorMessage model.errorMessage
, ul [ class "results" ] (List.map viewSearchResult model.results) , ul [ class "results" ] (List.map viewSearchResult model.results)
] ]
@@ -153,39 +162,40 @@ viewSearchResult result =
type OptionsMsg type OptionsMsg
= SetSort String = SetSort String
| SetOrder String | SetAscending Bool
| SetSearchIn (List String) | SetSearchInDescription Bool
| SetIncludeForks Bool
| SetUserFilter String | 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 : SearchOptions -> Html OptionsMsg
viewOptions model = viewOptions opts =
div [] div [ class "search-options" ]
[ input [ type' "text", defaultValue model.sort, onInput SetSort ] [] [ div [ class "search-option" ]
, input [ type' "text", defaultValue model.order, onInput SetOrder ] [] [ label [ class "top-label" ] [ text "Sort by" ]
, input [ type' "text", defaultValue (String.join " " model.searchIn) ] [] , select [ onChange SetSort, value opts.sort ]
, input [ type' "checkbox", checked model.includeForks ] [] [ option [ value "stars" ] [ text "Stars" ]
, input [ type' "text", defaultValue model.userFilter, onInput SetUserFilter ] [] , 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 -> Err err ->
HandleSearchError (Just 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"
)

View File

@@ -10,7 +10,7 @@ main =
Html.program Html.program
{ view = view { view = view
, update = update githubSearch , update = update githubSearch
, init = ( initialModel, githubSearch (getQueryString initialModel.query) ) , init = ( initialModel, githubSearch (getQueryString initialModel) )
, subscriptions = \_ -> githubResponse decodeResponse , subscriptions = \_ -> githubResponse decodeResponse
} }

View File

@@ -99,3 +99,41 @@ button:focus, input:focus {
font-family: monospace; font-family: monospace;
font-size: 18px; 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;
}