Continued refactoring; Yesod.Yesod
This commit is contained in:
parent
09b07a5aad
commit
3701e3c490
@ -41,9 +41,9 @@ data PageContent url = PageContent
|
|||||||
-- FIXME some typeclasses for the stuff below?
|
-- FIXME some typeclasses for the stuff below?
|
||||||
-- | Converts the given Hamlet template into 'Content', which can be used in a
|
-- | Converts the given Hamlet template into 'Content', which can be used in a
|
||||||
-- Yesod 'Response'.
|
-- Yesod 'Response'.
|
||||||
hamletToContent :: Hamlet (Routes sub) IO () -> GHandler sub master Content
|
hamletToContent :: Hamlet (Routes master) IO () -> GHandler sub master Content
|
||||||
hamletToContent h = do
|
hamletToContent h = do
|
||||||
render <- getUrlRender
|
render <- getUrlRenderMaster
|
||||||
return $ ContentEnum $ go render
|
return $ ContentEnum $ go render
|
||||||
where
|
where
|
||||||
go render iter seed = do
|
go render iter seed = do
|
||||||
@ -54,7 +54,7 @@ hamletToContent h = do
|
|||||||
iter' iter seed text = iter seed $ cs text
|
iter' iter seed text = iter seed $ cs text
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
hamletToRepHtml :: Hamlet (Routes sub) IO () -> GHandler sub master RepHtml
|
hamletToRepHtml :: Hamlet (Routes master) IO () -> GHandler sub master RepHtml
|
||||||
hamletToRepHtml = fmap RepHtml . hamletToContent
|
hamletToRepHtml = fmap RepHtml . hamletToContent
|
||||||
|
|
||||||
instance Monad m => ConvertSuccess String (Hamlet url m ()) where
|
instance Monad m => ConvertSuccess String (Hamlet url m ()) where
|
||||||
|
|||||||
@ -29,6 +29,7 @@ module Yesod.Handler
|
|||||||
, getUrlRender
|
, getUrlRender
|
||||||
, getUrlRenderMaster
|
, getUrlRenderMaster
|
||||||
, getRoute
|
, getRoute
|
||||||
|
, getRouteToMaster
|
||||||
-- * Special responses
|
-- * Special responses
|
||||||
, RedirectType (..)
|
, RedirectType (..)
|
||||||
, redirect
|
, redirect
|
||||||
@ -153,6 +154,11 @@ getUrlRenderMaster = handlerRender <$> getData
|
|||||||
getRoute :: GHandler sub master (Maybe (Routes sub))
|
getRoute :: GHandler sub master (Maybe (Routes sub))
|
||||||
getRoute = handlerRoute <$> getData
|
getRoute = handlerRoute <$> getData
|
||||||
|
|
||||||
|
-- | Get the function to promote a route for a subsite to a route for the
|
||||||
|
-- master site.
|
||||||
|
getRouteToMaster :: GHandler sub master (Routes sub -> Routes master)
|
||||||
|
getRouteToMaster = handlerToMaster <$> getData
|
||||||
|
|
||||||
-- | Function used internally by Yesod in the process of converting a
|
-- | Function used internally by Yesod in the process of converting a
|
||||||
-- 'GHandler' into an 'W.Application'. Should not be needed by users.
|
-- 'GHandler' into an 'W.Application'. Should not be needed by users.
|
||||||
runHandler :: HasReps c
|
runHandler :: HasReps c
|
||||||
|
|||||||
@ -29,7 +29,7 @@ newtype RepAtom = RepAtom Content
|
|||||||
instance HasReps RepAtom where
|
instance HasReps RepAtom where
|
||||||
chooseRep (RepAtom c) _ = return (TypeAtom, c)
|
chooseRep (RepAtom c) _ = return (TypeAtom, c)
|
||||||
|
|
||||||
atomFeed :: AtomFeed (Routes sub) -> GHandler sub master RepAtom
|
atomFeed :: AtomFeed (Routes master) -> GHandler sub master RepAtom
|
||||||
atomFeed = fmap RepAtom . hamletToContent . template
|
atomFeed = fmap RepAtom . hamletToContent . template
|
||||||
|
|
||||||
data AtomFeed url = AtomFeed
|
data AtomFeed url = AtomFeed
|
||||||
|
|||||||
@ -72,15 +72,9 @@ getOpenIdR = do
|
|||||||
case getParams rr "dest" of
|
case getParams rr "dest" of
|
||||||
[] -> return ()
|
[] -> return ()
|
||||||
(x:_) -> addCookie destCookieTimeout destCookieName x
|
(x:_) -> addCookie destCookieTimeout destCookieName x
|
||||||
y <- getYesodMaster
|
rtom <- getRouteToMaster
|
||||||
let html = template (getParams rr "message", id)
|
let html = template (getParams rr "message", rtom)
|
||||||
let pc = PageContent
|
applyLayout "Log in via OpenID" $ html
|
||||||
{ pageTitle = cs "Log in via OpenID"
|
|
||||||
, pageHead = return ()
|
|
||||||
, pageBody = html
|
|
||||||
}
|
|
||||||
content <- hamletToContent $ applyLayout y pc rr
|
|
||||||
return $ RepHtml content
|
|
||||||
where
|
where
|
||||||
urlForward (_, wrapper) = wrapper OpenIdForward
|
urlForward (_, wrapper) = wrapper OpenIdForward
|
||||||
hasMessage = not . null . fst
|
hasMessage = not . null . fst
|
||||||
|
|||||||
@ -65,7 +65,7 @@ template = [$hamlet|
|
|||||||
%priority $url.priority.show.cs$
|
%priority $url.priority.show.cs$
|
||||||
|]
|
|]
|
||||||
|
|
||||||
sitemap :: [SitemapUrl (Routes sub)] -> GHandler sub master RepXml
|
sitemap :: [SitemapUrl (Routes master)] -> GHandler sub master RepXml
|
||||||
sitemap = fmap RepXml . hamletToContent . template
|
sitemap = fmap RepXml . hamletToContent . template
|
||||||
|
|
||||||
robots :: Routes sub -- ^ sitemap url
|
robots :: Routes sub -- ^ sitemap url
|
||||||
|
|||||||
25
Yesod/Internal.hs
Normal file
25
Yesod/Internal.hs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-- | Normal users should never need access to these.
|
||||||
|
module Yesod.Internal
|
||||||
|
( -- * Error responses
|
||||||
|
ErrorResponse (..)
|
||||||
|
-- * Header
|
||||||
|
, Header (..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
-- | Responses to indicate some form of an error occurred. These are different
|
||||||
|
-- from 'SpecialResponse' in that they allow for custom error pages.
|
||||||
|
data ErrorResponse =
|
||||||
|
NotFound
|
||||||
|
| InternalError String
|
||||||
|
| InvalidArgs [(String, String)]
|
||||||
|
| PermissionDenied
|
||||||
|
| BadMethod String
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
----- header stuff
|
||||||
|
-- | Headers to be added to a 'Result'.
|
||||||
|
data Header =
|
||||||
|
AddCookie Int String String
|
||||||
|
| DeleteCookie String
|
||||||
|
| Header String String
|
||||||
|
deriving (Eq, Show)
|
||||||
@ -35,26 +35,26 @@ import Data.Text.Lazy (unpack)
|
|||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
newtype Json url m a = Json { unJson :: Hamlet url m a }
|
newtype Json url a = Json { unJson :: Hamlet url IO a }
|
||||||
deriving (Functor, Applicative, Monad)
|
deriving (Functor, Applicative, Monad)
|
||||||
|
|
||||||
jsonToContent :: Json (Routes sub) IO () -> GHandler sub master Content
|
jsonToContent :: Json (Routes master) () -> GHandler sub master Content
|
||||||
jsonToContent = hamletToContent . unJson
|
jsonToContent = hamletToContent . unJson
|
||||||
|
|
||||||
htmlContentToText :: HtmlContent -> Text
|
htmlContentToText :: HtmlContent -> Text
|
||||||
htmlContentToText (Encoded t) = t
|
htmlContentToText (Encoded t) = t
|
||||||
htmlContentToText (Unencoded t) = encodeHtml t
|
htmlContentToText (Unencoded t) = encodeHtml t
|
||||||
|
|
||||||
jsonScalar :: Monad m => HtmlContent -> Json url m ()
|
jsonScalar :: HtmlContent -> Json url ()
|
||||||
jsonScalar s = Json $ do
|
jsonScalar s = Json $ do
|
||||||
outputString "\""
|
outputString "\""
|
||||||
output $ encodeJson $ htmlContentToText s
|
output $ encodeJson $ htmlContentToText s
|
||||||
outputString "\""
|
outputString "\""
|
||||||
|
|
||||||
jsonList :: Monad m => [Json url m ()] -> Json url m ()
|
jsonList :: [Json url ()] -> Json url ()
|
||||||
jsonList = jsonList' . fromList
|
jsonList = jsonList' . fromList
|
||||||
|
|
||||||
jsonList' :: Monad m => Enumerator (Json url m ()) (Json url m) -> Json url m () -- FIXME simplify type
|
jsonList' :: Enumerator (Json url ()) (Json url) -> Json url () -- FIXME simplify type
|
||||||
jsonList' (Enumerator enum) = do
|
jsonList' (Enumerator enum) = do
|
||||||
Json $ outputString "["
|
Json $ outputString "["
|
||||||
_ <- enum go False
|
_ <- enum go False
|
||||||
@ -65,10 +65,10 @@ jsonList' (Enumerator enum) = do
|
|||||||
() <- j
|
() <- j
|
||||||
return $ Right True
|
return $ Right True
|
||||||
|
|
||||||
jsonMap :: Monad m => [(Json url m (), Json url m ())] -> Json url m ()
|
jsonMap :: [(Json url (), Json url ())] -> Json url ()
|
||||||
jsonMap = jsonMap' . fromList
|
jsonMap = jsonMap' . fromList
|
||||||
|
|
||||||
jsonMap' :: Monad m => Enumerator (Json url m (), Json url m ()) (Json url m) -> Json url m () -- FIXME simplify type
|
jsonMap' :: Enumerator (Json url (), Json url ()) (Json url) -> Json url () -- FIXME simplify type
|
||||||
jsonMap' (Enumerator enum) = do
|
jsonMap' (Enumerator enum) = do
|
||||||
Json $ outputString "{"
|
Json $ outputString "{"
|
||||||
_ <- enum go False
|
_ <- enum go False
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
-- | The basic typeclass for a Yesod application.
|
-- | The basic typeclass for a Yesod application.
|
||||||
module Yesod.Yesod
|
module Yesod.Yesod
|
||||||
( Yesod (..)
|
( Yesod (..)
|
||||||
, YesodSite (..)
|
, YesodSite (..)
|
||||||
, simpleApplyLayout
|
, applyLayout
|
||||||
, applyLayoutJson
|
, applyLayoutJson
|
||||||
, getApproot
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Content
|
import Yesod.Content
|
||||||
@ -36,15 +36,18 @@ class YesodSite a => Yesod a where
|
|||||||
clientSessionDuration = const 120
|
clientSessionDuration = const 120
|
||||||
|
|
||||||
-- | Output error response pages.
|
-- | Output error response pages.
|
||||||
errorHandler :: Yesod y => a -> ErrorResponse -> Handler y ChooseRep
|
errorHandler :: Yesod y
|
||||||
|
=> a
|
||||||
|
-> ErrorResponse
|
||||||
|
-> Handler y ChooseRep
|
||||||
errorHandler _ = defaultErrorHandler
|
errorHandler _ = defaultErrorHandler
|
||||||
|
|
||||||
-- | Applies some form of layout to <title> and <body> contents of a page. FIXME: use a Maybe here to allow subsites to simply inherit.
|
-- | Applies some form of layout to <title> and <body> contents of a page. FIXME: use a Maybe here to allow subsites to simply inherit.
|
||||||
applyLayout :: a
|
rawApplyLayout :: a
|
||||||
-> PageContent url -- FIXME not so good, should be Routes y
|
-> PageContent (Routes a)
|
||||||
-> Request
|
-> Request
|
||||||
-> Hamlet url IO ()
|
-> Hamlet (Routes a) IO ()
|
||||||
applyLayout _ p _ = [$hamlet|
|
rawApplyLayout _ p _ = [$hamlet|
|
||||||
!!!
|
!!!
|
||||||
%html
|
%html
|
||||||
%head
|
%head
|
||||||
@ -62,11 +65,27 @@ class YesodSite a => Yesod a where
|
|||||||
-- trailing slash.
|
-- trailing slash.
|
||||||
approot :: a -> Approot
|
approot :: a -> Approot
|
||||||
|
|
||||||
|
-- | A convenience wrapper around 'simpleApplyLayout for HTML-only data.
|
||||||
|
applyLayout :: Yesod master
|
||||||
|
=> String -- ^ title
|
||||||
|
-> Hamlet (Routes master) IO () -- ^ body
|
||||||
|
-> GHandler sub master RepHtml
|
||||||
|
applyLayout t b = do
|
||||||
|
let pc = PageContent
|
||||||
|
{ pageTitle = cs t
|
||||||
|
, pageHead = return ()
|
||||||
|
, pageBody = b
|
||||||
|
}
|
||||||
|
y <- getYesodMaster
|
||||||
|
rr <- getRequest
|
||||||
|
content <- hamletToContent $ rawApplyLayout y pc rr
|
||||||
|
return $ RepHtml content
|
||||||
|
|
||||||
applyLayoutJson :: Yesod master
|
applyLayoutJson :: Yesod master
|
||||||
=> String -- ^ title
|
=> String -- ^ title
|
||||||
-> x
|
-> x
|
||||||
-> (x -> Hamlet (Routes sub) IO ())
|
-> (x -> Hamlet (Routes master) IO ())
|
||||||
-> (x -> Json (Routes sub) IO ())
|
-> (x -> Json (Routes master) ())
|
||||||
-> GHandler sub master RepHtmlJson
|
-> GHandler sub master RepHtmlJson
|
||||||
applyLayoutJson t x toH toJ = do
|
applyLayoutJson t x toH toJ = do
|
||||||
let pc = PageContent
|
let pc = PageContent
|
||||||
@ -76,49 +95,32 @@ applyLayoutJson t x toH toJ = do
|
|||||||
}
|
}
|
||||||
y <- getYesodMaster
|
y <- getYesodMaster
|
||||||
rr <- getRequest
|
rr <- getRequest
|
||||||
html <- hamletToContent $ applyLayout y pc rr
|
html <- hamletToContent $ rawApplyLayout y pc rr
|
||||||
json <- jsonToContent $ toJ x
|
json <- jsonToContent $ toJ x
|
||||||
return $ RepHtmlJson html json
|
return $ RepHtmlJson html json
|
||||||
|
|
||||||
-- | A convenience wrapper around 'simpleApplyLayout for HTML-only data.
|
applyLayout' :: Yesod master
|
||||||
simpleApplyLayout :: Yesod master
|
=> String -- ^ title
|
||||||
=> String -- ^ title
|
-> Hamlet (Routes master) IO () -- ^ body
|
||||||
-> Hamlet (Routes sub) IO () -- ^ body
|
-> GHandler sub master ChooseRep
|
||||||
-> GHandler sub master RepHtml
|
applyLayout' s = fmap chooseRep . applyLayout s
|
||||||
simpleApplyLayout t b = do
|
|
||||||
let pc = PageContent
|
|
||||||
{ pageTitle = cs t
|
|
||||||
, pageHead = return ()
|
|
||||||
, pageBody = b
|
|
||||||
}
|
|
||||||
y <- getYesodMaster
|
|
||||||
rr <- getRequest
|
|
||||||
content <- hamletToContent $ applyLayout y pc rr
|
|
||||||
return $ RepHtml content
|
|
||||||
|
|
||||||
getApproot :: Yesod y => Handler y Approot
|
defaultErrorHandler :: Yesod y
|
||||||
getApproot = approot `fmap` getYesod
|
=> ErrorResponse
|
||||||
|
-> Handler y ChooseRep
|
||||||
simpleApplyLayout' :: Yesod master
|
|
||||||
=> String -- ^ title
|
|
||||||
-> Hamlet (Routes sub) IO () -- ^ body
|
|
||||||
-> GHandler sub master ChooseRep
|
|
||||||
simpleApplyLayout' t = fmap chooseRep . simpleApplyLayout t
|
|
||||||
|
|
||||||
defaultErrorHandler :: Yesod y => ErrorResponse -> Handler y ChooseRep
|
|
||||||
defaultErrorHandler NotFound = do
|
defaultErrorHandler NotFound = do
|
||||||
r <- waiRequest
|
r <- waiRequest
|
||||||
simpleApplyLayout' "Not Found" $ [$hamlet|
|
applyLayout' "Not Found" $ [$hamlet|
|
||||||
%h1 Not Found
|
%h1 Not Found
|
||||||
%p $helper$
|
%p $helper$
|
||||||
|] r
|
|] r
|
||||||
where
|
where
|
||||||
helper = Unencoded . cs . W.pathInfo
|
helper = Unencoded . cs . W.pathInfo
|
||||||
defaultErrorHandler PermissionDenied =
|
defaultErrorHandler PermissionDenied =
|
||||||
simpleApplyLayout' "Permission Denied" $ [$hamlet|
|
applyLayout' "Permission Denied" $ [$hamlet|
|
||||||
%h1 Permission denied|] ()
|
%h1 Permission denied|] ()
|
||||||
defaultErrorHandler (InvalidArgs ia) =
|
defaultErrorHandler (InvalidArgs ia) =
|
||||||
simpleApplyLayout' "Invalid Arguments" $ [$hamlet|
|
applyLayout' "Invalid Arguments" $ [$hamlet|
|
||||||
%h1 Invalid Arguments
|
%h1 Invalid Arguments
|
||||||
%dl
|
%dl
|
||||||
$forall ias pair
|
$forall ias pair
|
||||||
@ -128,12 +130,12 @@ defaultErrorHandler (InvalidArgs ia) =
|
|||||||
where
|
where
|
||||||
ias _ = map (cs *** cs) ia
|
ias _ = map (cs *** cs) ia
|
||||||
defaultErrorHandler (InternalError e) =
|
defaultErrorHandler (InternalError e) =
|
||||||
simpleApplyLayout' "Internal Server Error" $ [$hamlet|
|
applyLayout' "Internal Server Error" $ [$hamlet|
|
||||||
%h1 Internal Server Error
|
%h1 Internal Server Error
|
||||||
%p $cs$
|
%p $cs$
|
||||||
|] e
|
|] e
|
||||||
defaultErrorHandler (BadMethod m) =
|
defaultErrorHandler (BadMethod m) =
|
||||||
simpleApplyLayout' "Bad Method" $ [$hamlet|
|
applyLayout' "Bad Method" $ [$hamlet|
|
||||||
%h1 Method Not Supported
|
%h1 Method Not Supported
|
||||||
%p Method "$cs$" not supported
|
%p Method "$cs$" not supported
|
||||||
|] m
|
|] m
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user