Shift stages ahead one.

This commit is contained in:
Richard Feldman
2016-03-26 08:02:45 -07:00
parent dffa33f776
commit 236cd9057d
41 changed files with 440 additions and 443 deletions

View File

@@ -1,37 +0,0 @@
module Main (..) where
import Html exposing (..)
import Html.Attributes exposing (..)
model =
{ result =
{ id = 1
, name = "TheSeamau5/elm-checkerboardgrid-tutorial"
, stars = 66
}
}
view model =
div
[ class "content" ]
[ header
[]
[ -- TODO add the equivalent of <h1>ElmHub</h1> right before the tagline
span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
]
, ul
[ class "results" ]
[ li
[]
[ span [ class "star-count" ] [{- TODO display the number of stars -}]
-- TODO use the model to put a link here that points to
-- https://github.com/TheSeamau5/elm-checkerboardgrid-tutorial
]
]
]
main =
view model

View File

@@ -4,81 +4,34 @@ import Html exposing (..)
import Html.Attributes exposing (..)
main =
view model
type alias Model =
{ query : String
, results : List SearchResult
}
type alias SearchResult =
{ id : ResultId
, name : String
, stars : Int
}
type alias ResultId =
Int
{- See https://developer.github.com/v3/search/#example -}
model : Model
model =
{ query = "tutorial"
, results =
[ { id = 1
{ result =
{ 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 : Model -> Html
view model =
div
[ class "content" ]
[ header
[]
[ h1 [] [ text "ElmHub" ]
, span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
[ -- TODO add the equivalent of <h1>ElmHub</h1> right before the tagline
span [ class "tagline" ] [ text "Like GitHub, but for Elm things." ]
]
, ul
[ class "results" ]
[{- TODO use model.results and viewSearchResults to display results -}]
]
viewSearchResult : SearchResult -> Html
viewSearchResult result =
li
[ li
[]
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a
[ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, text result.name
[ span [ class "star-count" ] [{- TODO display the number of stars -}]
-- TODO use the model to put a link here that points to
-- https://github.com/TheSeamau5/elm-checkerboardgrid-tutorial
]
]
]
main =
view model

View File

@@ -26,8 +26,12 @@ type Action
update : Action -> Model -> ( Model, Effects Action )
update action model =
-- TODO make expand and collapse work
( model, Effects.none )
case action of
Expand ->
( { model | expanded = True }, Effects.none )
Collapse ->
( { model | expanded = False }, Effects.none )
view : Address Action -> Model -> Html
@@ -42,13 +46,11 @@ view address model =
]
[ text model.name ]
, button
-- TODO when the user clicks, send a Collapse action
[ class "hide-result" ]
[ class "hide-result", onClick address Collapse ]
[ text "X" ]
]
else
[ button
-- TODO when the user clicks, send an Expand action
[ class "expand-result" ]
[ class "expand-result", onClick address Expand ]
[ text "Show" ]
]

27
stages/10/Main.elm Normal file
View File

@@ -0,0 +1,27 @@
module Main (..) where
import StartApp
import Component.ElmHub exposing (..)
import Effects exposing (Effects)
import Task exposing (Task)
import Html exposing (Html)
main : Signal Html
main =
app.html
app : StartApp.App Model
app =
StartApp.start
{ view = view
, update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) )
, inputs = []
}
port tasks : Signal (Task Effects.Never ())
port tasks =
app.tasks

View File

@@ -1,4 +1,4 @@
Stage 1
Stage 5
=======
## Installation
@@ -15,3 +15,9 @@ to fail; in that case, just run `elm package install` again.)
```bash
elm live Main.elm --open -- --output=elm.js
```
## Compiling CSS
```bash
elm test css/Stylesheets.elm
```

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -9,7 +9,11 @@
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0"
"evancz/elm-effects": "2.0.0 <= v < 3.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",
"rtfeldman/elm-css": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}

View File

@@ -20,7 +20,7 @@
var app = Elm.fullscreen(Elm.Main, {});
// Uncomment this line and comment out the above to enable elm-reactor support.
// var app = Elm.fullscreenDebug("ElmHub", "ElmHub.elm");
// var app = Elm.fullscreenDebug("ElmHub", "Main.elm");
</script>
</html>

64
stages/10/test/Tests.elm Normal file
View File

@@ -0,0 +1,64 @@
module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode as Decode
import Json.Encode as Encode
import Check exposing (Claim, Evidence, check, claim, that, is, for)
import Check.Producer exposing (..)
import Check.Test exposing (evidenceToTest)
import String
import ElmHub exposing (..)
import Random
all : Test
all =
suite
"Decoding responses from GitHub"
[ test "they can decode empty responses"
<| let
emptyResponse =
"""{ "items": [] }"""
in
assertEqual
(Decode.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
(Decode.decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
, (claim "they can decode individual search results"
`that` (\( id, name, stars ) -> encodeAndDecode id name stars)
`is` (\( id, name, stars ) -> Ok (SearchResult id name stars))
`for` tuple3 ( int, string, int )
)
|> check 100 defaultSeed
|> evidenceToTest
]
encodeAndDecode : Int -> String -> Int -> Result String SearchResult
encodeAndDecode id name stars =
[ ( "id", Encode.int id )
, ( "full_name", Encode.string name )
, ( "stargazers_count", Encode.int stars )
]
|> Encode.object
|> Encode.encode 0
|> Decode.decodeString searchResultDecoder
defaultSeed =
Random.initialSeed 42

View File

@@ -9,6 +9,7 @@
],
"exposed-modules": [],
"dependencies": {
"NoRedInk/elm-check": "3.0.0 <= v < 4.0.0",
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0",

View File

@@ -2,17 +2,6 @@ module Main (..) where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import StartApp.Simple as StartApp
import Signal exposing (Address)
main =
StartApp.start
{ view = view
, update = update
, model = initialModel
}
type alias Model =
@@ -32,12 +21,9 @@ type alias ResultId =
Int
{- See https://developer.github.com/v3/search/#example -}
initialModel : Model
initialModel =
{-| TODO add a type annotation to this function
-}
model =
{ query = "tutorial"
, results =
[ { id = 1
@@ -64,8 +50,9 @@ initialModel =
}
view : Address Action -> Model -> Html
view address model =
{-| TODO add a type annotation to this function
-}
view model =
div
[ class "content" ]
[ header
@@ -75,32 +62,24 @@ view address model =
]
, ul
[ class "results" ]
(List.map (viewSearchResult address) model.results)
[{- TODO use model.results and viewSearchResults to display results -}]
]
viewSearchResult : Address Action -> SearchResult -> Html
viewSearchResult address result =
{-| TODO add a type annotation to this function
-}
viewSearchResult result =
li
[]
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a
[ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, button
-- TODO add an onClick handler that sends a DELETE_BY_ID action
[ class "hide-result" ]
[ text "X" ]
, text result.name
]
type alias Action =
{ -- TODO implement this type alias
}
update : Action -> Model -> Model
update action model =
-- TODO if we receive a DELETE_BY_ID action,
-- build a new model without the given ID present anymore.
model
{-| TODO add a type annotation to this function
-}
main =
view model

View File

@@ -1,4 +1,4 @@
Stage 2
Stage 1
=======
## Installation

View File

@@ -9,9 +9,7 @@
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0",
"evancz/elm-html": "4.0.0 <= v < 5.0.0",
"evancz/start-app": "2.0.0 <= v < 3.0.0"
"evancz/elm-html": "4.0.0 <= v < 5.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}

View File

@@ -3,26 +3,15 @@ module Main (..) where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import StartApp
import Task exposing (Task)
import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=))
import Json.Encode
import StartApp.Simple as StartApp
import Signal exposing (Address)
main : Signal Html
main =
app.html
app : StartApp.App Model
app =
StartApp.start
{ view = view
, update = update
, init = ( initialModel, Effects.none )
, inputs = []
, model = initialModel
}
@@ -43,10 +32,6 @@ type alias ResultId =
Int
{- See https://developer.github.com/v3/search/#example -}
initialModel : Model
initialModel =
{ query = "tutorial"
@@ -84,46 +69,34 @@ view address model =
[ h1 [] [ text "ElmHub" ]
, 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
[ class "results" ]
(List.map (viewSearchResult address) model.results)
]
onInput address wrap =
on "input" targetValue (\val -> Signal.message address (wrap val))
defaultValue str =
property "defaultValue" (Json.Encode.string str)
viewSearchResult : Address Action -> SearchResult -> Html
viewSearchResult address result =
li
[]
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a
[ href ("https://github.com/" ++ result.name)
, target "_blank"
]
[ href ("https://github.com/" ++ result.name), target "_blank" ]
[ text result.name ]
, button
-- TODO add an onClick handler that sends a DeleteById action
-- TODO add an onClick handler that sends a DELETE_BY_ID action
[ class "hide-result" ]
[ text "X" ]
]
type Action
= SetQuery String
| DeleteById ResultId
type alias Action =
{ -- TODO implement this type alias
}
update : Action -> Model -> ( Model, Effects Action )
update : Action -> Model -> Model
update action model =
-- TODO write a case-expression that makes SetQuery set the query
-- and DeleteById delete the appropriate result
( model, Effects.none )
-- TODO if we receive a DELETE_BY_ID action,
-- build a new model without the given ID present anymore.
model

View File

@@ -1,4 +1,4 @@
Stage 3
Stage 2
=======
## Installation

View File

@@ -4,7 +4,6 @@ import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import StartApp
import Http
import Task exposing (Task)
import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=))
@@ -22,47 +21,11 @@ app =
StartApp.start
{ view = view
, update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) )
, init = ( initialModel, Effects.none )
, 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
-- See https://developer.github.com/v3/search/#example
("TODO what field goes here?" := Json.Decode.int)
("TODO what field goes here?" := Json.Decode.string)
("TODO what field goes here?" := Json.Decode.int)
type alias Model =
{ query : String
, results : List SearchResult
@@ -80,10 +43,35 @@ type alias ResultId =
Int
{- See https://developer.github.com/v3/search/#example -}
initialModel : Model
initialModel =
{ 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
}
]
}
@@ -97,7 +85,7 @@ view address model =
, 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" ]
, button [ class "search-button" ] [ text "Search" ]
, ul
[ class "results" ]
(List.map (viewSearchResult address) model.results)
@@ -123,40 +111,19 @@ viewSearchResult address result =
]
[ text result.name ]
, button
[ class "hide-result", onClick address (DeleteById result.id) ]
-- TODO add an onClick handler that sends a DeleteById action
[ class "hide-result" ]
[ text "X" ]
]
type Action
= Search
| SetQuery String
= SetQuery String
| DeleteById ResultId
| SetResults (List SearchResult)
update : Action -> Model -> ( Model, Effects Action )
update action model =
case action of
Search ->
( model, Effects.task (searchFeed model.query) )
SetQuery query ->
( { model | query = query }, Effects.none )
SetResults results ->
let
newModel =
{ model | results = results }
in
( newModel, Effects.none )
DeleteById idToHide ->
let
newResults =
List.filter (\{ id } -> id /= idToHide) model.results
newModel =
{ model | results = newResults }
in
( newModel, Effects.none )
-- TODO write a case-expression that makes SetQuery set the query
-- and DeleteById delete the appropriate result
( model, Effects.none )

