forked from cadey/xesite
81 lines
2.2 KiB
Plaintext
81 lines
2.2 KiB
Plaintext
module App.BlogIndex where
|
|
|
|
import Control.Monad.Aff (attempt)
|
|
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
|
|
import Data.Either (Either(Left, Right), either)
|
|
import DOM (DOM)
|
|
import Network.HTTP.Affjax (AJAX, get)
|
|
import Prelude (($), bind, map, const, show, (<>), pure, (<<<))
|
|
import Pux (EffModel, noEffects)
|
|
import Pux.Html (Html, br, div, h1, ol, li, button, text, span, p)
|
|
import Pux.Html.Attributes (key, className)
|
|
import Pux.Html.Events (onClick)
|
|
|
|
data Action = RequestPosts
|
|
| ReceivePosts (Either String Posts)
|
|
|
|
type State =
|
|
{ posts :: Posts
|
|
, status :: String }
|
|
|
|
data Post = Post
|
|
{ title :: String
|
|
, link :: String
|
|
, summary :: String
|
|
, date :: String }
|
|
|
|
type Posts = Array Post
|
|
|
|
instance decodeJsonPost :: DecodeJson Post where
|
|
decodeJson json = do
|
|
obj <- decodeJson json
|
|
title <- obj .? "title"
|
|
link <- obj .? "link"
|
|
summ <- obj .? "summary"
|
|
date <- obj .? "date"
|
|
pure $ Post { title: title, link: link, summary: summ, date: date }
|
|
|
|
init :: State
|
|
init =
|
|
{ posts: []
|
|
, status: "Loading..." }
|
|
|
|
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
|
|
update (ReceivePosts (Left err)) state =
|
|
noEffects $ state { status = ("error: " <> err) }
|
|
update (ReceivePosts (Right posts)) state =
|
|
noEffects $ state { posts = posts, status = "Posts" }
|
|
update RequestPosts state =
|
|
{ state: state { status = "Fetching posts..." }
|
|
, effects: [ do
|
|
res <- attempt $ get "/api/blog/posts"
|
|
let decode r = decodeJson r.response :: Either String Posts
|
|
let posts = either (Left <<< show) decode res
|
|
pure $ ReceivePosts posts
|
|
]
|
|
}
|
|
|
|
post :: Post -> Html Action
|
|
post (Post state) =
|
|
div
|
|
[ className "col s4" ]
|
|
[ div
|
|
[ className "card pink lighten-1" ]
|
|
[ div
|
|
[ className "card-content black-text" ]
|
|
[ span [ className "card-title" ] [ text state.title ]
|
|
, br [] []
|
|
, p [] [ text ("Posted on: " <> state.date) ]
|
|
, span [] [ text state.summary ]
|
|
]
|
|
]
|
|
]
|
|
|
|
view :: State -> Html Action
|
|
view state =
|
|
div
|
|
[]
|
|
[ h1 [] [ text state.status ]
|
|
, button [ onClick (const RequestPosts) ] [ text "Fetch posts" ]
|
|
, div [ className "row" ] $ map post state.posts ]
|