Update things

This commit is contained in:
Richard Feldman
2016-03-05 08:24:42 -08:00
parent 9f3d21bfbf
commit 0015a48e52
19 changed files with 87 additions and 409 deletions

View File

@@ -4,18 +4,14 @@
"repository": "https://github.com/rtfeldman/elm-workshop.git", "repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"source-directories": [ "source-directories": [
"src", "src"
"test"
], ],
"exposed-modules": [], "exposed-modules": [],
"dependencies": { "dependencies": {
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0", "elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0", "evancz/elm-effects": "2.0.0 <= v < 3.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0", "evancz/elm-html": "4.0.0 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0", "evancz/start-app": "2.0.0 <= v < 3.0.0"
"evancz/start-app": "2.0.0 <= v < 3.0.0",
"laszlopandy/elm-console": "1.0.3 <= v < 2.0.0"
}, },
"elm-version": "0.16.0 <= v < 0.17.0" "elm-version": "0.16.0 <= v < 0.17.0"
} }

View File

@@ -19,7 +19,6 @@
}, },
"homepage": "https://github.com/rtfeldman/elm-workshop#readme", "homepage": "https://github.com/rtfeldman/elm-workshop#readme",
"devDependencies": { "devDependencies": {
"elm-live": "2.0.4", "elm-live": "2.0.4"
"elm-test": "0.16.1-alpha3"
} }
} }

View File

@@ -3,8 +3,7 @@ module ElmHub (..) where
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (..) import Html.Events exposing (..)
import StartApp import StartApp.Simple as StartApp
import Http
import Task exposing (Task) import Task exposing (Task)
import Effects exposing (Effects) import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=)) import Json.Decode exposing (Decoder, (:=))
@@ -12,56 +11,14 @@ import Json.Encode
import Signal exposing (Address) import Signal exposing (Address)
main : Signal Html
main = main =
app.html
app : StartApp.App Model
app =
StartApp.start StartApp.start
{ view = view { view = view
, update = update , update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) ) , model = initialModel
, inputs = []
} }
port tasks : Signal (Task Effects.Never ())
port tasks =
app.tasks
searchFeed : String -> Task x Action
searchFeed query =
let
-- See https://developer.github.com/v3/search/#example for how to customize!
url =
"https://api.github.com/search/repositories?q="
++ query
++ "+language:elm&sort=stars&order=desc"
task =
Http.get responseDecoder url
|> Task.map SetResults
in
Task.onError task (\_ -> Task.succeed (SetResults []))
responseDecoder : Decoder (List SearchResult)
responseDecoder =
"items" := Json.Decode.list searchResultDecoder
searchResultDecoder : Decoder SearchResult
searchResultDecoder =
Json.Decode.object3
SearchResult
("id" := Json.Decode.int)
("full_name" := Json.Decode.string)
("stargazers_count" := Json.Decode.int)
type alias Model = type alias Model =
{ query : String { query : String
, results : List SearchResult , results : List SearchResult
@@ -82,11 +39,31 @@ type alias ResultId =
initialModel : Model initialModel : Model
initialModel = initialModel =
{ query = "tutorial" { query = "tutorial"
, results = [] , results =
[ { id = 1
, name = "TheSeamau5/elm-checkerboardgrid-tutorial"
, stars = 66
}
, { id = 2
, name = "grzegorzbalcerek/elm-by-example"
, stars = 41
}
, { id = 3
, name = "sporto/elm-tutorial-app"
, stars = 35
}
, { id = 4
, name = "jvoigtlaender/Elm-Tutorium"
, stars = 10
}
, { id = 5
, name = "sporto/elm-tutorial-assets"
, stars = 7
}
]
} }
view : Address Action -> Model -> Html
view address model = view address model =
div div
[ class "content" ] [ class "content" ]
@@ -95,66 +72,21 @@ view address 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." ]
] ]
, input [ class "search-query", onInput address SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick address Search ] [ text "Search" ]
, ul , ul
[ class "results" ] [ class "results" ]
(List.map viewSearchResult model.results) [{- TODO use model.results and viewSearchResults to display results -}]
] ]
onInput address wrap =
on "input" targetValue (\val -> Signal.message address (wrap val))
defaultValue str =
property "defaultValue" (Json.Encode.string str)
viewSearchResult : SearchResult -> Html viewSearchResult : SearchResult -> Html
viewSearchResult result = viewSearchResult result =
li li
[] []
[ span [ class "star-count" ] [ text (toString result.stars) ] [ span [ class "star-count" ] [ text (toString result.stars) ]
, a -- TODO replace the following span with a link that opens in a new window!
[ href ("https://github.com/" ++ result.name) , span [ class "result-name" ] [ text result.name ]
, class "result-name"
, target "_blank"
]
[ text result.name ]
] ]
type Action
= Search
| SetQuery String
| HideById ResultId
| SetResults (List SearchResult)
update : Action -> Model -> ( Model, Effects Action )
update action model = update action model =
case action of model
Search ->
( model, Effects.task (searchFeed (Debug.log "searching for" model.query)) )
SetQuery query ->
( { model | query = query }, Effects.none )
SetResults results ->
let
newModel =
{ model | results = results }
in
( newModel, Effects.none )
HideById idToHide ->
let
newResults =
model.results
|> List.filter (\{ id } -> id /= idToHide)
newModel =
{ model | results = newResults }
in
( newModel, Effects.none )