View File

@@ -1,4 +1,4 @@
Stage 4
Stage 3
=======
## Installation

View File

@@ -11,7 +11,6 @@
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.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"
},
"elm-version": "0.16.0 <= v < 0.17.0"

View File

@@ -1,10 +1,15 @@
module Main (..) where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import StartApp
import ElmHub exposing (..)
import Effects exposing (Effects)
import Http
import Task exposing (Task)
import Html exposing (Html)
import Effects exposing (Effects)
import Json.Decode exposing (Decoder, (:=))
import Json.Encode
import Signal exposing (Address)
main : Signal Html
@@ -25,3 +30,133 @@ app =
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
-- See https://developer.github.com/v3/search/#example
("TODO what field goes here?" := Json.Decode.int)
("TODO what field goes here?" := Json.Decode.string)
("TODO what field goes here?" := Json.Decode.int)
type alias Model =
{ query : String
, results : List SearchResult
}
type alias SearchResult =
{ id : ResultId
, name : String
, stars : Int
}
type alias ResultId =
Int
initialModel : Model
initialModel =
{ query = "tutorial"
, results = []
}
view : Address Action -> Model -> Html
view address model =
div
[ class "content" ]
[ header
[]
[ h1 [] [ text "ElmHub" ]
, 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
[ class "results" ]
(List.map (viewSearchResult address) model.results)
]
onInput address wrap =
on "input" targetValue (\val -> Signal.message address (wrap val))
defaultValue str =
property "defaultValue" (Json.Encode.string str)
viewSearchResult : Address Action -> SearchResult -> Html
viewSearchResult address 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 address (DeleteById result.id) ]
[ text "X" ]
]
type Action
= Search
| SetQuery String
| DeleteById ResultId
| SetResults (List SearchResult)
update : Action -> Model -> ( Model, Effects Action )
update action model =
case action of
Search ->
( model, Effects.task (searchFeed model.query) )
SetQuery query ->
( { model | query = query }, Effects.none )
SetResults results ->
let
newModel =
{ model | results = results }
in
( newModel, Effects.none )
DeleteById idToHide ->
let
newResults =
List.filter (\{ id } -> id /= idToHide) model.results
newModel =
{ model | results = newResults }
in
( newModel, Effects.none )

