diff --git a/frontend/src/BlogEntry.js b/frontend/src/BlogEntry.js new file mode 100644 index 0000000..f464cf2 --- /dev/null +++ b/frontend/src/BlogEntry.js @@ -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 :)"; +} diff --git a/frontend/src/BlogEntry.purs b/frontend/src/BlogEntry.purs new file mode 100644 index 0000000..c104a78 --- /dev/null +++ b/frontend/src/BlogEntry.purs @@ -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 diff --git a/frontend/src/BlogIndex.purs b/frontend/src/BlogIndex.purs index d1b19f6..a52e6bd 100644 --- a/frontend/src/BlogIndex.purs +++ b/frontend/src/BlogIndex.purs @@ -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 ] diff --git a/frontend/src/Layout.purs b/frontend/src/Layout.purs index 86b2496..96d056a 100644 --- a/frontend/src/Layout.purs +++ b/frontend/src/Layout.purs @@ -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" ] diff --git a/frontend/src/Main.purs b/frontend/src/Main.purs index c7106b4..5f42a8a 100644 --- a/frontend/src/Main.purs +++ b/frontend/src/Main.purs @@ -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 ((~>)) diff --git a/frontend/src/Routes.purs b/frontend/src/Routes.purs index 08ae9e5..111d0d7 100644 --- a/frontend/src/Routes.purs +++ b/frontend/src/Routes.purs @@ -19,3 +19,5 @@ match url = fromMaybe NotFound $ router url $ Home <$ end <|> BlogIndex <$ lit "blog" <* end + <|> + BlogPost <$> (lit "blog" *> str) <* end