View File

@@ -1,15 +0,0 @@
module Main where
import Signal exposing (Signal)
import ElmTest exposing (consoleRunner)
import Console exposing (IO, run)
import Task
import Tests
console : IO ()
console = consoleRunner Tests.all
port runner : Signal (Task.Task x ())
port runner = run console

View File

@@ -1,35 +0,0 @@
module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode exposing (decodeString)
all : Test
all =
suite
"Decoding responses from GitHub"
[ test "they can decode empty responses"
<| let
emptyResponse =
"""{ "items": [] }"""
in
assertEqual
(decodeString responseDecoder emptyResponse)
(Ok [])
, test "they can decode responses with results in them"
<| let
response =
"""{ "items": [
{ "id": 5, "full_name": "foo", "stargazers_count": 42 },
{ "id": 3, "full_name": "bar", "stargazers_count": 77 }
] }"""
in
assertEqual
(decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
]

View File

@@ -4,18 +4,14 @@
"repository": "https://github.com/rtfeldman/elm-workshop.git", "repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"source-directories": [ "source-directories": [
"src", "src"
"test"
], ],
"exposed-modules": [], "exposed-modules": [],
"dependencies": { "dependencies": {
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0", "elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0", "evancz/elm-effects": "2.0.0 <= v < 3.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0", "evancz/elm-html": "4.0.0 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0", "evancz/start-app": "2.0.0 <= v < 3.0.0"
"evancz/start-app": "2.0.0 <= v < 3.0.0",
"laszlopandy/elm-console": "1.0.3 <= v < 2.0.0"
}, },
"elm-version": "0.16.0 <= v < 0.17.0" "elm-version": "0.16.0 <= v < 0.17.0"
} }

View File

@@ -19,7 +19,6 @@
}, },
"homepage": "https://github.com/rtfeldman/elm-workshop#readme", "homepage": "https://github.com/rtfeldman/elm-workshop#readme",
"devDependencies": { "devDependencies": {
"elm-live": "2.0.4", "elm-live": "2.0.4"
"elm-test": "0.16.1-alpha3"
} }
} }

View File

