Use Elm Architecture in stages/8

This commit is contained in:
Richard Feldman
2016-03-06 08:58:11 -08:00
parent 72e5d3ac44
commit a6fc81e481
3 changed files with 89 additions and 39 deletions

View File

@@ -1,15 +1,15 @@
module ElmHub (..) where
module Component.ElmHub (..) where
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, (:=))
import Json.Encode
import Signal exposing (Address)
import Component.SearchResult exposing (ResultId)
searchFeed : String -> Task x Action
@@ -28,37 +28,27 @@ searchFeed query =
Task.onError task (\_ -> Task.succeed (SetResults []))
responseDecoder : Decoder (List SearchResult)
responseDecoder : Decoder (List Component.SearchResult.Model)
responseDecoder =
"items" := Json.Decode.list searchResultDecoder
searchResultDecoder : Decoder SearchResult
searchResultDecoder : Decoder Component.SearchResult.Model
searchResultDecoder =
Json.Decode.object3
SearchResult
Json.Decode.object4
Component.SearchResult.Model
("id" := Json.Decode.int)
("full_name" := Json.Decode.string)
("stargazers_count" := Json.Decode.int)
(Json.Decode.succeed True)
type alias Model =
{ query : String
, results : List SearchResult
, results : List Component.SearchResult.Model
}
type alias SearchResult =
{ id : ResultId
, name : String
, stars : Int
}
type alias ResultId =
Int
initialModel : Model
initialModel =
{ query = "tutorial"
@@ -91,28 +81,18 @@ defaultValue str =
property "defaultValue" (Json.Encode.string str)
viewSearchResult : Address Action -> SearchResult -> Html
viewSearchResult : Address Action -> Component.SearchResult.Model -> Html
viewSearchResult address result =
li
[]
[ span [ class "star-count" ] [ text (toString result.stars) ]
, a
[ href ("https://github.com/" ++ result.name)
, class "result-name"
, target "_blank"
]
[ text result.name ]
, button
[ class "hide-result", onClick address (HideById result.id) ]
[ text "X" ]
]
Component.SearchResult.view
(Signal.forwardTo address (UpdateSearchResult result.id))
result
type Action
= Search
| SetQuery String
| HideById ResultId
| SetResults (List SearchResult)
| SetResults (List Component.SearchResult.Model)
| UpdateSearchResult ResultId Component.SearchResult.Action
update : Action -> Model -> ( Model, Effects Action )
@@ -131,13 +111,26 @@ update action model =
in
( newModel, Effects.none )
HideById idToHide ->
UpdateSearchResult id childAction ->
let
newResults =
updateResult childModel =
if childModel.id == id then
let
( newChildModel, childEffects ) =
Component.SearchResult.update childAction childModel
in
( newChildModel
, Effects.map (UpdateSearchResult id) childEffects
)
else
( childModel, Effects.none )
( newResults, effects ) =
model.results
|> List.filter (\{ id } -> id /= idToHide)
|> List.map updateResult
|> List.unzip
newModel =
{ model | results = newResults }
in
( newModel, Effects.none )
( newModel, Effects.batch effects )

View File

@@ -0,0 +1,57 @@
module Component.SearchResult (..) where
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Signal exposing (Address)
import Effects exposing (Effects)
type alias Model =
{ id : Int
, name : String
, stars : Int
, expanded : Bool
}
type alias ResultId =
Int
type Action
= Expand
| Collapse
update : Action -> Model -> ( Model, Effects Action )
update action model =
case action of
Expand ->
( { model | expanded = True }, Effects.none )
Collapse ->
( { model | expanded = False }, Effects.none )
view : Address Action -> Model -> Html
view address model =
li
[]
<| if model.expanded then
[ span [ class "star-count" ] [ text (toString model.stars) ]
, a
[ href ("https://github.com/" ++ model.name)
, class "result-name"
, target "_blank"
]
[ text model.name ]
, button
[ class "hide-result", onClick address Collapse ]
[ text "X" ]
]
else
[ button
[ class "expand-result", onClick address Expand ]
[ text "Show" ]
]

View File

@@ -1,7 +1,7 @@
module Main (..) where
import StartApp
import ElmHub exposing (..)
import Component.ElmHub exposing (..)
import Effects exposing (Effects)
import Task exposing (Task)
import Html exposing (Html)