frontend: render blog posts

This commit is contained in:
Cadey Ratio 2016-12-14 11:54:17 -08:00
parent 4a52f5006b
commit 81206835d5
6 changed files with 109 additions and 7 deletions

View File

@ -0,0 +1,9 @@
// Module App.BlogEntry
exports.mdify = function(id) {
var converter = new showdown.Converter()
elem = document.getElementById(id);
md = elem.innerHTML;
elem.innerHTML = converter.makeHtml(md);
return "done :)";
}

View File

@ -0,0 +1,79 @@
module App.BlogEntry where
import Control.Monad.Aff (attempt)
import DOM (DOM)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Either (Either(..), either)
import Data.Maybe (Maybe(..))
import Network.HTTP.Affjax (AJAX, get)
import Prelude (bind, pure, show, ($), (<>), (<<<))
import Pux (EffModel, noEffects)
import Pux.Html (Html, div, h1, h2, p, text)
import Pux.Html.Attributes (id_)
data Action = RequestPost
| ReceivePost (Either String Post)
| RenderPost
type State =
{ status :: String
, hack :: String
, id :: Maybe Int
, post :: Post
, name :: String }
data Post = Post
{ title :: String
, body :: String
, date :: String }
instance decodeJsonPost :: DecodeJson Post where
decodeJson json = do
obj <- decodeJson json
title <- obj .? "title"
body <- obj .? "body"
date <- obj .? "date"
pure $ Post { title: title, body: body, date: date }
init :: State
init =
{ status: "Loading..."
, hack: ""
, post: Post
{ title: ""
, body: ""
, date: "" }
, name: ""
, id: Nothing }
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
update (ReceivePost (Left err)) state =
noEffects $ state { id = Nothing, status = err }
update (ReceivePost (Right post)) state =
{ state: state { status = "", id = Just 1, post = post }
, effects: [ pure $ RenderPost ]
}
update RequestPost state =
{ state: state
, effects: [ do
res <- attempt $ get ("/api/blog/post?name=" <> state.name)
let decode r = decodeJson r.response :: Either String Post
let post = either (Left <<< show) decode res
pure $ ReceivePost post
]
}
update RenderPost state =
noEffects $ state { hack = mdify "blogpost" }
view :: State -> Html Action
view { id: id, status: status, post: (Post post) } =
case id of
Nothing -> div [] []
(Just _) ->
div []
[ h1 [] [ text status ]
, div []
[ p [ id_ "blogpost" ] [ text post.body ] ]
]
foreign import mdify :: String -> String

View File

@ -39,15 +39,15 @@ instance decodeJsonPost :: DecodeJson Post where
init :: State
init =
{ posts: []
, status: "Loading..." }
, status: "" }
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" }
noEffects $ state { posts = posts, status = "" }
update RequestPosts state =
{ state: state { status = "Fetching posts..." }
{ state: state { status = "Loading..." }
, effects: [ do
res <- attempt $ get "/api/blog/posts"
let decode r = decodeJson r.response :: Either String Posts
@ -79,5 +79,6 @@ view :: State -> Html Action
view state =
div
[]
[ h1 [] [ text state.status ]
[ h1 [] [ text "Posts" ]
, p [] [ text state.status ]
, div [ className "row" ] $ map post state.posts ]

View File

@ -1,8 +1,10 @@
module App.Layout where
import App.BlogEntry as BlogEntry
import App.BlogIndex as BlogIndex
import App.Counter as Counter
import App.Routes (Route(..))
import Control.Monad.RWS (state)
import DOM (DOM)
import Network.HTTP.Affjax (AJAX)
import Prelude (($), (#), map, pure)
@ -14,29 +16,37 @@ import Pux.Router (link)
data Action
= Child (Counter.Action)
| BIChild (BlogIndex.Action)
| BEChild (BlogEntry.Action)
| PageView Route
type State =
{ route :: Route
, count :: Counter.State
, bistate :: BlogIndex.State }
, bistate :: BlogIndex.State
, bestate :: BlogEntry.State }
init :: State
init =
{ route: NotFound
, count: Counter.init
, bistate: BlogIndex.init }
, bistate: BlogIndex.init
, bestate: BlogEntry.init }
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
update (PageView route) state = routeEffects route $ state { route = route }
update (BIChild action) state = BlogIndex.update action state.bistate
# mapState (state { bistate = _ })
# mapEffects BIChild
update (BEChild action) state = BlogEntry.update action state.bestate
# mapState (state { bestate = _ })
# mapEffects BEChild
update (Child action) state = noEffects $ state { count = Counter.update action state.count }
routeEffects :: Route -> State -> EffModel State Action (dom :: DOM, ajax :: AJAX)
routeEffects BlogIndex state = { state: state
, effects: [ pure BlogIndex.RequestPosts ] } # mapEffects BIChild
routeEffects (BlogPost page) state = { state: state { bestate = BlogEntry.init { name = page } }
, effects: [ pure BlogEntry.RequestPost ] } # mapEffects BEChild
routeEffects _ state = noEffects $ state
view :: State -> Html Action
@ -71,4 +81,5 @@ page NotFound _ = h1 [] [ text "not found" ]
page Home state = map Child $ Counter.view state.count
page Resume state = h1 [] [ text "Christine Dodrill" ]
page BlogIndex state = map BIChild $ BlogIndex.view state.bistate
page (BlogPost _) state = map BEChild $ BlogEntry.view state.bestate
page _ _ = h1 [] [ text "not implemented yet" ]

View File

@ -7,7 +7,7 @@ import Control.Monad.Eff (Eff)
import DOM (DOM)
import Network.HTTP.Affjax (AJAX)
import Prelude (bind, pure)
import Pux (App, Config, CoreEffects, fromSimple, renderToDOM, start)
import Pux (App, Config, CoreEffects, renderToDOM, start)
import Pux.Devtool (Action, start) as Pux.Devtool
import Pux.Router (sampleUrl)
import Signal ((~>))

View File

@ -19,3 +19,5 @@ match url = fromMaybe NotFound $ router url $
Home <$ end
<|>
BlogIndex <$ lit "blog" <* end
<|>
BlogPost <$> (lit "blog" *> str) <* end