@@ -3,8 +3,7 @@ module ElmHub (..) where
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (..) import Html.Events exposing (..)
import StartApp import StartApp.Simple as StartApp
import Http
import Task exposing (Task) import Task exposing (Task)
import Effects exposing (Effects) import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=)) import Json.Decode exposing (Decoder, (:=))
@@ -12,56 +11,14 @@ import Json.Encode
import Signal exposing (Address) import Signal exposing (Address)
main : Signal Html
main = main =
app.html
app : StartApp.App Model
app =
StartApp.start StartApp.start
{ view = view { view = view
, update = update , update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) ) , model = initialModel
, inputs = []
} }
port tasks : Signal (Task Effects.Never ())
port tasks =
app.tasks
searchFeed : String -> Task x Action
searchFeed query =
let
-- See https://developer.github.com/v3/search/#example for how to customize!
url =
"https://api.github.com/search/repositories?q="
++ query
++ "+language:elm&sort=stars&order=desc"
task =
Http.get responseDecoder url
|> Task.map SetResults
in
Task.onError task (\_ -> Task.succeed (SetResults []))
responseDecoder : Decoder (List SearchResult)
responseDecoder =
"items" := Json.Decode.list searchResultDecoder
searchResultDecoder : Decoder SearchResult
searchResultDecoder =
Json.Decode.object3
SearchResult
("id" := Json.Decode.int)
("full_name" := Json.Decode.string)
("stargazers_count" := Json.Decode.int)
type alias Model = type alias Model =
{ query : String { query : String
, results : List SearchResult , results : List SearchResult
@@ -82,7 +39,28 @@ type alias ResultId =
initialModel : Model initialModel : Model
initialModel = initialModel =
{ query = "tutorial" { query = "tutorial"
, results = [] , results =
[ { id = 1
, name = "TheSeamau5/elm-checkerboardgrid-tutorial"
, stars = 66
}
, { id = 2
, name = "grzegorzbalcerek/elm-by-example"
, stars = 41
}
, { id = 3
, name = "sporto/elm-tutorial-app"
, stars = 35
}
, { id = 4
, name = "jvoigtlaender/Elm-Tutorium"
, stars = 10
}
, { id = 5
, name = "sporto/elm-tutorial-assets"
, stars = 7
}
]
} }
@@ -95,11 +73,9 @@ view address 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." ]
] ]
, input [ class "search-query", onInput address SetQuery, defaultValue model.query ] []
, button [ class "search-button", onClick address Search ] [ text "Search" ]
, ul , ul
[ class "results" ] [ class "results" ]
(List.map viewSearchResult model.results) (List.map (viewSearchResult address) model.results)
] ]
@@ -111,8 +87,8 @@ defaultValue str =
property "defaultValue" (Json.Encode.string str) property "defaultValue" (Json.Encode.string str)
viewSearchResult : SearchResult -> Html viewSearchResult : Address Action -> SearchResult -> Html
viewSearchResult result = viewSearchResult address result =
li li
[] []
[ span [ class "star-count" ] [ text (toString result.stars) ] [ span [ class "star-count" ] [ text (toString result.stars) ]
@@ -122,39 +98,27 @@ viewSearchResult result =
, target "_blank" , target "_blank"
] ]
[ text result.name ] [ text result.name ]
, button
-- TODO add an onClick handler that sends a HideById action
[ class "hide-result" ]
[ text "X" ]
] ]
type Action type alias Action =
= Search { actionType : String
| SetQuery String , payload : Int
| HideById ResultId }
| SetResults (List SearchResult)
update : Action -> Model -> ( Model, Effects Action ) update : Action -> Model -> Model
update action model = update action model =
case action of if action.actionType == "HIDE_BY_ID" then
Search ->
( model, Effects.task (searchFeed (Debug.log "searching for" model.query)) )
SetQuery query ->
( { model | query = query }, Effects.none )
SetResults results ->
let let
-- TODO build a new model without the given ID present anymore.
newModel = newModel =
{ model | results = results } model
in in
( newModel, Effects.none ) newModel
else
HideById idToHide -> model
let
newResults =
model.results
|> List.filter (\{ id } -> id /= idToHide)
newModel =
{ model | results = newResults }
in
( newModel, Effects.none )

View File

@@ -1,15 +0,0 @@
module Main where
import Signal exposing (Signal)
import ElmTest exposing (consoleRunner)
import Console exposing (IO, run)
import Task
import Tests
console : IO ()
console = consoleRunner Tests.all
port runner : Signal (Task.Task x ())
port runner = run console

View File

@@ -1,35 +0,0 @@
module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode exposing (decodeString)
all : Test
all =
suite
"Decoding responses from GitHub"
[ test "they can decode empty responses"
<| let
emptyResponse =
"""{ "items": [] }"""
in
assertEqual
(decodeString responseDecoder emptyResponse)
(Ok [])
, test "they can decode responses with results in them"
<| let
response =
"""{ "items": [
{ "id": 5, "full_name": "foo", "stargazers_count": 42 },
{ "id": 3, "full_name": "bar", "stargazers_count": 77 }
] }"""
in
assertEqual
(decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
]

View File

@@ -4,18 +4,14 @@
"repository": "https://github.com/rtfeldman/elm-workshop.git", "repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"source-directories": [ "source-directories": [
"src", "src"
"test"
], ],
"exposed-modules": [], "exposed-modules": [],
"dependencies": { "dependencies": {
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0", "elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0", "evancz/elm-effects": "2.0.0 <= v < 3.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0", "evancz/elm-html": "4.0.0 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0", "evancz/start-app": "2.0.0 <= v < 3.0.0"
"evancz/start-app": "2.0.0 <= v < 3.0.0",
"laszlopandy/elm-console": "1.0.3 <= v < 2.0.0"
}, },
"elm-version": "0.16.0 <= v < 0.17.0" "elm-version": "0.16.0 <= v < 0.17.0"
} }