View File

@@ -1,4 +1,4 @@
Stage 5
Stage 4
=======
## Installation
@@ -15,10 +15,3 @@ to fail; in that case, just run `elm package install` again.)
```bash
elm live Main.elm --open -- --output=elm.js
```
## Running Tests
```bash
cd test
elm test TestRunner.elm
```

View File

@@ -20,7 +20,7 @@
var app = Elm.fullscreen(Elm.Main, {});
// Uncomment this line and comment out the above to enable elm-reactor support.
// var app = Elm.fullscreenDebug("ElmHub", "Main.elm");
// var app = Elm.fullscreenDebug("ElmHub", "ElmHub.elm");
</script>
</html>

View File

@@ -1,34 +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: what goes here? -})
, test "they can decode responses with results in them"
<| let
response =
"""{ "items": [
/* TODO: dummy JSON goes here */
] }"""
in
assertEqual
(decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
]

View File

@@ -20,6 +20,5 @@ elm live Main.elm --open -- --output=elm.js
```bash
cd test
elm package install
elm test TestRunner.elm
```

View File

@@ -2,14 +2,7 @@ module Tests (..) where
import ElmTest exposing (..)
import ElmHub exposing (responseDecoder)
import Json.Decode as Decode
import Json.Encode as Encode
import Check exposing (Claim, Evidence, check, claim, that, is, for)
import Check.Producer exposing (..)
import Check.Test exposing (evidenceToTest)
import String
import ElmHub exposing (..)
import Random
import Json.Decode exposing (decodeString)
all : Test
@@ -22,43 +15,20 @@ all =
"""{ "items": [] }"""
in
assertEqual
(Decode.decodeString responseDecoder emptyResponse)
(Ok [])
(decodeString responseDecoder emptyResponse)
({- TODO: what goes here? -})
, 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 }
/* TODO: dummy JSON goes here */
] }"""
in
assertEqual
(Decode.decodeString responseDecoder response)
(decodeString responseDecoder response)
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
, (claim "they can decode individual search results"
`that` ({- TODO call encodeAndDecode -})
`is` (\( id, name, stars ) -> Ok (SearchResult id name stars))
`for` tuple3 ( int, string, int )
)
|> check 100 defaultSeed
|> evidenceToTest
]
encodeAndDecode : Int -> String -> Int -> Result String SearchResult
encodeAndDecode id name stars =
-- TODO: finish turning this into a JSON String,
-- then Decode it with searchResultDecoder
[ ( "id", Encode.int id )
, ( "full_name", Encode.string name )
, ( "stargazers_count", Encode.int stars )
]
|> Encode.object
defaultSeed =
Random.initialSeed 42

View File

@@ -9,7 +9,6 @@
],
"exposed-modules": [],
"dependencies": {
"NoRedInk/elm-check": "3.0.0 <= v < 4.0.0",
"deadfoxygrandpa/elm-test": "3.1.1 <= v < 4.0.0",
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.0 <= v < 3.0.0",

View File

@@ -11,8 +11,8 @@ import Json.Encode
import Signal exposing (Address)
searchFeed : Address String -> String -> Task x Action
searchFeed address query =
searchFeed : String -> Task x Action
searchFeed query =
let
-- See https://developer.github.com/v3/search/#example for how to customize!
url =
@@ -20,13 +20,11 @@ searchFeed address query =
++ query
++ "+language:elm&sort=stars&order=desc"
-- These only talk to JavaScript ports now. They don't
-- actually do any actions themselves.
task =
Signal.send address query
|> Task.map (\_ -> DoNothing)
Http.get responseDecoder url
|> Task.map SetResults
in
Task.onError task (\_ -> Task.succeed DoNothing)
Task.onError task (\_ -> Task.succeed (SetResults []))
responseDecoder : Decoder (List SearchResult)
@@ -113,14 +111,13 @@ type Action
| SetQuery String
| DeleteById ResultId
| SetResults (List SearchResult)
| DoNothing
update : Address String -> Action -> Model -> ( Model, Effects Action )
update searchAddress action model =
update : Action -> Model -> ( Model, Effects Action )
update action model =
case action of
Search ->
( model, Effects.task (searchFeed searchAddress model.query) )
( model, Effects.task (searchFeed model.query) )
SetQuery query ->
( { model | query = query }, Effects.none )
@@ -142,6 +139,3 @@ update searchAddress action model =
{ model | results = newResults }
in
( newModel, Effects.none )
DoNothing ->
( model, Effects.none )

View File

@@ -5,9 +5,6 @@ import ElmHub exposing (..)
import Effects exposing (Effects)
import Task exposing (Task)
import Html exposing (Html)
import Signal
import Json.Encode
import Json.Decode
main : Signal Html
@@ -19,40 +16,12 @@ app : StartApp.App Model
app =
StartApp.start
{ view = view
, update = update search.address
, init = ( initialModel, Effects.task (searchFeed search.address initialModel.query) )
, inputs = [ responseActions ]
, update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) )
, inputs = []
}
port tasks : Signal (Task Effects.Never ())
port tasks =
app.tasks
search : Signal.Mailbox String
search =
Signal.mailbox ""
port githubSearch : Signal String
port githubSearch =
search.signal
responseActions : Signal Action
responseActions =
Signal.map decodeGithubResponse githubResponse
decodeGithubResponse : Json.Encode.Value -> Action
decodeGithubResponse value =
case Json.Decode.decodeValue responseDecoder value of
Ok results ->
SetResults results
Err _ ->
DoNothing
port githubResponse : Signal Json.Encode.Value

View File

@@ -4,37 +4,23 @@
<head>
<meta charset="UTF-8">
<title>ElmHub</title>
<script type="text/javascript" src="github.js"></script>
<script type="text/javascript" src="elm.js"></script>
<!-- Uncomment the below line to enable elm-reactor support. -->
<!-- <script type="text/javascript" src="/_reactor/debug.js"></script> -->
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="elm-hub.png">
</head>
<body>
<div id="elm-landing-pad"></div>
</body>
<script type="text/javascript">
// documentation: https://github.com/michael/github
var github = new Github();
var app = Elm.fullscreen(Elm.Main, {});
var app = Elm.embed(
Elm.Main,
document.getElementById("elm-landing-pad"),
{githubResponse: []});
function searchGithub(query) {
console.log("Searching for", query);
var search = github.getSearch(query);
search.repositories({}, function (err, repositories) {
console.log("Got response", repositories);
// TODO: app.ports.portNameGoesHere.send(repositories);
});
}
// TODO app.ports.portNameGoesHere.subscribe(searchGithub);
// Uncomment this line and comment out the above to enable elm-reactor support.
// var app = Elm.fullscreenDebug("ElmHub", "Main.elm");
</script>
</html>

View File

@@ -40,7 +40,7 @@ all =
]
)
, (claim "they can decode individual search results"
`that` (\( id, name, stars ) -> encodeAndDecode id name stars)
`that` ({- TODO call encodeAndDecode -})
`is` (\( id, name, stars ) -> Ok (SearchResult id name stars))
`for` tuple3 ( int, string, int )
)
@@ -51,13 +51,13 @@ all =
encodeAndDecode : Int -> String -> Int -> Result String SearchResult
encodeAndDecode id name stars =
-- TODO: finish turning this into a JSON String,
-- then Decode it with searchResultDecoder
[ ( "id", Encode.int id )
, ( "full_name", Encode.string name )
, ( "stargazers_count", Encode.int stars )
]
|> Encode.object
|> Encode.encode 0
|> Decode.decodeString searchResultDecoder
defaultSeed =

View File

@@ -11,8 +11,8 @@ import Json.Encode
import Signal exposing (Address)
searchFeed : String -> Task x Action
searchFeed query =
searchFeed : Address String -> String -> Task x Action
searchFeed address query =
let
-- See https://developer.github.com/v3/search/#example for how to customize!
url =
@@ -20,11 +20,13 @@ searchFeed query =
++ query
++ "+language:elm&sort=stars&order=desc"
-- These only talk to JavaScript ports now. They don't
-- actually do any actions themselves.
task =
Http.get responseDecoder url
|> Task.map SetResults
Signal.send address query
|> Task.map (\_ -> DoNothing)
in
Task.onError task (\_ -> Task.succeed (SetResults []))
Task.onError task (\_ -> Task.succeed DoNothing)
responseDecoder : Decoder (List SearchResult)
@@ -111,13 +113,14 @@ type Action
| SetQuery String
| DeleteById ResultId
| SetResults (List SearchResult)
| DoNothing
update : Action -> Model -> ( Model, Effects Action )
update action model =
update : Address String -> Action -> Model -> ( Model, Effects Action )
update searchAddress action model =
case action of
Search ->
( model, Effects.task (searchFeed model.query) )
( model, Effects.task (searchFeed searchAddress model.query) )
SetQuery query ->
( { model | query = query }, Effects.none )
@@ -139,3 +142,6 @@ update action model =
{ model | results = newResults }
in
( newModel, Effects.none )
DoNothing ->
( model, Effects.none )

View File

@@ -1,10 +1,13 @@
module Main (..) where
import StartApp
import Component.ElmHub exposing (..)
import ElmHub exposing (..)
import Effects exposing (Effects)
import Task exposing (Task)
import Html exposing (Html)
import Signal
import Json.Encode
import Json.Decode
main : Signal Html
@@ -16,12 +19,40 @@ app : StartApp.App Model
app =
StartApp.start
{ view = view
, update = update
, init = ( initialModel, Effects.task (searchFeed initialModel.query) )
, inputs = []
, update = update search.address
, init = ( initialModel, Effects.task (searchFeed search.address initialModel.query) )
, inputs = [ responseActions ]
}
port tasks : Signal (Task Effects.Never ())
port tasks =
app.tasks
search : Signal.Mailbox String
search =
Signal.mailbox ""
port githubSearch : Signal String
port githubSearch =
search.signal
responseActions : Signal Action
responseActions =
Signal.map decodeGithubResponse githubResponse
decodeGithubResponse : Json.Encode.Value -> Action
decodeGithubResponse value =
case Json.Decode.decodeValue responseDecoder value of
Ok results ->
SetResults results
Err _ ->
DoNothing
port githubResponse : Signal Json.Encode.Value

View File

@@ -4,23 +4,37 @@
<head>
<meta charset="UTF-8">
<title>ElmHub</title>
<script type="text/javascript" src="github.js"></script>
<script type="text/javascript" src="elm.js"></script>
<!-- Uncomment the below line to enable elm-reactor support. -->
<!-- <script type="text/javascript" src="/_reactor/debug.js"></script> -->
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="elm-hub.png">
</head>
<body>
<div id="elm-landing-pad"></div>
</body>
<script type="text/javascript">
var app = Elm.fullscreen(Elm.Main, {});
// documentation: https://github.com/michael/github
var github = new Github();
// Uncomment this line and comment out the above to enable elm-reactor support.
// var app = Elm.fullscreenDebug("ElmHub", "Main.elm");
var app = Elm.embed(
Elm.Main,
document.getElementById("elm-landing-pad"),
{githubResponse: []});
function searchGithub(query) {
console.log("Searching for", query);
var search = github.getSearch(query);
search.repositories({}, function (err, repositories) {
console.log("Got response", repositories);
// TODO: app.ports.portNameGoesHere.send(repositories);
});
}
// TODO app.ports.portNameGoesHere.subscribe(searchGithub);
</script>
</html>

View File

@@ -26,12 +26,8 @@ type Action
update : Action -> Model -> ( Model, Effects Action )
update action model =
case action of
Expand ->
( { model | expanded = True }, Effects.none )
Collapse ->
( { model | expanded = False }, Effects.none )
-- TODO make expand and collapse work
( model, Effects.none )
view : Address Action -> Model -> Html
@@ -46,11 +42,13 @@ view address model =
]
[ text model.name ]
, button
[ class "hide-result", onClick address Collapse ]
-- TODO when the user clicks, send a Collapse action
[ class "hide-result" ]
[ text "X" ]
]
else
[ button
[ class "expand-result", onClick address Expand ]
-- TODO when the user clicks, send an Expand action
[ class "expand-result" ]
[ text "Show" ]
]

View File

@@ -16,8 +16,10 @@ to fail; in that case, just run `elm package install` again.)
elm live Main.elm --open -- --output=elm.js
```
## Compiling CSS
## Running Tests
```bash
elm test css/Stylesheets.elm
cd test
elm package install
elm test TestRunner.elm
```

View File

@@ -12,8 +12,7 @@
"evancz/elm-effects": "2.0.0 <= v < 3.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",
"rtfeldman/elm-css": "1.0.0 <= v < 2.0.0"
"evancz/start-app": "2.0.0 <= v < 3.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}