{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, OverloadedStrings, RecordWildCards, TemplateHaskell, TypeFamilies, TypeSynonymInstances, OverloadedStrings #-} {-# OPTIONS_GHC -F -pgmFhsx2hs #-} module Tiny.Pages ( route ) where import Data.Text (Text) import qualified Data.Text as Text (null) import qualified Data.Text.Lazy as Lazy (pack) import Data.Time.Clock (getCurrentTime) import Happstack.Foundation ((++>), (<$>), (<++), Applicative((<*), (<*>)), asContentType, Attr((:=)), EmbedAsAttr(asAttr), EmbedAsChild(asChild), errorList, fieldset, form, fromStringLit, inputSubmit, inputText, label, li, method, Method(GET), MonadIO(liftIO), notFound, ok, query, reform, Response, seeOtherURL, select, serveFile, textarea, transformEither, transformEitherM, ul, update, whereami, XML, XMLGen(genElement)) import Tiny.Events (GetPasteById(GetPasteById), GetRecentPastes(GetRecentPastes), InsertPaste(InsertPaste)) import Tiny.Route (App, AppForm, Route(..)) import Tiny.Template (appTemplateHSP) import Tiny.Types (Format(..), Paste(..), PasteId(..), PasteMeta(PasteMeta, format, nickname, pasteId, pasted, title)) ------------------------------------------------------------------------------ -- Pages ------------------------------------------------------------------------------ -- | page handler for 'ViewRecent' viewRecentPage :: App Response viewRecentPage = do method GET recent <- query (GetRecentPastes 20 0) case recent of [] -> appTemplateHSP "Recent Pastes" ()

There are no pastes yet.

_ -> appTemplateHSP "Recent Pastes" () $ <%>

Recent Pastes

<% mapM mkTableRow recent %>
id title author date format
where mkTableRow PasteMeta{..} = <% show $ unPasteId pasteId %> <% title %> <% nickname %> <% pasted %> <% show format %> -- | page handler for 'ViewPaste' viewPastePage :: PasteId -> App Response viewPastePage pid = do method GET mPaste <- query (GetPasteById pid) case mPaste of Nothing -> do notFound () appTemplateHSP "Paste not found." () $

Paste <% pid %> could not be found.

(Just (Paste (PasteMeta{..}) paste)) -> do ok () appTemplateHSP (Lazy.pack $ "Paste " ++ (show $ unPasteId pid)) () $
Paste:
<% pid %>
Title:
<% title %>
Author:
<% nickname %>
<% formatPaste format paste %>
-- | convert the paste to HTML. We currently only support 'PlainText', -- but eventually it might do syntax hightlighting, markdown, etc. -- -- Note that we do not have to worry about escaping the txt -- value.. that is done automatically by HSP. formatPaste :: Format -> Text -> App XML formatPaste PlainText txt =
<% txt %>
-- | page handler for 'NewPaste' newPastePage :: App Response newPastePage = do here <- whereami appTemplateHSP "Add a Paste" () $ <%>

Add a paste

<% reform (form here) "add" success Nothing pasteForm %> where success :: Paste -> App Response success paste = do pid <- update (InsertPaste paste) seeOtherURL (ViewPaste pid) -- | the 'Form' used for entering a new paste pasteForm :: AppForm Paste pasteForm = (fieldset $ ul $ (,,,) <$> (li $ label title ++> (inputText "" `transformEither` required) <++ errorList) <*> (li $ label nick ++> (inputText "" `transformEither` required) <++ errorList) <*> (li $ label format ++> formatForm) <*> (li $ label
paste
++> errorList ++> (textarea 80 25 "" `transformEither` required)) <* inputSubmit "paste!" ) `transformEitherM` toPaste where formatForm = select [(a, show a) | a <- [minBound .. maxBound]] (== PlainText) toPaste (ttl, nick, fmt, bdy) = do now <- liftIO getCurrentTime return $ Right $ (Paste { pasteMeta = PasteMeta { pasteId = PasteId 0 , title = ttl , nickname = nick , format = fmt , pasted = now } , paste = bdy }) required txt | Text.null txt = Left "Required" | otherwise = Right txt ------------------------------------------------------------------------------ -- route ------------------------------------------------------------------------------ -- | the route mapping function route :: Route -> App Response route url = case url of ViewRecent -> viewRecentPage (ViewPaste pid) -> viewPastePage pid NewPaste -> newPastePage CSS -> serveFile (asContentType "text/css") "style.css"