View File

@@ -19,7 +19,6 @@
}, },
"homepage": "https://github.com/rtfeldman/elm-workshop#readme", "homepage": "https://github.com/rtfeldman/elm-workshop#readme",
"devDependencies": { "devDependencies": {
"elm-live": "2.0.4", "elm-live": "2.0.4"
"elm-test": "0.16.1-alpha3"
} }
} }

View File

@@ -4,7 +4,6 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (..) import Html.Events exposing (..)
import StartApp import StartApp
import Http
import Task exposing (Task) import Task exposing (Task)
import Effects exposing (Effects) import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=)) import Json.Decode exposing (Decoder, (:=))
@@ -81,6 +80,8 @@ view address 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." ]
] ]
, input [ class "search-query", onInput address SetQuery, defaultValue model.query ] []
, button [ class "search-button" ] [ text "Search" ]
, ul , ul
[ class "results" ] [ class "results" ]
(List.map (viewSearchResult address) model.results) (List.map (viewSearchResult address) model.results)

View File

@@ -1,15 +0,0 @@
module Main where
import Signal exposing (Signal)
import ElmTest exposing (consoleRunner)
import Console exposing (IO, run)
import Task
import Tests
console : IO ()
console = consoleRunner Tests.all
port runner : Signal (Task.Task x ())
port runner = run console

View File

@@ -1,35 +0,0 @@
module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode exposing (decodeString)
all : Test
all =
suite
"Decoding responses from GitHub"
[ test "they can decode empty responses"
<| let
emptyResponse =
"""{ "items": [] }"""
in
assertEqual
(decodeString responseDecoder emptyResponse)
(Ok [])
, test "they can decode responses with results in them"
<| let
response =
"""{ "items": [
{ "id": 5, "full_name": "foo", "stargazers_count": 42 },
{ "id": 3, "full_name": "bar", "stargazers_count": 77 }
] }"""
in
assertEqual
(decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
]

View File

@@ -4,18 +4,15 @@
"repository": "https://github.com/rtfeldman/elm-workshop.git", "repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"source-directories": [ "source-directories": [
"src", "src"
"test"
], ],
"exposed-modules": [], "exposed-modules": [],
"dependencies": { "dependencies": {
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0", "elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0", "evancz/elm-effects": "2.0.0 <= v < 3.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0", "evancz/elm-html": "4.0.0 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0", "evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/start-app": "2.0.0 <= v < 3.0.0", "evancz/start-app": "2.0.0 <= v < 3.0.0"
"laszlopandy/elm-console": "1.0.3 <= v < 2.0.0"
}, },
"elm-version": "0.16.0 <= v < 0.17.0" "elm-version": "0.16.0 <= v < 0.17.0"
} }

View File

@@ -19,7 +19,6 @@
}, },
"homepage": "https://github.com/rtfeldman/elm-workshop#readme", "homepage": "https://github.com/rtfeldman/elm-workshop#readme",
"devDependencies": { "devDependencies": {
"elm-live": "2.0.4", "elm-live": "2.0.4"
"elm-test": "0.16.1-alpha3"
} }
} }

View File

@@ -1,15 +0,0 @@
module Main where
import Signal exposing (Signal)
import ElmTest exposing (consoleRunner)
import Console exposing (IO, run)
import Task
import Tests
console : IO ()
console = consoleRunner Tests.all
port runner : Signal (Task.Task x ())
port runner = run console

View File

@@ -1,35 +0,0 @@
module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode exposing (decodeString)
all : Test
all =
suite
"Decoding responses from GitHub"
[ test "they can decode empty responses"
<| let
emptyResponse =
"""{ "items": [] }"""
in
assertEqual
(decodeString responseDecoder emptyResponse)
({- TODO: put the expected result here instead -})
, test "they can decode responses with results in them"
<| let
response =
"""{
... json goes here ...
}"""
expected =
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
in
assertEqual
(decodeString responseDecoder response)
({- TODO: put the expected result here instead -})
]