diff --git a/stages/0/Main.elm b/stages/0/Main.elm deleted file mode 100644 index 56a2cad..0000000 --- a/stages/0/Main.elm +++ /dev/null @@ -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

ElmHub

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 diff --git a/stages/1/Main.elm b/stages/1/Main.elm index 6a605f8..56a2cad 100644 --- a/stages/1/Main.elm +++ b/stages/1/Main.elm @@ -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 - , 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 - } - ] + { result = + { id = 1 + , name = "TheSeamau5/elm-checkerboardgrid-tutorial" + , stars = 66 + } } -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

ElmHub

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 -}] + [ 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 + ] + ] ] -viewSearchResult : SearchResult -> Html -viewSearchResult result = - li - [] - [ span [ class "star-count" ] [ text (toString result.stars) ] - , a - [ href ("https://github.com/" ++ result.name), target "_blank" ] - [ text result.name ] - , text result.name - ] +main = + view model diff --git a/stages/8/Component/ElmHub.elm b/stages/10/Component/ElmHub.elm similarity index 100% rename from stages/8/Component/ElmHub.elm rename to stages/10/Component/ElmHub.elm diff --git a/stages/8/Component/SearchResult.elm b/stages/10/Component/SearchResult.elm similarity index 76% rename from stages/8/Component/SearchResult.elm rename to stages/10/Component/SearchResult.elm index 7e9b0aa..067ad36 100644 --- a/stages/8/Component/SearchResult.elm +++ b/stages/10/Component/SearchResult.elm @@ -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" ] ] diff --git a/stages/9/ElmHub.elm b/stages/10/ElmHub.elm similarity index 100% rename from stages/9/ElmHub.elm rename to stages/10/ElmHub.elm diff --git a/stages/10/Main.elm b/stages/10/Main.elm new file mode 100644 index 0000000..5b8e88e --- /dev/null +++ b/stages/10/Main.elm @@ -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 diff --git a/stages/0/README.md b/stages/10/README.md similarity index 79% rename from stages/0/README.md rename to stages/10/README.md index e4a727c..3f40f91 100644 --- a/stages/0/README.md +++ b/stages/10/README.md @@ -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 +``` diff --git a/stages/9/Stylesheets.elm b/stages/10/Stylesheets.elm similarity index 100% rename from stages/9/Stylesheets.elm rename to stages/10/Stylesheets.elm diff --git a/stages/9/css/Stylesheets.elm b/stages/10/css/Stylesheets.elm similarity index 100% rename from stages/9/css/Stylesheets.elm rename to stages/10/css/Stylesheets.elm diff --git a/stages/0/elm-hub.png b/stages/10/elm-hub.png similarity index 100% rename from stages/0/elm-hub.png rename to stages/10/elm-hub.png diff --git a/stages/0/elm-package.json b/stages/10/elm-package.json similarity index 59% rename from stages/0/elm-package.json rename to stages/10/elm-package.json index 2b33bdf..ea197b6 100644 --- a/stages/0/elm-package.json +++ b/stages/10/elm-package.json @@ -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" } diff --git a/stages/0/index.html b/stages/10/index.html similarity index 90% rename from stages/0/index.html rename to stages/10/index.html index d045ba4..5db9b93 100644 --- a/stages/0/index.html +++ b/stages/10/index.html @@ -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"); diff --git a/stages/0/style.css b/stages/10/style.css similarity index 100% rename from stages/0/style.css rename to stages/10/style.css diff --git a/stages/5/test/TestRunner.elm b/stages/10/test/TestRunner.elm similarity index 100% rename from stages/5/test/TestRunner.elm rename to stages/10/test/TestRunner.elm diff --git a/stages/10/test/Tests.elm b/stages/10/test/Tests.elm new file mode 100644 index 0000000..1781dd3 --- /dev/null +++ b/stages/10/test/Tests.elm @@ -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 diff --git a/stages/5/test/elm-package.json b/stages/10/test/elm-package.json similarity index 93% rename from stages/5/test/elm-package.json rename to stages/10/test/elm-package.json index a440485..e4c57c0 100644 --- a/stages/5/test/elm-package.json +++ b/stages/10/test/elm-package.json @@ -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", diff --git a/stages/2/Main.elm b/stages/2/Main.elm index c30d61a..3fda197 100644 --- a/stages/2/Main.elm +++ b/stages/2/Main.elm @@ -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 diff --git a/stages/2/README.md b/stages/2/README.md index f20ae3f..e4a727c 100644 --- a/stages/2/README.md +++ b/stages/2/README.md @@ -1,4 +1,4 @@ -Stage 2 +Stage 1 ======= ## Installation diff --git a/stages/2/elm-package.json b/stages/2/elm-package.json index 588e1cf..2b33bdf 100644 --- a/stages/2/elm-package.json +++ b/stages/2/elm-package.json @@ -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" } diff --git a/stages/3/Main.elm b/stages/3/Main.elm index a70be41..ca1ec18 100644 --- a/stages/3/Main.elm +++ b/stages/3/Main.elm @@ -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 diff --git a/stages/3/README.md b/stages/3/README.md index fcf6d94..f20ae3f 100644 --- a/stages/3/README.md +++ b/stages/3/README.md @@ -1,4 +1,4 @@ -Stage 3 +Stage 2 ======= ## Installation diff --git a/stages/4/Main.elm b/stages/4/Main.elm index f7355a6..a70be41 100644 --- a/stages/4/Main.elm +++ b/stages/4/Main.elm @@ -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 ) diff --git a/stages/4/README.md b/stages/4/README.md index 80fedb5..fcf6d94 100644 --- a/stages/4/README.md +++ b/stages/4/README.md @@ -1,4 +1,4 @@ -Stage 4 +Stage 3 ======= ## Installation diff --git a/stages/4/elm-package.json b/stages/4/elm-package.json index 5728b71..588e1cf 100644 --- a/stages/4/elm-package.json +++ b/stages/4/elm-package.json @@ -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" diff --git a/stages/5/Main.elm b/stages/5/Main.elm index fa4bada..f7355a6 100644 --- a/stages/5/Main.elm +++ b/stages/5/Main.elm @@ -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 ) diff --git a/stages/5/README.md b/stages/5/README.md index f50c90f..80fedb5 100644 --- a/stages/5/README.md +++ b/stages/5/README.md @@ -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 -``` diff --git a/stages/5/index.html b/stages/5/index.html index 5db9b93..d045ba4 100644 --- a/stages/5/index.html +++ b/stages/5/index.html @@ -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"); diff --git a/stages/5/test/Tests.elm b/stages/5/test/Tests.elm deleted file mode 100644 index b017897..0000000 --- a/stages/5/test/Tests.elm +++ /dev/null @@ -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 } - ] - ) - ] diff --git a/stages/6/README.md b/stages/6/README.md index 4e2d33e..f50c90f 100644 --- a/stages/6/README.md +++ b/stages/6/README.md @@ -20,6 +20,5 @@ elm live Main.elm --open -- --output=elm.js ```bash cd test -elm package install elm test TestRunner.elm ``` diff --git a/stages/6/test/Tests.elm b/stages/6/test/Tests.elm index 1470107..b017897 100644 --- a/stages/6/test/Tests.elm +++ b/stages/6/test/Tests.elm @@ -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 diff --git a/stages/6/test/elm-package.json b/stages/6/test/elm-package.json index e4c57c0..a440485 100644 --- a/stages/6/test/elm-package.json +++ b/stages/6/test/elm-package.json @@ -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", diff --git a/stages/7/ElmHub.elm b/stages/7/ElmHub.elm index 0fac7cd..d94fbca 100644 --- a/stages/7/ElmHub.elm +++ b/stages/7/ElmHub.elm @@ -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 ) diff --git a/stages/7/Main.elm b/stages/7/Main.elm index 290b13c..fa4bada 100644 --- a/stages/7/Main.elm +++ b/stages/7/Main.elm @@ -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 diff --git a/stages/7/index.html b/stages/7/index.html index 9ecef8f..5db9b93 100644 --- a/stages/7/index.html +++ b/stages/7/index.html @@ -4,37 +4,23 @@ ElmHub - + + + + -
diff --git a/stages/7/test/Tests.elm b/stages/7/test/Tests.elm index 1781dd3..1470107 100644 --- a/stages/7/test/Tests.elm +++ b/stages/7/test/Tests.elm @@ -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 = diff --git a/stages/5/ElmHub.elm b/stages/8/ElmHub.elm similarity index 83% rename from stages/5/ElmHub.elm rename to stages/8/ElmHub.elm index d94fbca..0fac7cd 100644 --- a/stages/5/ElmHub.elm +++ b/stages/8/ElmHub.elm @@ -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 ) diff --git a/stages/8/Main.elm b/stages/8/Main.elm index 5b8e88e..290b13c 100644 --- a/stages/8/Main.elm +++ b/stages/8/Main.elm @@ -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 diff --git a/stages/8/index.html b/stages/8/index.html index 5db9b93..9ecef8f 100644 --- a/stages/8/index.html +++ b/stages/8/index.html @@ -4,23 +4,37 @@ ElmHub + - - - - +
diff --git a/stages/9/Component/SearchResult.elm b/stages/9/Component/SearchResult.elm index 067ad36..7e9b0aa 100644 --- a/stages/9/Component/SearchResult.elm +++ b/stages/9/Component/SearchResult.elm @@ -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" ] ] diff --git a/stages/9/README.md b/stages/9/README.md index 3f40f91..4e2d33e 100644 --- a/stages/9/README.md +++ b/stages/9/README.md @@ -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 ``` diff --git a/stages/9/elm-package.json b/stages/9/elm-package.json index ea197b6..5728b71 100644 --- a/stages/9/elm-package.json +++ b/stages/9/elm-package.json @@ -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" }