{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, OverloadedStrings, RecordWildCards, TemplateHaskell, TypeFamilies, TypeSynonymInstances, OverloadedStrings #-} {-# OPTIONS_GHC -F -pgmFhsx2hs #-} module 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 Events (GetPasteById(GetPasteById), GetRecentPastes(GetRecentPastes), InsertPaste(InsertPaste)) 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 Route (CtrlV, CtrlVForm, Route(..)) import Template (appTemplate) import Types (Format(..), Paste(..), PasteId(..), PasteMeta(PasteMeta, format, nickname, pasteId, pasted, title)) ------------------------------------------------------------------------------ -- Pages ------------------------------------------------------------------------------ -- | page handler for 'ViewRecent' viewRecentPage :: CtrlV Response viewRecentPage = do method GET recent <- query (GetRecentPastes 20 0) case recent of [] -> appTemplate "Recent Pastes" ()

There are no pastes yet.

_ -> appTemplate "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 -> CtrlV Response viewPastePage pid = do method GET mPaste <- query (GetPasteById pid) case mPaste of Nothing -> do notFound () appTemplate "Paste not found." () $

Paste <% pid %> could not be found.

(Just (Paste (PasteMeta{..}) paste)) -> do ok () appTemplate (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 -> CtrlV XML formatPaste PlainText txt =
<% txt %>
-- | page handler for 'NewPaste' newPastePage :: CtrlV Response newPastePage = do here <- whereami appTemplate "Add a Paste" () $ <%>

Add a paste

<% reform (form here) "add" success Nothing pasteForm %> where success :: Paste -> CtrlV Response success paste = do pid <- update (InsertPaste paste) seeOtherURL (ViewPaste pid) -- | the 'Form' used for entering a new paste pasteForm :: CtrlVForm 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 -> CtrlV Response route url = case url of ViewRecent -> viewRecentPage (ViewPaste pid) -> viewPastePage pid NewPaste -> newPastePage CSS -> serveFile (asContentType "text/css") "style.css"