MonadHandler/MonadWidget
This commit is contained in:
parent
1fabee31e4
commit
a2c4f1f3b7
@ -48,9 +48,8 @@ module Yesod.Core
|
|||||||
, ScriptLoadPosition (..)
|
, ScriptLoadPosition (..)
|
||||||
, BottomOfHeadAsync
|
, BottomOfHeadAsync
|
||||||
-- * Subsites
|
-- * Subsites
|
||||||
, HandlerReader (..)
|
, MonadHandler (..)
|
||||||
, HandlerState (..)
|
, MonadWidget (..)
|
||||||
, HandlerError (..)
|
|
||||||
, getRouteToParent
|
, getRouteToParent
|
||||||
-- * Misc
|
-- * Misc
|
||||||
, yesodVersion
|
, yesodVersion
|
||||||
@ -89,7 +88,7 @@ import Data.Version (showVersion)
|
|||||||
import Yesod.Routes.Class (RenderRoute (..))
|
import Yesod.Routes.Class (RenderRoute (..))
|
||||||
|
|
||||||
-- | Return an 'Unauthorized' value, with the given i18n message.
|
-- | Return an 'Unauthorized' value, with the given i18n message.
|
||||||
unauthorizedI :: (Monad m, RenderMessage site msg) => msg -> HandlerT site m AuthResult
|
unauthorizedI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => msg -> m AuthResult
|
||||||
unauthorizedI msg = do
|
unauthorizedI msg = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
return $ Unauthorized $ mr msg
|
return $ Unauthorized $ mr msg
|
||||||
|
|||||||
@ -1,60 +1,48 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE ConstraintKinds #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
module Yesod.Core.Class.Handler where
|
module Yesod.Core.Class.Handler
|
||||||
|
( MonadHandler (..)
|
||||||
|
, MonadWidget (..)
|
||||||
|
) where
|
||||||
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Data.IORef.Lifted (atomicModifyIORef)
|
import Data.IORef.Lifted (atomicModifyIORef)
|
||||||
import Control.Exception.Lifted (throwIO)
|
import Control.Exception.Lifted (throwIO)
|
||||||
import Control.Monad.Base
|
import Control.Monad.Base
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
|
import Control.Monad (liftM)
|
||||||
|
import Control.Monad.IO.Class (MonadIO, liftIO)
|
||||||
|
import Control.Monad.Trans.Resource (MonadResource, MonadResourceBase, ExceptionT (..))
|
||||||
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
|
||||||
class Monad m => HandlerReader m where
|
class MonadResource m => MonadHandler m where
|
||||||
type HandlerSite m
|
type HandlerSite m
|
||||||
|
liftHandlerT :: HandlerT (HandlerSite m) IO a -> m a
|
||||||
|
|
||||||
askYesodRequest :: m YesodRequest
|
replaceToParent :: HandlerData site route -> HandlerData site ()
|
||||||
askHandlerEnv :: m (RunHandlerEnv (HandlerSite m))
|
replaceToParent hd = hd { handlerToParent = const () }
|
||||||
|
|
||||||
instance Monad m => HandlerReader (HandlerT site m) where
|
instance MonadResourceBase m => MonadHandler (HandlerT site m) where
|
||||||
type HandlerSite (HandlerT site m) = site
|
type HandlerSite (HandlerT site m) = site
|
||||||
|
liftHandlerT (HandlerT f) = HandlerT $ liftIO . f . replaceToParent
|
||||||
|
{-# RULES "liftHandlerT (HandlerT site IO)" forall action. liftHandlerT action = id #-}
|
||||||
|
|
||||||
askYesodRequest = HandlerT $ return . handlerRequest
|
instance MonadResourceBase m => MonadHandler (WidgetT site m) where
|
||||||
askHandlerEnv = HandlerT $ return . handlerEnv
|
|
||||||
|
|
||||||
instance Monad m => HandlerReader (WidgetT site m) where
|
|
||||||
type HandlerSite (WidgetT site m) = site
|
type HandlerSite (WidgetT site m) = site
|
||||||
|
liftHandlerT (HandlerT f) = WidgetT $ liftIO . liftM (, mempty) . f . replaceToParent
|
||||||
|
{-# RULES "liftHandlerT (WidgetT site IO)" forall f. liftHandlerT (HandlerT f) = WidgetT $ liftM (, mempty) . f #-}
|
||||||
|
|
||||||
askYesodRequest = WidgetT $ return . (, mempty) . handlerRequest
|
instance MonadHandler m => MonadHandler (ExceptionT m) where
|
||||||
askHandlerEnv = WidgetT $ return . (, mempty) . handlerEnv
|
type HandlerSite (ExceptionT m) = HandlerSite m
|
||||||
|
liftHandlerT = lift . liftHandlerT
|
||||||
|
-- FIXME add a bunch of transformer instances
|
||||||
|
|
||||||
class HandlerReader m => HandlerState m where
|
class MonadHandler m => MonadWidget m where
|
||||||
stateGHState :: (GHState -> (a, GHState)) -> m a
|
liftWidgetT :: WidgetT (HandlerSite m) IO a -> m a
|
||||||
|
instance MonadResourceBase m => MonadWidget (WidgetT site m) where
|
||||||
getGHState :: m GHState
|
liftWidgetT (WidgetT f) = WidgetT $ liftIO . f . replaceToParent
|
||||||
getGHState = stateGHState $ \s -> (s, s)
|
-- FIXME add a bunch of transformer instances
|
||||||
|
|
||||||
putGHState :: GHState -> m ()
|
|
||||||
putGHState s = stateGHState $ const ((), s)
|
|
||||||
|
|
||||||
instance MonadBase IO m => HandlerState (HandlerT site m) where
|
|
||||||
stateGHState f =
|
|
||||||
HandlerT $ flip atomicModifyIORef f' . handlerState
|
|
||||||
where
|
|
||||||
f' z = let (x, y) = f z in (y, x)
|
|
||||||
|
|
||||||
instance MonadBase IO m => HandlerState (WidgetT site m) where
|
|
||||||
stateGHState f =
|
|
||||||
WidgetT $ fmap (, mempty) . flip atomicModifyIORef f' . handlerState
|
|
||||||
where
|
|
||||||
f' z = let (x, y) = f z in (y, x)
|
|
||||||
|
|
||||||
class HandlerReader m => HandlerError m where
|
|
||||||
handlerError :: HandlerContents -> m a
|
|
||||||
|
|
||||||
instance MonadBase IO m => HandlerError (HandlerT site m) where
|
|
||||||
handlerError = throwIO
|
|
||||||
|
|
||||||
instance MonadBase IO m => HandlerError (WidgetT site m) where
|
|
||||||
handlerError = throwIO
|
|
||||||
|
|||||||
@ -244,6 +244,8 @@ instance ToTypedContent Html where
|
|||||||
toTypedContent h = TypedContent typeHtml (toContent h)
|
toTypedContent h = TypedContent typeHtml (toContent h)
|
||||||
instance ToTypedContent T.Text where
|
instance ToTypedContent T.Text where
|
||||||
toTypedContent t = TypedContent typePlain (toContent t)
|
toTypedContent t = TypedContent typePlain (toContent t)
|
||||||
|
instance ToTypedContent [Char] where
|
||||||
|
toTypedContent = toTypedContent . pack
|
||||||
instance ToTypedContent Text where
|
instance ToTypedContent Text where
|
||||||
toTypedContent t = TypedContent typePlain (toContent t)
|
toTypedContent t = TypedContent typePlain (toContent t)
|
||||||
instance ToTypedContent a => ToTypedContent (DontFullyEvaluate a) where
|
instance ToTypedContent a => ToTypedContent (DontFullyEvaluate a) where
|
||||||
|
|||||||
@ -114,9 +114,8 @@ mkYesodGeneral name args clazzes isSub resS = do
|
|||||||
return (renderRouteDec ++ masterTypeSyns, dispatchDec)
|
return (renderRouteDec ++ masterTypeSyns, dispatchDec)
|
||||||
where sub = foldl appT subCons subArgs
|
where sub = foldl appT subCons subArgs
|
||||||
master = if isSub then (varT $ mkName "m") else sub
|
master = if isSub then (varT $ mkName "m") else sub
|
||||||
context = if isSub then cxt $ yesod : map return clazzes
|
context = if isSub then cxt $ map return clazzes
|
||||||
else return []
|
else return []
|
||||||
yesod = classP ''HandlerReader [master]
|
|
||||||
handler = tySynD (mkName "Handler") [] [t| HandlerT $master IO |]
|
handler = tySynD (mkName "Handler") [] [t| HandlerT $master IO |]
|
||||||
widget = tySynD (mkName "Widget") [] [t| WidgetT $master IO () |]
|
widget = tySynD (mkName "Widget") [] [t| WidgetT $master IO () |]
|
||||||
res = map (fmap parseType) resS
|
res = map (fmap parseType) resS
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE ConstraintKinds #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE FunctionalDependencies #-}
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
@ -165,36 +166,41 @@ import Text.Blaze.Html (preEscapedToMarkup, toHtml)
|
|||||||
|
|
||||||
import Control.Monad.Trans.Resource (ResourceT)
|
import Control.Monad.Trans.Resource (ResourceT)
|
||||||
import Data.Dynamic (fromDynamic, toDyn)
|
import Data.Dynamic (fromDynamic, toDyn)
|
||||||
import qualified Data.IORef as I
|
import qualified Data.IORef.Lifted as I
|
||||||
import Data.Maybe (listToMaybe)
|
import Data.Maybe (listToMaybe)
|
||||||
import Data.Typeable (Typeable, typeOf)
|
import Data.Typeable (Typeable, typeOf)
|
||||||
import Yesod.Core.Class.Handler
|
import Yesod.Core.Class.Handler
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Yesod.Routes.Class (Route)
|
import Yesod.Routes.Class (Route)
|
||||||
|
import Control.Failure (failure)
|
||||||
|
|
||||||
get :: HandlerState m => m GHState
|
get :: MonadHandler m => m GHState
|
||||||
get = getGHState
|
get = liftHandlerT $ HandlerT $ I.readIORef . handlerState
|
||||||
|
|
||||||
put :: HandlerState m => GHState -> m ()
|
put :: MonadHandler m => GHState -> m ()
|
||||||
put = putGHState
|
put x = liftHandlerT $ HandlerT $ flip I.writeIORef x . handlerState
|
||||||
|
|
||||||
modify :: HandlerState m => (GHState -> GHState) -> m ()
|
modify :: MonadHandler m => (GHState -> GHState) -> m ()
|
||||||
modify = stateGHState . (((), ) .)
|
modify f = liftHandlerT $ HandlerT $ flip I.modifyIORef f . handlerState
|
||||||
|
|
||||||
tell :: HandlerState m => Endo [Header] -> m ()
|
tell :: MonadHandler m => Endo [Header] -> m ()
|
||||||
tell hs = modify $ \g -> g { ghsHeaders = ghsHeaders g `mappend` hs }
|
tell hs = modify $ \g -> g { ghsHeaders = ghsHeaders g `mappend` hs }
|
||||||
|
|
||||||
hcError :: HandlerError m => ErrorResponse -> m a
|
handlerError :: MonadHandler m => HandlerContents -> m a
|
||||||
|
handlerError = liftHandlerT . failure
|
||||||
|
|
||||||
|
hcError :: MonadHandler m => ErrorResponse -> m a
|
||||||
hcError = handlerError . HCError
|
hcError = handlerError . HCError
|
||||||
|
|
||||||
getRequest :: HandlerReader m => m YesodRequest
|
getRequest :: MonadHandler m => m YesodRequest
|
||||||
getRequest = askYesodRequest
|
getRequest = liftHandlerT $ HandlerT $ return . handlerRequest
|
||||||
|
|
||||||
runRequestBody :: (MonadResource m, HandlerReader m, HandlerState m)
|
runRequestBody :: MonadHandler m => m RequestBodyContents
|
||||||
=> m RequestBodyContents
|
|
||||||
runRequestBody = do
|
runRequestBody = do
|
||||||
RunHandlerEnv {..} <- askHandlerEnv
|
HandlerData
|
||||||
req <- askYesodRequest
|
{ handlerEnv = RunHandlerEnv {..}
|
||||||
|
, handlerRequest = req
|
||||||
|
} <- liftHandlerT $ HandlerT return
|
||||||
let len = W.requestBodyLength $ reqWaiRequest req
|
let len = W.requestBodyLength $ reqWaiRequest req
|
||||||
upload = rheUpload len
|
upload = rheUpload len
|
||||||
x <- get
|
x <- get
|
||||||
@ -232,25 +238,28 @@ rbHelper' backend mkFI req =
|
|||||||
| otherwise = a'
|
| otherwise = a'
|
||||||
go = decodeUtf8With lenientDecode
|
go = decodeUtf8With lenientDecode
|
||||||
|
|
||||||
|
askHandlerEnv :: MonadHandler m => m (RunHandlerEnv (HandlerSite m))
|
||||||
|
askHandlerEnv = liftHandlerT $ HandlerT $ return . handlerEnv
|
||||||
|
|
||||||
-- | Get the master site appliation argument.
|
-- | Get the master site appliation argument.
|
||||||
getYesod :: HandlerReader m => m (HandlerSite m)
|
getYesod :: MonadHandler m => m (HandlerSite m)
|
||||||
getYesod = rheSite `liftM` askHandlerEnv
|
getYesod = rheSite `liftM` askHandlerEnv
|
||||||
|
|
||||||
-- | Get the URL rendering function.
|
-- | Get the URL rendering function.
|
||||||
getUrlRender :: HandlerReader m => m (Route (HandlerSite m) -> Text)
|
getUrlRender :: MonadHandler m => m (Route (HandlerSite m) -> Text)
|
||||||
getUrlRender = do
|
getUrlRender = do
|
||||||
x <- rheRender `liftM` askHandlerEnv
|
x <- rheRender `liftM` askHandlerEnv
|
||||||
return $ flip x []
|
return $ flip x []
|
||||||
|
|
||||||
-- | The URL rendering function with query-string parameters.
|
-- | The URL rendering function with query-string parameters.
|
||||||
getUrlRenderParams
|
getUrlRenderParams
|
||||||
:: HandlerReader m
|
:: MonadHandler m
|
||||||
=> m (Route (HandlerSite m) -> [(Text, Text)] -> Text)
|
=> m (Route (HandlerSite m) -> [(Text, Text)] -> Text)
|
||||||
getUrlRenderParams = rheRender `liftM` askHandlerEnv
|
getUrlRenderParams = rheRender `liftM` askHandlerEnv
|
||||||
|
|
||||||
-- | Get the route requested by the user. If this is a 404 response- where the
|
-- | Get the route requested by the user. If this is a 404 response- where the
|
||||||
-- user requested an invalid route- this function will return 'Nothing'.
|
-- user requested an invalid route- this function will return 'Nothing'.
|
||||||
getCurrentRoute :: HandlerReader m => m (Maybe (Route (HandlerSite m)))
|
getCurrentRoute :: MonadHandler m => m (Maybe (Route (HandlerSite m)))
|
||||||
getCurrentRoute = rheRoute `liftM` askHandlerEnv
|
getCurrentRoute = rheRoute `liftM` askHandlerEnv
|
||||||
|
|
||||||
-- | Returns a function that runs 'HandlerT' actions inside @IO@.
|
-- | Returns a function that runs 'HandlerT' actions inside @IO@.
|
||||||
@ -332,7 +341,7 @@ handlerToIO =
|
|||||||
--
|
--
|
||||||
-- If you want direct control of the final status code, or need a different
|
-- If you want direct control of the final status code, or need a different
|
||||||
-- status code, please use 'redirectWith'.
|
-- status code, please use 'redirectWith'.
|
||||||
redirect :: (HandlerError m, RedirectUrl (HandlerSite m) url, HandlerReader m)
|
redirect :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
||||||
=> url -> m a
|
=> url -> m a
|
||||||
redirect url = do
|
redirect url = do
|
||||||
req <- waiRequest
|
req <- waiRequest
|
||||||
@ -343,7 +352,7 @@ redirect url = do
|
|||||||
redirectWith status url
|
redirectWith status url
|
||||||
|
|
||||||
-- | Redirect to the given URL with the specified status code.
|
-- | Redirect to the given URL with the specified status code.
|
||||||
redirectWith :: (HandlerError m, RedirectUrl (HandlerSite m) url, HandlerReader m)
|
redirectWith :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
||||||
=> H.Status
|
=> H.Status
|
||||||
-> url
|
-> url
|
||||||
-> m a
|
-> m a
|
||||||
@ -358,7 +367,7 @@ ultDestKey = "_ULT"
|
|||||||
--
|
--
|
||||||
-- An ultimate destination is stored in the user session and can be loaded
|
-- An ultimate destination is stored in the user session and can be loaded
|
||||||
-- later by 'redirectUltDest'.
|
-- later by 'redirectUltDest'.
|
||||||
setUltDest :: (HandlerState m, RedirectUrl (HandlerSite m) url)
|
setUltDest :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
||||||
=> url
|
=> url
|
||||||
-> m ()
|
-> m ()
|
||||||
setUltDest url = do
|
setUltDest url = do
|
||||||
@ -369,19 +378,19 @@ setUltDest url = do
|
|||||||
--
|
--
|
||||||
-- If this is a 404 handler, there is no current page, and then this call does
|
-- If this is a 404 handler, there is no current page, and then this call does
|
||||||
-- nothing.
|
-- nothing.
|
||||||
setUltDestCurrent :: HandlerState m => m ()
|
setUltDestCurrent :: MonadHandler m => m ()
|
||||||
setUltDestCurrent = do
|
setUltDestCurrent = do
|
||||||
route <- getCurrentRoute
|
route <- getCurrentRoute
|
||||||
case route of
|
case route of
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
Just r -> do
|
Just r -> do
|
||||||
gets' <- reqGetParams `liftM` askYesodRequest
|
gets' <- reqGetParams `liftM` getRequest
|
||||||
setUltDest (r, gets')
|
setUltDest (r, gets')
|
||||||
|
|
||||||
-- | Sets the ultimate destination to the referer request header, if present.
|
-- | Sets the ultimate destination to the referer request header, if present.
|
||||||
--
|
--
|
||||||
-- This function will not overwrite an existing ultdest.
|
-- This function will not overwrite an existing ultdest.
|
||||||
setUltDestReferer :: HandlerState m => m ()
|
setUltDestReferer :: MonadHandler m => m ()
|
||||||
setUltDestReferer = do
|
setUltDestReferer = do
|
||||||
mdest <- lookupSession ultDestKey
|
mdest <- lookupSession ultDestKey
|
||||||
maybe
|
maybe
|
||||||
@ -398,7 +407,7 @@ setUltDestReferer = do
|
|||||||
--
|
--
|
||||||
-- This function uses 'redirect', and thus will perform a temporary redirect to
|
-- This function uses 'redirect', and thus will perform a temporary redirect to
|
||||||
-- a GET request.
|
-- a GET request.
|
||||||
redirectUltDest :: (RedirectUrl (HandlerSite m) url, HandlerState m, HandlerError m)
|
redirectUltDest :: (RedirectUrl (HandlerSite m) url, MonadHandler m)
|
||||||
=> url -- ^ default destination if nothing in session
|
=> url -- ^ default destination if nothing in session
|
||||||
-> m a
|
-> m a
|
||||||
redirectUltDest def = do
|
redirectUltDest def = do
|
||||||
@ -407,7 +416,7 @@ redirectUltDest def = do
|
|||||||
maybe (redirect def) redirect mdest
|
maybe (redirect def) redirect mdest
|
||||||
|
|
||||||
-- | Remove a previously set ultimate destination. See 'setUltDest'.
|
-- | Remove a previously set ultimate destination. See 'setUltDest'.
|
||||||
clearUltDest :: HandlerState m => m ()
|
clearUltDest :: MonadHandler m => m ()
|
||||||
clearUltDest = deleteSession ultDestKey
|
clearUltDest = deleteSession ultDestKey
|
||||||
|
|
||||||
msgKey :: Text
|
msgKey :: Text
|
||||||
@ -416,13 +425,13 @@ msgKey = "_MSG"
|
|||||||
-- | Sets a message in the user's session.
|
-- | Sets a message in the user's session.
|
||||||
--
|
--
|
||||||
-- See 'getMessage'.
|
-- See 'getMessage'.
|
||||||
setMessage :: HandlerState m => Html -> m ()
|
setMessage :: MonadHandler m => Html -> m ()
|
||||||
setMessage = setSession msgKey . T.concat . TL.toChunks . RenderText.renderHtml
|
setMessage = setSession msgKey . T.concat . TL.toChunks . RenderText.renderHtml
|
||||||
|
|
||||||
-- | Sets a message in the user's session.
|
-- | Sets a message in the user's session.
|
||||||
--
|
--
|
||||||
-- See 'getMessage'.
|
-- See 'getMessage'.
|
||||||
setMessageI :: (HandlerState m, RenderMessage (HandlerSite m) msg)
|
setMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
||||||
=> msg -> m ()
|
=> msg -> m ()
|
||||||
setMessageI msg = do
|
setMessageI msg = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
@ -432,7 +441,7 @@ setMessageI msg = do
|
|||||||
-- variable.
|
-- variable.
|
||||||
--
|
--
|
||||||
-- See 'setMessage'.
|
-- See 'setMessage'.
|
||||||
getMessage :: HandlerState m => m (Maybe Html)
|
getMessage :: MonadHandler m => m (Maybe Html)
|
||||||
getMessage = do
|
getMessage = do
|
||||||
mmsg <- liftM (fmap preEscapedToMarkup) $ lookupSession msgKey
|
mmsg <- liftM (fmap preEscapedToMarkup) $ lookupSession msgKey
|
||||||
deleteSession msgKey
|
deleteSession msgKey
|
||||||
@ -442,11 +451,11 @@ getMessage = do
|
|||||||
--
|
--
|
||||||
-- For some backends, this is more efficient than reading in the file to
|
-- For some backends, this is more efficient than reading in the file to
|
||||||
-- memory, since they can optimize file sending via a system call to sendfile.
|
-- memory, since they can optimize file sending via a system call to sendfile.
|
||||||
sendFile :: HandlerError m => ContentType -> FilePath -> m a
|
sendFile :: MonadHandler m => ContentType -> FilePath -> m a
|
||||||
sendFile ct fp = handlerError $ HCSendFile ct fp Nothing
|
sendFile ct fp = handlerError $ HCSendFile ct fp Nothing
|
||||||
|
|
||||||
-- | Same as 'sendFile', but only sends part of a file.
|
-- | Same as 'sendFile', but only sends part of a file.
|
||||||
sendFilePart :: HandlerError m
|
sendFilePart :: MonadHandler m
|
||||||
=> ContentType
|
=> ContentType
|
||||||
-> FilePath
|
-> FilePath
|
||||||
-> Integer -- ^ offset
|
-> Integer -- ^ offset
|
||||||
@ -457,17 +466,17 @@ sendFilePart ct fp off count =
|
|||||||
|
|
||||||
-- | Bypass remaining handler code and output the given content with a 200
|
-- | Bypass remaining handler code and output the given content with a 200
|
||||||
-- status code.
|
-- status code.
|
||||||
sendResponse :: (HandlerError m, ToTypedContent c) => c -> m a
|
sendResponse :: (MonadHandler m, ToTypedContent c) => c -> m a
|
||||||
sendResponse = handlerError . HCContent H.status200 . toTypedContent
|
sendResponse = handlerError . HCContent H.status200 . toTypedContent
|
||||||
|
|
||||||
-- | Bypass remaining handler code and output the given content with the given
|
-- | Bypass remaining handler code and output the given content with the given
|
||||||
-- status code.
|
-- status code.
|
||||||
sendResponseStatus :: (HandlerError m, ToTypedContent c) => H.Status -> c -> m a
|
sendResponseStatus :: (MonadHandler m, ToTypedContent c) => H.Status -> c -> m a
|
||||||
sendResponseStatus s = handlerError . HCContent s . toTypedContent
|
sendResponseStatus s = handlerError . HCContent s . toTypedContent
|
||||||
|
|
||||||
-- | Send a 201 "Created" response with the given route as the Location
|
-- | Send a 201 "Created" response with the given route as the Location
|
||||||
-- response header.
|
-- response header.
|
||||||
sendResponseCreated :: HandlerError m => Route (HandlerSite m) -> m a
|
sendResponseCreated :: MonadHandler m => Route (HandlerSite m) -> m a
|
||||||
sendResponseCreated url = do
|
sendResponseCreated url = do
|
||||||
r <- getUrlRender
|
r <- getUrlRender
|
||||||
handlerError $ HCCreated $ r url
|
handlerError $ HCCreated $ r url
|
||||||
@ -477,25 +486,25 @@ sendResponseCreated url = do
|
|||||||
-- that you have already specified. This function short-circuits. It should be
|
-- that you have already specified. This function short-circuits. It should be
|
||||||
-- considered only for very specific needs. If you are not sure if you need it,
|
-- considered only for very specific needs. If you are not sure if you need it,
|
||||||
-- you don't.
|
-- you don't.
|
||||||
sendWaiResponse :: HandlerError m => W.Response -> m b
|
sendWaiResponse :: MonadHandler m => W.Response -> m b
|
||||||
sendWaiResponse = handlerError . HCWai
|
sendWaiResponse = handlerError . HCWai
|
||||||
|
|
||||||
-- | Return a 404 not found page. Also denotes no handler available.
|
-- | Return a 404 not found page. Also denotes no handler available.
|
||||||
notFound :: HandlerError m => m a
|
notFound :: MonadHandler m => m a
|
||||||
notFound = hcError NotFound
|
notFound = hcError NotFound
|
||||||
|
|
||||||
-- | Return a 405 method not supported page.
|
-- | Return a 405 method not supported page.
|
||||||
badMethod :: HandlerError m => m a
|
badMethod :: MonadHandler m => m a
|
||||||
badMethod = do
|
badMethod = do
|
||||||
w <- waiRequest
|
w <- waiRequest
|
||||||
hcError $ BadMethod $ W.requestMethod w
|
hcError $ BadMethod $ W.requestMethod w
|
||||||
|
|
||||||
-- | Return a 403 permission denied page.
|
-- | Return a 403 permission denied page.
|
||||||
permissionDenied :: HandlerError m => Text -> m a
|
permissionDenied :: MonadHandler m => Text -> m a
|
||||||
permissionDenied = hcError . PermissionDenied
|
permissionDenied = hcError . PermissionDenied
|
||||||
|
|
||||||
-- | Return a 403 permission denied page.
|
-- | Return a 403 permission denied page.
|
||||||
permissionDeniedI :: (RenderMessage (HandlerSite m) msg, HandlerError m)
|
permissionDeniedI :: (RenderMessage (HandlerSite m) msg, MonadHandler m)
|
||||||
=> msg
|
=> msg
|
||||||
-> m a
|
-> m a
|
||||||
permissionDeniedI msg = do
|
permissionDeniedI msg = do
|
||||||
@ -503,11 +512,11 @@ permissionDeniedI msg = do
|
|||||||
permissionDenied $ mr msg
|
permissionDenied $ mr msg
|
||||||
|
|
||||||
-- | Return a 400 invalid arguments page.
|
-- | Return a 400 invalid arguments page.
|
||||||
invalidArgs :: HandlerError m => [Text] -> m a
|
invalidArgs :: MonadHandler m => [Text] -> m a
|
||||||
invalidArgs = hcError . InvalidArgs
|
invalidArgs = hcError . InvalidArgs
|
||||||
|
|
||||||
-- | Return a 400 invalid arguments page.
|
-- | Return a 400 invalid arguments page.
|
||||||
invalidArgsI :: (HandlerError m, RenderMessage (HandlerSite m) msg) => [msg] -> m a
|
invalidArgsI :: (MonadHandler m, RenderMessage (HandlerSite m) msg) => [msg] -> m a
|
||||||
invalidArgsI msg = do
|
invalidArgsI msg = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
invalidArgs $ map mr msg
|
invalidArgs $ map mr msg
|
||||||
@ -515,7 +524,7 @@ invalidArgsI msg = do
|
|||||||
------- Headers
|
------- Headers
|
||||||
-- | Set the cookie on the client.
|
-- | Set the cookie on the client.
|
||||||
|
|
||||||
setCookie :: HandlerState m => SetCookie -> m ()
|
setCookie :: MonadHandler m => SetCookie -> m ()
|
||||||
setCookie = addHeader . AddCookie
|
setCookie = addHeader . AddCookie
|
||||||
|
|
||||||
-- | Helper function for setCookieExpires value
|
-- | Helper function for setCookieExpires value
|
||||||
@ -531,7 +540,7 @@ getExpires m = do
|
|||||||
--
|
--
|
||||||
-- Note: although the value used for key and path is 'Text', you should only
|
-- Note: although the value used for key and path is 'Text', you should only
|
||||||
-- use ASCII values to be HTTP compliant.
|
-- use ASCII values to be HTTP compliant.
|
||||||
deleteCookie :: HandlerState m
|
deleteCookie :: MonadHandler m
|
||||||
=> Text -- ^ key
|
=> Text -- ^ key
|
||||||
-> Text -- ^ path
|
-> Text -- ^ path
|
||||||
-> m ()
|
-> m ()
|
||||||
@ -540,19 +549,19 @@ deleteCookie a = addHeader . DeleteCookie (encodeUtf8 a) . encodeUtf8
|
|||||||
|
|
||||||
-- | Set the language in the user session. Will show up in 'languages' on the
|
-- | Set the language in the user session. Will show up in 'languages' on the
|
||||||
-- next request.
|
-- next request.
|
||||||
setLanguage :: HandlerState m => Text -> m ()
|
setLanguage :: MonadHandler m => Text -> m ()
|
||||||
setLanguage = setSession langKey
|
setLanguage = setSession langKey
|
||||||
|
|
||||||
-- | Set an arbitrary response header.
|
-- | Set an arbitrary response header.
|
||||||
--
|
--
|
||||||
-- Note that, while the data type used here is 'Text', you must provide only
|
-- Note that, while the data type used here is 'Text', you must provide only
|
||||||
-- ASCII value to be HTTP compliant.
|
-- ASCII value to be HTTP compliant.
|
||||||
setHeader :: HandlerState m => Text -> Text -> m ()
|
setHeader :: MonadHandler m => Text -> Text -> m ()
|
||||||
setHeader a = addHeader . Header (encodeUtf8 a) . encodeUtf8
|
setHeader a = addHeader . Header (encodeUtf8 a) . encodeUtf8
|
||||||
|
|
||||||
-- | Set the Cache-Control header to indicate this response should be cached
|
-- | Set the Cache-Control header to indicate this response should be cached
|
||||||
-- for the given number of seconds.
|
-- for the given number of seconds.
|
||||||
cacheSeconds :: HandlerState m => Int -> m ()
|
cacheSeconds :: MonadHandler m => Int -> m ()
|
||||||
cacheSeconds i = setHeader "Cache-Control" $ T.concat
|
cacheSeconds i = setHeader "Cache-Control" $ T.concat
|
||||||
[ "max-age="
|
[ "max-age="
|
||||||
, T.pack $ show i
|
, T.pack $ show i
|
||||||
@ -561,16 +570,16 @@ cacheSeconds i = setHeader "Cache-Control" $ T.concat
|
|||||||
|
|
||||||
-- | Set the Expires header to some date in 2037. In other words, this content
|
-- | Set the Expires header to some date in 2037. In other words, this content
|
||||||
-- is never (realistically) expired.
|
-- is never (realistically) expired.
|
||||||
neverExpires :: HandlerState m => m ()
|
neverExpires :: MonadHandler m => m ()
|
||||||
neverExpires = setHeader "Expires" "Thu, 31 Dec 2037 23:55:55 GMT"
|
neverExpires = setHeader "Expires" "Thu, 31 Dec 2037 23:55:55 GMT"
|
||||||
|
|
||||||
-- | Set an Expires header in the past, meaning this content should not be
|
-- | Set an Expires header in the past, meaning this content should not be
|
||||||
-- cached.
|
-- cached.
|
||||||
alreadyExpired :: HandlerState m => m ()
|
alreadyExpired :: MonadHandler m => m ()
|
||||||
alreadyExpired = setHeader "Expires" "Thu, 01 Jan 1970 05:05:05 GMT"
|
alreadyExpired = setHeader "Expires" "Thu, 01 Jan 1970 05:05:05 GMT"
|
||||||
|
|
||||||
-- | Set an Expires header to the given date.
|
-- | Set an Expires header to the given date.
|
||||||
expiresAt :: HandlerState m => UTCTime -> m ()
|
expiresAt :: MonadHandler m => UTCTime -> m ()
|
||||||
expiresAt = setHeader "Expires" . formatRFC1123
|
expiresAt = setHeader "Expires" . formatRFC1123
|
||||||
|
|
||||||
-- | Set a variable in the user's session.
|
-- | Set a variable in the user's session.
|
||||||
@ -578,40 +587,40 @@ expiresAt = setHeader "Expires" . formatRFC1123
|
|||||||
-- The session is handled by the clientsession package: it sets an encrypted
|
-- The session is handled by the clientsession package: it sets an encrypted
|
||||||
-- and hashed cookie on the client. This ensures that all data is secure and
|
-- and hashed cookie on the client. This ensures that all data is secure and
|
||||||
-- not tampered with.
|
-- not tampered with.
|
||||||
setSession :: HandlerState m
|
setSession :: MonadHandler m
|
||||||
=> Text -- ^ key
|
=> Text -- ^ key
|
||||||
-> Text -- ^ value
|
-> Text -- ^ value
|
||||||
-> m ()
|
-> m ()
|
||||||
setSession k = setSessionBS k . encodeUtf8
|
setSession k = setSessionBS k . encodeUtf8
|
||||||
|
|
||||||
-- | Same as 'setSession', but uses binary data for the value.
|
-- | Same as 'setSession', but uses binary data for the value.
|
||||||
setSessionBS :: HandlerState m
|
setSessionBS :: MonadHandler m
|
||||||
=> Text
|
=> Text
|
||||||
-> S.ByteString
|
-> S.ByteString
|
||||||
-> m ()
|
-> m ()
|
||||||
setSessionBS k = modify . modSession . Map.insert k
|
setSessionBS k = modify . modSession . Map.insert k
|
||||||
|
|
||||||
-- | Unsets a session variable. See 'setSession'.
|
-- | Unsets a session variable. See 'setSession'.
|
||||||
deleteSession :: HandlerState m => Text -> m ()
|
deleteSession :: MonadHandler m => Text -> m ()
|
||||||
deleteSession = modify . modSession . Map.delete
|
deleteSession = modify . modSession . Map.delete
|
||||||
|
|
||||||
-- | Clear all session variables.
|
-- | Clear all session variables.
|
||||||
--
|
--
|
||||||
-- Since: 1.0.1
|
-- Since: 1.0.1
|
||||||
clearSession :: HandlerState m => m ()
|
clearSession :: MonadHandler m => m ()
|
||||||
clearSession = modify $ \x -> x { ghsSession = Map.empty }
|
clearSession = modify $ \x -> x { ghsSession = Map.empty }
|
||||||
|
|
||||||
modSession :: (SessionMap -> SessionMap) -> GHState -> GHState
|
modSession :: (SessionMap -> SessionMap) -> GHState -> GHState
|
||||||
modSession f x = x { ghsSession = f $ ghsSession x }
|
modSession f x = x { ghsSession = f $ ghsSession x }
|
||||||
|
|
||||||
-- | Internal use only, not to be confused with 'setHeader'.
|
-- | Internal use only, not to be confused with 'setHeader'.
|
||||||
addHeader :: HandlerState m => Header -> m ()
|
addHeader :: MonadHandler m => Header -> m ()
|
||||||
addHeader = tell . Endo . (:)
|
addHeader = tell . Endo . (:)
|
||||||
|
|
||||||
-- | Some value which can be turned into a URL for redirects.
|
-- | Some value which can be turned into a URL for redirects.
|
||||||
class RedirectUrl master a where
|
class RedirectUrl master a where
|
||||||
-- | Converts the value to the URL and a list of query-string parameters.
|
-- | Converts the value to the URL and a list of query-string parameters.
|
||||||
toTextUrl :: (HandlerReader m, HandlerSite m ~ master) => a -> m Text
|
toTextUrl :: (MonadHandler m, HandlerSite m ~ master) => a -> m Text
|
||||||
|
|
||||||
instance RedirectUrl master Text where
|
instance RedirectUrl master Text where
|
||||||
toTextUrl = return
|
toTextUrl = return
|
||||||
@ -633,21 +642,21 @@ instance (key ~ Text, val ~ Text) => RedirectUrl master (Route master, Map.Map k
|
|||||||
toTextUrl (url, params) = toTextUrl (url, Map.toList params)
|
toTextUrl (url, params) = toTextUrl (url, Map.toList params)
|
||||||
|
|
||||||
-- | Lookup for session data.
|
-- | Lookup for session data.
|
||||||
lookupSession :: HandlerState m => Text -> m (Maybe Text)
|
lookupSession :: MonadHandler m => Text -> m (Maybe Text)
|
||||||
lookupSession = (liftM . fmap) (decodeUtf8With lenientDecode) . lookupSessionBS
|
lookupSession = (liftM . fmap) (decodeUtf8With lenientDecode) . lookupSessionBS
|
||||||
|
|
||||||
-- | Lookup for session data in binary format.
|
-- | Lookup for session data in binary format.
|
||||||
lookupSessionBS :: HandlerState m => Text -> m (Maybe S.ByteString)
|
lookupSessionBS :: MonadHandler m => Text -> m (Maybe S.ByteString)
|
||||||
lookupSessionBS n = do
|
lookupSessionBS n = do
|
||||||
m <- liftM ghsSession get
|
m <- liftM ghsSession get
|
||||||
return $ Map.lookup n m
|
return $ Map.lookup n m
|
||||||
|
|
||||||
-- | Get all session variables.
|
-- | Get all session variables.
|
||||||
getSession :: HandlerState m => m SessionMap
|
getSession :: MonadHandler m => m SessionMap
|
||||||
getSession = liftM ghsSession get
|
getSession = liftM ghsSession get
|
||||||
|
|
||||||
-- | Get a unique identifier.
|
-- | Get a unique identifier.
|
||||||
newIdent :: HandlerState m => m Text
|
newIdent :: MonadHandler m => m Text
|
||||||
newIdent = do
|
newIdent = do
|
||||||
x <- get
|
x <- get
|
||||||
let i' = ghsIdent x + 1
|
let i' = ghsIdent x + 1
|
||||||
@ -660,7 +669,7 @@ newIdent = do
|
|||||||
-- POST form, and some Javascript to automatically submit the form. This can be
|
-- POST form, and some Javascript to automatically submit the form. This can be
|
||||||
-- useful when you need to post a plain link somewhere that needs to cause
|
-- useful when you need to post a plain link somewhere that needs to cause
|
||||||
-- changes on the server.
|
-- changes on the server.
|
||||||
redirectToPost :: (HandlerError m, RedirectUrl (HandlerSite m) url)
|
redirectToPost :: (MonadHandler m, RedirectUrl (HandlerSite m) url)
|
||||||
=> url
|
=> url
|
||||||
-> m a
|
-> m a
|
||||||
redirectToPost url = do
|
redirectToPost url = do
|
||||||
@ -680,14 +689,14 @@ $doctype 5
|
|||||||
|] >>= sendResponse
|
|] >>= sendResponse
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
hamletToRepHtml :: HandlerReader m => HtmlUrl (Route (HandlerSite m)) -> m Html
|
hamletToRepHtml :: MonadHandler m => HtmlUrl (Route (HandlerSite m)) -> m Html
|
||||||
hamletToRepHtml = giveUrlRenderer
|
hamletToRepHtml = giveUrlRenderer
|
||||||
|
|
||||||
-- | Provide a URL rendering function to the given function and return the
|
-- | Provide a URL rendering function to the given function and return the
|
||||||
-- result. Useful for processing Shakespearean templates.
|
-- result. Useful for processing Shakespearean templates.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
giveUrlRenderer :: HandlerReader m
|
giveUrlRenderer :: MonadHandler m
|
||||||
=> ((Route (HandlerSite m) -> [(Text, Text)] -> Text) -> output)
|
=> ((Route (HandlerSite m) -> [(Text, Text)] -> Text) -> output)
|
||||||
-> m output
|
-> m output
|
||||||
giveUrlRenderer f = do
|
giveUrlRenderer f = do
|
||||||
@ -695,10 +704,10 @@ giveUrlRenderer f = do
|
|||||||
return $ f render
|
return $ f render
|
||||||
|
|
||||||
-- | Get the request\'s 'W.Request' value.
|
-- | Get the request\'s 'W.Request' value.
|
||||||
waiRequest :: HandlerReader m => m W.Request
|
waiRequest :: MonadHandler m => m W.Request
|
||||||
waiRequest = reqWaiRequest `liftM` getRequest
|
waiRequest = reqWaiRequest `liftM` getRequest
|
||||||
|
|
||||||
getMessageRender :: (HandlerReader m, RenderMessage (HandlerSite m) message)
|
getMessageRender :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
||||||
=> m (message -> Text)
|
=> m (message -> Text)
|
||||||
getMessageRender = do
|
getMessageRender = do
|
||||||
env <- askHandlerEnv
|
env <- askHandlerEnv
|
||||||
@ -710,7 +719,7 @@ getMessageRender = do
|
|||||||
-- newtype wrappers to distinguish logically different types.
|
-- newtype wrappers to distinguish logically different types.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
cached :: (HandlerState m, Typeable a)
|
cached :: (MonadHandler m, Typeable a)
|
||||||
=> m a
|
=> m a
|
||||||
-> m a
|
-> m a
|
||||||
cached f = do
|
cached f = do
|
||||||
@ -751,41 +760,41 @@ cached f = do
|
|||||||
-- If a matching language is not found the default language will be used.
|
-- If a matching language is not found the default language will be used.
|
||||||
--
|
--
|
||||||
-- This is handled by parseWaiRequest (not exposed).
|
-- This is handled by parseWaiRequest (not exposed).
|
||||||
languages :: HandlerReader m => m [Text]
|
languages :: MonadHandler m => m [Text]
|
||||||
languages = reqLangs `liftM` getRequest
|
languages = reqLangs `liftM` getRequest
|
||||||
|
|
||||||
lookup' :: Eq a => a -> [(a, b)] -> [b]
|
lookup' :: Eq a => a -> [(a, b)] -> [b]
|
||||||
lookup' a = map snd . filter (\x -> a == fst x)
|
lookup' a = map snd . filter (\x -> a == fst x)
|
||||||
|
|
||||||
-- | Lookup for GET parameters.
|
-- | Lookup for GET parameters.
|
||||||
lookupGetParams :: HandlerReader m => Text -> m [Text]
|
lookupGetParams :: MonadHandler m => Text -> m [Text]
|
||||||
lookupGetParams pn = do
|
lookupGetParams pn = do
|
||||||
rr <- getRequest
|
rr <- getRequest
|
||||||
return $ lookup' pn $ reqGetParams rr
|
return $ lookup' pn $ reqGetParams rr
|
||||||
|
|
||||||
-- | Lookup for GET parameters.
|
-- | Lookup for GET parameters.
|
||||||
lookupGetParam :: HandlerReader m => Text -> m (Maybe Text)
|
lookupGetParam :: MonadHandler m => Text -> m (Maybe Text)
|
||||||
lookupGetParam = liftM listToMaybe . lookupGetParams
|
lookupGetParam = liftM listToMaybe . lookupGetParams
|
||||||
|
|
||||||
-- | Lookup for POST parameters.
|
-- | Lookup for POST parameters.
|
||||||
lookupPostParams :: (MonadResource m, HandlerState m) => Text -> m [Text]
|
lookupPostParams :: (MonadResource m, MonadHandler m) => Text -> m [Text]
|
||||||
lookupPostParams pn = do
|
lookupPostParams pn = do
|
||||||
(pp, _) <- runRequestBody
|
(pp, _) <- runRequestBody
|
||||||
return $ lookup' pn pp
|
return $ lookup' pn pp
|
||||||
|
|
||||||
lookupPostParam :: (MonadResource m, HandlerState m)
|
lookupPostParam :: (MonadResource m, MonadHandler m)
|
||||||
=> Text
|
=> Text
|
||||||
-> m (Maybe Text)
|
-> m (Maybe Text)
|
||||||
lookupPostParam = liftM listToMaybe . lookupPostParams
|
lookupPostParam = liftM listToMaybe . lookupPostParams
|
||||||
|
|
||||||
-- | Lookup for POSTed files.
|
-- | Lookup for POSTed files.
|
||||||
lookupFile :: (HandlerState m, MonadResource m)
|
lookupFile :: (MonadHandler m, MonadResource m)
|
||||||
=> Text
|
=> Text
|
||||||
-> m (Maybe FileInfo)
|
-> m (Maybe FileInfo)
|
||||||
lookupFile = liftM listToMaybe . lookupFiles
|
lookupFile = liftM listToMaybe . lookupFiles
|
||||||
|
|
||||||
-- | Lookup for POSTed files.
|
-- | Lookup for POSTed files.
|
||||||
lookupFiles :: (HandlerState m, MonadResource m)
|
lookupFiles :: (MonadHandler m, MonadResource m)
|
||||||
=> Text
|
=> Text
|
||||||
-> m [FileInfo]
|
-> m [FileInfo]
|
||||||
lookupFiles pn = do
|
lookupFiles pn = do
|
||||||
@ -793,11 +802,11 @@ lookupFiles pn = do
|
|||||||
return $ lookup' pn files
|
return $ lookup' pn files
|
||||||
|
|
||||||
-- | Lookup for cookie data.
|
-- | Lookup for cookie data.
|
||||||
lookupCookie :: HandlerReader m => Text -> m (Maybe Text)
|
lookupCookie :: MonadHandler m => Text -> m (Maybe Text)
|
||||||
lookupCookie = liftM listToMaybe . lookupCookies
|
lookupCookie = liftM listToMaybe . lookupCookies
|
||||||
|
|
||||||
-- | Lookup for cookie data.
|
-- | Lookup for cookie data.
|
||||||
lookupCookies :: HandlerReader m => Text -> m [Text]
|
lookupCookies :: MonadHandler m => Text -> m [Text]
|
||||||
lookupCookies pn = do
|
lookupCookies pn = do
|
||||||
rr <- getRequest
|
rr <- getRequest
|
||||||
return $ lookup' pn $ reqCookies rr
|
return $ lookup' pn $ reqCookies rr
|
||||||
@ -823,11 +832,11 @@ lookupCookies pn = do
|
|||||||
-- provided inside this do-block. Should be used together with 'provideRep'.
|
-- provided inside this do-block. Should be used together with 'provideRep'.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
selectRep :: HandlerReader m
|
selectRep :: MonadHandler m
|
||||||
=> Writer.Writer (Endo [ProvidedRep m]) ()
|
=> Writer.Writer (Endo [ProvidedRep m]) ()
|
||||||
-> m TypedContent
|
-> m TypedContent
|
||||||
selectRep w = do
|
selectRep w = do
|
||||||
cts <- liftM reqAccept askYesodRequest
|
cts <- liftM reqAccept getRequest
|
||||||
case mapMaybe tryAccept cts of
|
case mapMaybe tryAccept cts of
|
||||||
[] ->
|
[] ->
|
||||||
case reps of
|
case reps of
|
||||||
@ -885,7 +894,7 @@ provideRepType ct handler =
|
|||||||
-- | Stream in the raw request body without any parsing.
|
-- | Stream in the raw request body without any parsing.
|
||||||
--
|
--
|
||||||
-- Since 1.2.0
|
-- Since 1.2.0
|
||||||
rawRequestBody :: (HandlerReader m, MonadResource m) => Source m S.ByteString
|
rawRequestBody :: (MonadHandler m, MonadResource m) => Source m S.ByteString
|
||||||
rawRequestBody = do
|
rawRequestBody = do
|
||||||
req <- lift waiRequest
|
req <- lift waiRequest
|
||||||
transPipe liftResourceT $ W.requestBody req
|
transPipe liftResourceT $ W.requestBody req
|
||||||
|
|||||||
@ -20,8 +20,9 @@ module Yesod.Core.Json
|
|||||||
, acceptsJson
|
, acceptsJson
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Core.Handler (HandlerT, waiRequest, invalidArgs, redirect, selectRep, provideRep)
|
import Yesod.Core.Handler (HandlerT, getRequest, invalidArgs, redirect, selectRep, provideRep, rawRequestBody)
|
||||||
import Yesod.Core.Content (TypedContent)
|
import Yesod.Core.Content (TypedContent)
|
||||||
|
import Yesod.Core.Types (reqAccept)
|
||||||
import Yesod.Core.Class.Yesod (defaultLayout, Yesod)
|
import Yesod.Core.Class.Yesod (defaultLayout, Yesod)
|
||||||
import Yesod.Core.Class.Handler
|
import Yesod.Core.Class.Handler
|
||||||
import Yesod.Core.Widget (WidgetT)
|
import Yesod.Core.Widget (WidgetT)
|
||||||
@ -67,19 +68,16 @@ jsonToRepJson = return . J.toJSON
|
|||||||
-- 'J.Value'@.
|
-- 'J.Value'@.
|
||||||
--
|
--
|
||||||
-- /Since: 0.3.0/
|
-- /Since: 0.3.0/
|
||||||
parseJsonBody :: (MonadResource m, HandlerReader m, J.FromJSON a) => m (J.Result a)
|
parseJsonBody :: (MonadHandler m, J.FromJSON a) => m (J.Result a)
|
||||||
parseJsonBody = do
|
parseJsonBody = do
|
||||||
req <- waiRequest
|
eValue <- runExceptionT $ rawRequestBody $$ sinkParser JP.value'
|
||||||
eValue <- runExceptionT
|
|
||||||
$ transPipe liftResourceT (requestBody req)
|
|
||||||
$$ sinkParser JP.value'
|
|
||||||
return $ case eValue of
|
return $ case eValue of
|
||||||
Left e -> J.Error $ show e
|
Left e -> J.Error $ show e
|
||||||
Right value -> J.fromJSON value
|
Right value -> J.fromJSON value
|
||||||
|
|
||||||
-- | Same as 'parseJsonBody', but return an invalid args response on a parse
|
-- | Same as 'parseJsonBody', but return an invalid args response on a parse
|
||||||
-- error.
|
-- error.
|
||||||
parseJsonBody_ :: (HandlerError m, J.FromJSON a, MonadResource m) => m a
|
parseJsonBody_ :: (MonadHandler m, J.FromJSON a) => m a
|
||||||
parseJsonBody_ = do
|
parseJsonBody_ = do
|
||||||
ra <- parseJsonBody
|
ra <- parseJsonBody
|
||||||
case ra of
|
case ra of
|
||||||
@ -97,8 +95,7 @@ array = J.Array . V.fromList . map J.toJSON
|
|||||||
-- @application\/json@ (e.g. AJAX, see 'acceptsJSON').
|
-- @application\/json@ (e.g. AJAX, see 'acceptsJSON').
|
||||||
--
|
--
|
||||||
-- 2. 3xx otherwise, following the PRG pattern.
|
-- 2. 3xx otherwise, following the PRG pattern.
|
||||||
jsonOrRedirect :: HandlerError m
|
jsonOrRedirect :: (MonadHandler m, J.ToJSON a)
|
||||||
=> J.ToJSON a
|
|
||||||
=> Route (HandlerSite m) -- ^ Redirect target
|
=> Route (HandlerSite m) -- ^ Redirect target
|
||||||
-> a -- ^ Data to send via JSON
|
-> a -- ^ Data to send via JSON
|
||||||
-> m J.Value
|
-> m J.Value
|
||||||
@ -109,9 +106,8 @@ jsonOrRedirect r j = do
|
|||||||
|
|
||||||
-- | Returns @True@ if the client prefers @application\/json@ as
|
-- | Returns @True@ if the client prefers @application\/json@ as
|
||||||
-- indicated by the @Accept@ HTTP header.
|
-- indicated by the @Accept@ HTTP header.
|
||||||
acceptsJson :: HandlerReader m => m Bool
|
acceptsJson :: MonadHandler m => m Bool
|
||||||
acceptsJson = (maybe False ((== "application/json") . B8.takeWhile (/= ';'))
|
acceptsJson = (maybe False ((== "application/json") . B8.takeWhile (/= ';'))
|
||||||
. join
|
. listToMaybe
|
||||||
. liftM (listToMaybe . parseHttpAccept)
|
. reqAccept)
|
||||||
. lookup "Accept" . requestHeaders)
|
`liftM` getRequest
|
||||||
`liftM` waiRequest
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import Control.Applicative (Applicative (..))
|
|||||||
import Control.Applicative ((<$>))
|
import Control.Applicative ((<$>))
|
||||||
import Control.Arrow (first)
|
import Control.Arrow (first)
|
||||||
import Control.Exception (Exception)
|
import Control.Exception (Exception)
|
||||||
import Control.Failure (Failure (..))
|
|
||||||
import Control.Monad (liftM, ap)
|
import Control.Monad (liftM, ap)
|
||||||
import Control.Monad.Base (MonadBase (liftBase))
|
import Control.Monad.Base (MonadBase (liftBase))
|
||||||
import Control.Monad.IO.Class (MonadIO (liftIO))
|
import Control.Monad.IO.Class (MonadIO (liftIO))
|
||||||
@ -424,9 +423,6 @@ instance MonadIO m => MonadLogger (HandlerT site m) where
|
|||||||
monadLoggerLog a b c d = HandlerT $ \hd ->
|
monadLoggerLog a b c d = HandlerT $ \hd ->
|
||||||
liftIO $ rheLog (handlerEnv hd) a b c (toLogStr d)
|
liftIO $ rheLog (handlerEnv hd) a b c (toLogStr d)
|
||||||
|
|
||||||
instance Failure e m => Failure e (HandlerT site m) where
|
|
||||||
failure = lift . failure
|
|
||||||
|
|
||||||
instance Monoid (UniqueList x) where
|
instance Monoid (UniqueList x) where
|
||||||
mempty = UniqueList id
|
mempty = UniqueList id
|
||||||
UniqueList x `mappend` UniqueList y = UniqueList $ x . y
|
UniqueList x `mappend` UniqueList y = UniqueList $ x . y
|
||||||
|
|||||||
@ -70,24 +70,25 @@ import qualified Data.Text.Lazy as TL
|
|||||||
|
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
import Yesod.Core.Class.Handler
|
import Yesod.Core.Class.Handler
|
||||||
|
import Text.Shakespeare.I18N (renderMessage)
|
||||||
|
|
||||||
preEscapedLazyText :: TL.Text -> Html
|
preEscapedLazyText :: TL.Text -> Html
|
||||||
preEscapedLazyText = preEscapedToMarkup
|
preEscapedLazyText = preEscapedToMarkup
|
||||||
|
|
||||||
class Monad m => ToWidget site m a where
|
class ToWidget site a where
|
||||||
toWidget :: a -> WidgetT site m ()
|
toWidget :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance (Monad m, render ~ RY site) => ToWidget site m (render -> Html) where
|
instance render ~ RY site => ToWidget site (render -> Html) where
|
||||||
toWidget x = tell $ GWData (Body x) mempty mempty mempty mempty mempty mempty
|
toWidget x = tell $ GWData (Body x) mempty mempty mempty mempty mempty mempty
|
||||||
instance (Monad m, render ~ RY site) => ToWidget site m (render -> Css) where
|
instance render ~ RY site => ToWidget site (render -> Css) where
|
||||||
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . x
|
toWidget x = toWidget $ CssBuilder . fromLazyText . renderCss . x
|
||||||
instance (Monad m, render ~ RY site) => ToWidget site m (render -> CssBuilder) where
|
instance render ~ RY site => ToWidget site (render -> CssBuilder) where
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . x) mempty mempty
|
toWidget x = tell $ GWData mempty mempty mempty mempty (Map.singleton Nothing $ unCssBuilder . x) mempty mempty
|
||||||
instance (Monad m, render ~ RY site) => ToWidget site m (render -> Javascript) where
|
instance render ~ RY site => ToWidget site (render -> Javascript) where
|
||||||
toWidget x = tell $ GWData mempty mempty mempty mempty mempty (Just x) mempty
|
toWidget x = tell $ GWData mempty mempty mempty mempty mempty (Just x) mempty
|
||||||
instance (site' ~ site, Monad m, m' ~ m) => ToWidget site' m' (WidgetT site m ()) where
|
instance (site' ~ site, IO ~ m, a ~ ()) => ToWidget site' (WidgetT site m a) where
|
||||||
toWidget = id
|
toWidget = liftWidgetT
|
||||||
instance Monad m => ToWidget site m Html where
|
instance ToWidget site Html where
|
||||||
toWidget = toWidget . const
|
toWidget = toWidget . const
|
||||||
|
|
||||||
-- | Allows adding some CSS to the page with a specific media type.
|
-- | Allows adding some CSS to the page with a specific media type.
|
||||||
@ -97,17 +98,17 @@ class ToWidgetMedia site a where
|
|||||||
-- | Add the given content to the page, but only for the given media type.
|
-- | Add the given content to the page, but only for the given media type.
|
||||||
--
|
--
|
||||||
-- Since 1.2
|
-- Since 1.2
|
||||||
toWidgetMedia :: Monad m
|
toWidgetMedia :: (MonadWidget m, HandlerSite m ~ site)
|
||||||
=> Text -- ^ media value
|
=> Text -- ^ media value
|
||||||
-> a
|
-> a
|
||||||
-> WidgetT site m ()
|
-> m ()
|
||||||
instance render ~ RY site => ToWidgetMedia site (render -> Css) where
|
instance render ~ RY site => ToWidgetMedia site (render -> Css) where
|
||||||
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . x
|
toWidgetMedia media x = toWidgetMedia media $ CssBuilder . fromLazyText . renderCss . x
|
||||||
instance render ~ RY site => ToWidgetMedia site (render -> CssBuilder) where
|
instance render ~ RY site => ToWidgetMedia site (render -> CssBuilder) where
|
||||||
toWidgetMedia media x = tell $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . x) mempty mempty
|
toWidgetMedia media x = tell $ GWData mempty mempty mempty mempty (Map.singleton (Just media) $ unCssBuilder . x) mempty mempty
|
||||||
|
|
||||||
class ToWidgetBody site a where
|
class ToWidgetBody site a where
|
||||||
toWidgetBody :: Monad m => a -> WidgetT site m ()
|
toWidgetBody :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance render ~ RY site => ToWidgetBody site (render -> Html) where
|
instance render ~ RY site => ToWidgetBody site (render -> Html) where
|
||||||
toWidgetBody = toWidget
|
toWidgetBody = toWidget
|
||||||
@ -117,7 +118,7 @@ instance ToWidgetBody site Html where
|
|||||||
toWidgetBody = toWidget
|
toWidgetBody = toWidget
|
||||||
|
|
||||||
class ToWidgetHead site a where
|
class ToWidgetHead site a where
|
||||||
toWidgetHead :: Monad m => a -> WidgetT site m ()
|
toWidgetHead :: (MonadWidget m, HandlerSite m ~ site) => a -> m ()
|
||||||
|
|
||||||
instance render ~ RY site => ToWidgetHead site (render -> Html) where
|
instance render ~ RY site => ToWidgetHead site (render -> Html) where
|
||||||
toWidgetHead = tell . GWData mempty mempty mempty mempty mempty mempty . Head
|
toWidgetHead = tell . GWData mempty mempty mempty mempty mempty mempty . Head
|
||||||
@ -132,52 +133,59 @@ instance ToWidgetHead site Html where
|
|||||||
|
|
||||||
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
||||||
-- set values.
|
-- set values.
|
||||||
setTitle :: Monad m => Html -> WidgetT site m ()
|
setTitle :: MonadWidget m => Html -> m ()
|
||||||
setTitle x = tell $ GWData mempty (Last $ Just $ Title x) mempty mempty mempty mempty mempty
|
setTitle x = tell $ GWData mempty (Last $ Just $ Title x) mempty mempty mempty mempty mempty
|
||||||
|
|
||||||
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
-- | Set the page title. Calling 'setTitle' multiple times overrides previously
|
||||||
-- set values.
|
-- set values.
|
||||||
setTitleI :: (Monad m, RenderMessage site msg) => msg -> WidgetT site m ()
|
setTitleI :: (MonadWidget m, RenderMessage (HandlerSite m) msg) => msg -> m ()
|
||||||
setTitleI msg = do
|
setTitleI msg = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
setTitle $ toHtml $ mr msg
|
setTitle $ toHtml $ mr msg
|
||||||
|
|
||||||
-- | Link to the specified local stylesheet.
|
-- | Link to the specified local stylesheet.
|
||||||
addStylesheet :: Monad m => Route site -> WidgetT site m ()
|
addStylesheet :: MonadWidget m => Route (HandlerSite m) -> m ()
|
||||||
addStylesheet = flip addStylesheetAttrs []
|
addStylesheet = flip addStylesheetAttrs []
|
||||||
|
|
||||||
-- | Link to the specified local stylesheet.
|
-- | Link to the specified local stylesheet.
|
||||||
addStylesheetAttrs :: Monad m => Route site -> [(Text, Text)] -> WidgetT site m ()
|
addStylesheetAttrs :: MonadWidget m
|
||||||
|
=> Route (HandlerSite m)
|
||||||
|
-> [(Text, Text)]
|
||||||
|
-> m ()
|
||||||
addStylesheetAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Local x) y) mempty mempty mempty
|
addStylesheetAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Local x) y) mempty mempty mempty
|
||||||
|
|
||||||
-- | Link to the specified remote stylesheet.
|
-- | Link to the specified remote stylesheet.
|
||||||
addStylesheetRemote :: Monad m => Text -> WidgetT site m ()
|
addStylesheetRemote :: MonadWidget m => Text -> m ()
|
||||||
addStylesheetRemote = flip addStylesheetRemoteAttrs []
|
addStylesheetRemote = flip addStylesheetRemoteAttrs []
|
||||||
|
|
||||||
-- | Link to the specified remote stylesheet.
|
-- | Link to the specified remote stylesheet.
|
||||||
addStylesheetRemoteAttrs :: Monad m => Text -> [(Text, Text)] -> WidgetT site m ()
|
addStylesheetRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
||||||
addStylesheetRemoteAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Remote x) y) mempty mempty mempty
|
addStylesheetRemoteAttrs x y = tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Remote x) y) mempty mempty mempty
|
||||||
|
|
||||||
addStylesheetEither :: Monad m => Either (Route site) Text -> WidgetT site m ()
|
addStylesheetEither :: MonadWidget m
|
||||||
|
=> Either (Route (HandlerSite m)) Text
|
||||||
|
-> m ()
|
||||||
addStylesheetEither = either addStylesheet addStylesheetRemote
|
addStylesheetEither = either addStylesheet addStylesheetRemote
|
||||||
|
|
||||||
addScriptEither :: Monad m => Either (Route site) Text -> WidgetT site m ()
|
addScriptEither :: MonadWidget m
|
||||||
|
=> Either (Route (HandlerSite m)) Text
|
||||||
|
-> m ()
|
||||||
addScriptEither = either addScript addScriptRemote
|
addScriptEither = either addScript addScriptRemote
|
||||||
|
|
||||||
-- | Link to the specified local script.
|
-- | Link to the specified local script.
|
||||||
addScript :: Monad m => Route site -> WidgetT site m ()
|
addScript :: MonadWidget m => Route (HandlerSite m) -> m ()
|
||||||
addScript = flip addScriptAttrs []
|
addScript = flip addScriptAttrs []
|
||||||
|
|
||||||
-- | Link to the specified local script.
|
-- | Link to the specified local script.
|
||||||
addScriptAttrs :: Monad m => Route site -> [(Text, Text)] -> WidgetT site m ()
|
addScriptAttrs :: MonadWidget m => Route (HandlerSite m) -> [(Text, Text)] -> m ()
|
||||||
addScriptAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Local x) y) mempty mempty mempty mempty
|
addScriptAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Local x) y) mempty mempty mempty mempty
|
||||||
|
|
||||||
-- | Link to the specified remote script.
|
-- | Link to the specified remote script.
|
||||||
addScriptRemote :: Monad m => Text -> WidgetT site m ()
|
addScriptRemote :: MonadWidget m => Text -> m ()
|
||||||
addScriptRemote = flip addScriptRemoteAttrs []
|
addScriptRemote = flip addScriptRemoteAttrs []
|
||||||
|
|
||||||
-- | Link to the specified remote script.
|
-- | Link to the specified remote script.
|
||||||
addScriptRemoteAttrs :: Monad m => Text -> [(Text, Text)] -> WidgetT site m ()
|
addScriptRemoteAttrs :: MonadWidget m => Text -> [(Text, Text)] -> m ()
|
||||||
addScriptRemoteAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Remote x) y) mempty mempty mempty mempty
|
addScriptRemoteAttrs x y = tell $ GWData mempty mempty (toUnique $ Script (Remote x) y) mempty mempty mempty mempty
|
||||||
|
|
||||||
whamlet :: QuasiQuoter
|
whamlet :: QuasiQuoter
|
||||||
@ -207,7 +215,7 @@ rules = do
|
|||||||
return $ NP.HamletRules ah ur $ \_ b -> return $ ah `AppE` b
|
return $ NP.HamletRules ah ur $ \_ b -> return $ ah `AppE` b
|
||||||
|
|
||||||
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
|
||||||
ihamletToRepHtml :: (HandlerReader m, RenderMessage (HandlerSite m) message)
|
ihamletToRepHtml :: (MonadHandler m, RenderMessage (HandlerSite m) message)
|
||||||
=> HtmlUrlI18n message (Route (HandlerSite m))
|
=> HtmlUrlI18n message (Route (HandlerSite m))
|
||||||
-> m Html
|
-> m Html
|
||||||
ihamletToRepHtml ih = do
|
ihamletToRepHtml ih = do
|
||||||
@ -215,8 +223,8 @@ ihamletToRepHtml ih = do
|
|||||||
mrender <- getMessageRender
|
mrender <- getMessageRender
|
||||||
return $ ih (toHtml . mrender) urender
|
return $ ih (toHtml . mrender) urender
|
||||||
|
|
||||||
tell :: Monad m => GWData (Route site) -> WidgetT site m ()
|
tell :: MonadWidget m => GWData (Route (HandlerSite m)) -> m ()
|
||||||
tell w = WidgetT $ const $ return ((), w)
|
tell w = liftWidgetT $ WidgetT $ const $ return ((), w)
|
||||||
|
|
||||||
toUnique :: x -> UniqueList x
|
toUnique :: x -> UniqueList x
|
||||||
toUnique = UniqueList . (:)
|
toUnique = UniqueList . (:)
|
||||||
|
|||||||
@ -17,17 +17,16 @@ mkYesodSub "Subsite" [] [parseRoutes|
|
|||||||
/multi/*Strings SubMultiR
|
/multi/*Strings SubMultiR
|
||||||
|]
|
|]
|
||||||
|
|
||||||
getSubRootR :: Yesod m => GHandler Subsite m RepPlain
|
getSubRootR :: Yesod master => HandlerT Subsite (HandlerT master IO) RepPlain
|
||||||
getSubRootR = do
|
getSubRootR = do
|
||||||
Subsite s <- getYesodSub
|
Subsite s <- getYesod
|
||||||
tm <- getRouteToMaster
|
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
$logDebug "I'm in SubRootR"
|
$logDebug "I'm in SubRootR"
|
||||||
return $ RepPlain $ toContent $ "Hello Sub World: " ++ s ++ ". " ++ unpack (render (tm SubRootR))
|
return $ RepPlain $ toContent $ "Hello Sub World: " ++ s ++ ". " ++ unpack (render SubRootR)
|
||||||
|
|
||||||
handleSubMultiR :: Yesod m => Strings -> GHandler Subsite m RepPlain
|
handleSubMultiR :: Yesod master => Strings -> HandlerT Subsite (HandlerT master IO) RepPlain
|
||||||
handleSubMultiR x = do
|
handleSubMultiR x = do
|
||||||
Subsite y <- getYesodSub
|
Subsite y <- getYesod
|
||||||
$logInfo "In SubMultiR"
|
$logInfo "In SubMultiR"
|
||||||
return . RepPlain . toContent . show $ (x, y)
|
return . RepPlain . toContent . show $ (x, y)
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,6 @@ import qualified Data.ByteString.Lazy as L
|
|||||||
import Data.Text (Text, unpack, pack)
|
import Data.Text (Text, unpack, pack)
|
||||||
import qualified Data.Text.Read
|
import qualified Data.Text.Read
|
||||||
|
|
||||||
import Control.Monad.Trans.Class
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Yesod.Persist (selectList, runDB, Filter, SelectOpt, YesodPersistBackend, Key, YesodPersist, PersistEntity, PersistQuery, YesodDB)
|
import Yesod.Persist (selectList, runDB, Filter, SelectOpt, YesodPersistBackend, Key, YesodPersist, PersistEntity, PersistQuery, YesodDB)
|
||||||
import Control.Arrow ((&&&))
|
import Control.Arrow ((&&&))
|
||||||
@ -482,7 +481,7 @@ data Option a = Option
|
|||||||
, optionExternalValue :: Text
|
, optionExternalValue :: Text
|
||||||
}
|
}
|
||||||
|
|
||||||
optionsPairs :: (HandlerReader m, RenderMessage (HandlerSite m) msg)
|
optionsPairs :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
||||||
=> [(msg, a)] -> m (OptionList a)
|
=> [(msg, a)] -> m (OptionList a)
|
||||||
optionsPairs opts = do
|
optionsPairs opts = do
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
@ -493,7 +492,7 @@ optionsPairs opts = do
|
|||||||
}
|
}
|
||||||
return $ mkOptionList (zipWith mkOption [1 :: Int ..] opts)
|
return $ mkOptionList (zipWith mkOption [1 :: Int ..] opts)
|
||||||
|
|
||||||
optionsEnum :: (HandlerReader m, Show a, Enum a, Bounded a) => m (OptionList a)
|
optionsEnum :: (MonadHandler m, Show a, Enum a, Bounded a) => m (OptionList a)
|
||||||
optionsEnum = optionsPairs $ map (\x -> (pack $ show x, x)) [minBound..maxBound]
|
optionsEnum = optionsPairs $ map (\x -> (pack $ show x, x)) [minBound..maxBound]
|
||||||
|
|
||||||
optionsPersist :: ( YesodPersist site, PersistEntity a
|
optionsPersist :: ( YesodPersist site, PersistEntity a
|
||||||
@ -563,7 +562,7 @@ fileField = Field
|
|||||||
, fieldEnctype = Multipart
|
, fieldEnctype = Multipart
|
||||||
}
|
}
|
||||||
|
|
||||||
fileAFormReq :: (HandlerState m, RenderMessage (HandlerSite m) FormMessage)
|
fileAFormReq :: (MonadHandler m, RenderMessage (HandlerSite m) FormMessage)
|
||||||
=> FieldSettings (HandlerSite m) -> AForm m FileInfo
|
=> FieldSettings (HandlerSite m) -> AForm m FileInfo
|
||||||
fileAFormReq fs = AForm $ \(site, langs) menvs ints -> do
|
fileAFormReq fs = AForm $ \(site, langs) menvs ints -> do
|
||||||
let (name, ints') =
|
let (name, ints') =
|
||||||
@ -595,7 +594,7 @@ $newline never
|
|||||||
}
|
}
|
||||||
return (res, (fv :), ints', Multipart)
|
return (res, (fv :), ints', Multipart)
|
||||||
|
|
||||||
fileAFormOpt :: HandlerState m
|
fileAFormOpt :: MonadHandler m
|
||||||
=> RenderMessage (HandlerSite m) FormMessage
|
=> RenderMessage (HandlerSite m) FormMessage
|
||||||
=> FieldSettings (HandlerSite m)
|
=> FieldSettings (HandlerSite m)
|
||||||
-> AForm m (Maybe FileInfo)
|
-> AForm m (Maybe FileInfo)
|
||||||
|
|||||||
@ -100,21 +100,21 @@ askFiles = do
|
|||||||
(x, _, _) <- ask
|
(x, _, _) <- ask
|
||||||
return $ liftM snd x
|
return $ liftM snd x
|
||||||
|
|
||||||
mreq :: (RenderMessage site FormMessage, HandlerSite m ~ site, HandlerState m)
|
mreq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m)
|
||||||
=> Field m a
|
=> Field m a
|
||||||
-> FieldSettings site
|
-> FieldSettings site
|
||||||
-> Maybe a
|
-> Maybe a
|
||||||
-> MForm m (FormResult a, FieldView site)
|
-> MForm m (FormResult a, FieldView site)
|
||||||
mreq field fs mdef = mhelper field fs mdef (\m l -> FormFailure [renderMessage m l MsgValueRequired]) FormSuccess True
|
mreq field fs mdef = mhelper field fs mdef (\m l -> FormFailure [renderMessage m l MsgValueRequired]) FormSuccess True
|
||||||
|
|
||||||
mopt :: (site ~ HandlerSite m, HandlerState m)
|
mopt :: (site ~ HandlerSite m, MonadHandler m)
|
||||||
=> Field m a
|
=> Field m a
|
||||||
-> FieldSettings site
|
-> FieldSettings site
|
||||||
-> Maybe (Maybe a)
|
-> Maybe (Maybe a)
|
||||||
-> MForm m (FormResult (Maybe a), FieldView site)
|
-> MForm m (FormResult (Maybe a), FieldView site)
|
||||||
mopt field fs mdef = mhelper field fs (join mdef) (const $ const $ FormSuccess Nothing) (FormSuccess . Just) False
|
mopt field fs mdef = mhelper field fs (join mdef) (const $ const $ FormSuccess Nothing) (FormSuccess . Just) False
|
||||||
|
|
||||||
mhelper :: (site ~ HandlerSite m, HandlerState m)
|
mhelper :: (site ~ HandlerSite m, MonadHandler m)
|
||||||
=> Field m a
|
=> Field m a
|
||||||
-> FieldSettings site
|
-> FieldSettings site
|
||||||
-> Maybe a
|
-> Maybe a
|
||||||
@ -156,14 +156,14 @@ mhelper Field {..} FieldSettings {..} mdef onMissing onFound isReq = do
|
|||||||
, fvRequired = isReq
|
, fvRequired = isReq
|
||||||
})
|
})
|
||||||
|
|
||||||
areq :: (RenderMessage site FormMessage, HandlerSite m ~ site, HandlerState m)
|
areq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m)
|
||||||
=> Field m a
|
=> Field m a
|
||||||
-> FieldSettings site
|
-> FieldSettings site
|
||||||
-> Maybe a
|
-> Maybe a
|
||||||
-> AForm m a
|
-> AForm m a
|
||||||
areq a b = formToAForm . liftM (second return) . mreq a b
|
areq a b = formToAForm . liftM (second return) . mreq a b
|
||||||
|
|
||||||
aopt :: HandlerState m
|
aopt :: MonadHandler m
|
||||||
=> Field m a
|
=> Field m a
|
||||||
-> FieldSettings (HandlerSite m)
|
-> FieldSettings (HandlerSite m)
|
||||||
-> Maybe (Maybe a)
|
-> Maybe (Maybe a)
|
||||||
@ -187,14 +187,14 @@ runFormGeneric form site langs env = evalRWST form (env, site, langs) (IntSingle
|
|||||||
-- For example, a common case is displaying a form on a GET request and having
|
-- For example, a common case is displaying a form on a GET request and having
|
||||||
-- the form submit to a POST page. In such a case, both the GET and POST
|
-- the form submit to a POST page. In such a case, both the GET and POST
|
||||||
-- handlers should use 'runFormPost'.
|
-- handlers should use 'runFormPost'.
|
||||||
runFormPost :: (RenderMessage (HandlerSite m) FormMessage, MonadResource m, HandlerState m)
|
runFormPost :: (RenderMessage (HandlerSite m) FormMessage, MonadResource m, MonadHandler m)
|
||||||
=> (Html -> MForm m (FormResult a, xml))
|
=> (Html -> MForm m (FormResult a, xml))
|
||||||
-> m ((FormResult a, xml), Enctype)
|
-> m ((FormResult a, xml), Enctype)
|
||||||
runFormPost form = do
|
runFormPost form = do
|
||||||
env <- postEnv
|
env <- postEnv
|
||||||
postHelper form env
|
postHelper form env
|
||||||
|
|
||||||
postHelper :: (HandlerReader m, RenderMessage (HandlerSite m) FormMessage)
|
postHelper :: (MonadHandler m, RenderMessage (HandlerSite m) FormMessage)
|
||||||
=> (Html -> MForm m (FormResult a, xml))
|
=> (Html -> MForm m (FormResult a, xml))
|
||||||
-> Maybe (Env, FileEnv)
|
-> Maybe (Env, FileEnv)
|
||||||
-> m ((FormResult a, xml), Enctype)
|
-> m ((FormResult a, xml), Enctype)
|
||||||
@ -224,12 +224,12 @@ postHelper form env = do
|
|||||||
-- page will both receive and incoming form and produce a new, blank form. For
|
-- page will both receive and incoming form and produce a new, blank form. For
|
||||||
-- general usage, you can stick with @runFormPost@.
|
-- general usage, you can stick with @runFormPost@.
|
||||||
generateFormPost
|
generateFormPost
|
||||||
:: (RenderMessage (HandlerSite m) FormMessage, HandlerReader m)
|
:: (RenderMessage (HandlerSite m) FormMessage, MonadHandler m)
|
||||||
=> (Html -> MForm m (FormResult a, xml))
|
=> (Html -> MForm m (FormResult a, xml))
|
||||||
-> m (xml, Enctype)
|
-> m (xml, Enctype)
|
||||||
generateFormPost form = first snd `liftM` postHelper form Nothing
|
generateFormPost form = first snd `liftM` postHelper form Nothing
|
||||||
|
|
||||||
postEnv :: (HandlerState m, MonadResource m)
|
postEnv :: (MonadHandler m, MonadResource m)
|
||||||
=> m (Maybe (Env, FileEnv))
|
=> m (Maybe (Env, FileEnv))
|
||||||
postEnv = do
|
postEnv = do
|
||||||
req <- getRequest
|
req <- getRequest
|
||||||
@ -240,7 +240,7 @@ postEnv = do
|
|||||||
let p' = Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) p
|
let p' = Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) p
|
||||||
return $ Just (p', Map.unionsWith (++) $ map (\(k, v) -> Map.singleton k [v]) f)
|
return $ Just (p', Map.unionsWith (++) $ map (\(k, v) -> Map.singleton k [v]) f)
|
||||||
|
|
||||||
runFormPostNoToken :: (HandlerState m, MonadResource m)
|
runFormPostNoToken :: MonadHandler m
|
||||||
=> (Html -> MForm m (FormResult a, xml))
|
=> (Html -> MForm m (FormResult a, xml))
|
||||||
-> m ((FormResult a, xml), Enctype)
|
-> m ((FormResult a, xml), Enctype)
|
||||||
runFormPostNoToken form = do
|
runFormPostNoToken form = do
|
||||||
@ -249,7 +249,7 @@ runFormPostNoToken form = do
|
|||||||
env <- postEnv
|
env <- postEnv
|
||||||
runFormGeneric (form mempty) m langs env
|
runFormGeneric (form mempty) m langs env
|
||||||
|
|
||||||
runFormGet :: HandlerReader m
|
runFormGet :: MonadHandler m
|
||||||
=> (Html -> MForm m a)
|
=> (Html -> MForm m a)
|
||||||
-> m (a, Enctype)
|
-> m (a, Enctype)
|
||||||
runFormGet form = do
|
runFormGet form = do
|
||||||
@ -260,7 +260,7 @@ runFormGet form = do
|
|||||||
Just _ -> Just (Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) gets, Map.empty)
|
Just _ -> Just (Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) gets, Map.empty)
|
||||||
getHelper form env
|
getHelper form env
|
||||||
|
|
||||||
generateFormGet :: HandlerReader m
|
generateFormGet :: MonadHandler m
|
||||||
=> (Html -> MForm m a)
|
=> (Html -> MForm m a)
|
||||||
-> m (a, Enctype)
|
-> m (a, Enctype)
|
||||||
generateFormGet form = getHelper form Nothing
|
generateFormGet form = getHelper form Nothing
|
||||||
@ -268,7 +268,7 @@ generateFormGet form = getHelper form Nothing
|
|||||||
getKey :: Text
|
getKey :: Text
|
||||||
getKey = "_hasdata"
|
getKey = "_hasdata"
|
||||||
|
|
||||||
getHelper :: HandlerReader m
|
getHelper :: MonadHandler m
|
||||||
=> (Html -> MForm m a)
|
=> (Html -> MForm m a)
|
||||||
-> Maybe (Env, FileEnv)
|
-> Maybe (Env, FileEnv)
|
||||||
-> m (a, Enctype)
|
-> m (a, Enctype)
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import Data.Text (Text)
|
|||||||
import Control.Applicative (Applicative (..))
|
import Control.Applicative (Applicative (..))
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Control.Monad (liftM)
|
import Control.Monad (liftM)
|
||||||
import Control.Monad.Trans.Resource
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
@ -53,7 +52,7 @@ iopt field name = FormInput $ \m l env fenv -> do
|
|||||||
Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e
|
Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e
|
||||||
Right x -> Right x
|
Right x -> Right x
|
||||||
|
|
||||||
runInputGet :: HandlerError m => FormInput m a -> m a
|
runInputGet :: MonadHandler m => FormInput m a -> m a
|
||||||
runInputGet (FormInput f) = do
|
runInputGet (FormInput f) = do
|
||||||
env <- liftM (toMap . reqGetParams) getRequest
|
env <- liftM (toMap . reqGetParams) getRequest
|
||||||
m <- getYesod
|
m <- getYesod
|
||||||
@ -66,7 +65,7 @@ runInputGet (FormInput f) = do
|
|||||||
toMap :: [(Text, a)] -> Map.Map Text [a]
|
toMap :: [(Text, a)] -> Map.Map Text [a]
|
||||||
toMap = Map.unionsWith (++) . map (\(x, y) -> Map.singleton x [y])
|
toMap = Map.unionsWith (++) . map (\(x, y) -> Map.singleton x [y])
|
||||||
|
|
||||||
runInputPost :: (HandlerState m, HandlerError m, MonadResource m) => FormInput m a -> m a
|
runInputPost :: MonadHandler m => FormInput m a -> m a
|
||||||
runInputPost (FormInput f) = do
|
runInputPost (FormInput f) = do
|
||||||
(env, fenv) <- liftM (toMap *** toMap) runRequestBody
|
(env, fenv) <- liftM (toMap *** toMap) runRequestBody
|
||||||
m <- getYesod
|
m <- getYesod
|
||||||
|
|||||||
@ -115,12 +115,14 @@ $(function(){$("##{rawJS theId}").autocomplete({source:"@{src}",minLength:2})});
|
|||||||
, fieldEnctype = UrlEncoded
|
, fieldEnctype = UrlEncoded
|
||||||
}
|
}
|
||||||
|
|
||||||
addScript' :: Monad m => (site -> Either (Route site) Text) -> WidgetT site m ()
|
addScript' :: (HandlerSite m ~ site, MonadWidget m) => (site -> Either (Route site) Text) -> m ()
|
||||||
addScript' f = do
|
addScript' f = do
|
||||||
y <- getYesod
|
y <- getYesod
|
||||||
addScriptEither $ f y
|
addScriptEither $ f y
|
||||||
|
|
||||||
addStylesheet' :: Monad m => (site -> Either (Route site) Text) -> WidgetT site m ()
|
addStylesheet' :: (MonadWidget m, HandlerSite m ~ site)
|
||||||
|
=> (site -> Either (Route site) Text)
|
||||||
|
-> m ()
|
||||||
addStylesheet' f = do
|
addStylesheet' f = do
|
||||||
y <- getYesod
|
y <- getYesod
|
||||||
addStylesheetEither $ f y
|
addStylesheetEither $ f y
|
||||||
|
|||||||
@ -47,7 +47,9 @@ bkLib.onDomLoaded(function(){new nicEditor({fullPanel:true}).panelInstance("#{ra
|
|||||||
where
|
where
|
||||||
showVal = either id (pack . renderHtml)
|
showVal = either id (pack . renderHtml)
|
||||||
|
|
||||||
addScript' :: Monad m => (site -> Either (Route site) Text) -> WidgetT site m ()
|
addScript' :: (MonadWidget m, HandlerSite m ~ site)
|
||||||
|
=> (site -> Either (Route site) Text)
|
||||||
|
-> m ()
|
||||||
addScript' f = do
|
addScript' f = do
|
||||||
y <- getYesod
|
y <- getYesod
|
||||||
addScriptEither $ f y
|
addScriptEither $ f y
|
||||||
|
|||||||
@ -42,7 +42,7 @@ instance HasContentType RepAtom where
|
|||||||
instance ToTypedContent RepAtom where
|
instance ToTypedContent RepAtom where
|
||||||
toTypedContent = TypedContent typeAtom . toContent
|
toTypedContent = TypedContent typeAtom . toContent
|
||||||
|
|
||||||
atomFeed :: HandlerReader m => Feed (Route (HandlerSite m)) -> m RepAtom
|
atomFeed :: MonadHandler m => Feed (Route (HandlerSite m)) -> m RepAtom
|
||||||
atomFeed feed = do
|
atomFeed feed = do
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
return $ RepAtom $ toContent $ renderLBS def $ template feed render
|
return $ RepAtom $ toContent $ renderLBS def $ template feed render
|
||||||
@ -75,10 +75,10 @@ entryTemplate FeedEntry {..} render = Element "entry" Map.empty $ map NodeElemen
|
|||||||
]
|
]
|
||||||
|
|
||||||
-- | Generates a link tag in the head of a widget.
|
-- | Generates a link tag in the head of a widget.
|
||||||
atomLink :: Monad m
|
atomLink :: MonadWidget m
|
||||||
=> Route site
|
=> Route (HandlerSite m)
|
||||||
-> Text -- ^ title
|
-> Text -- ^ title
|
||||||
-> WidgetT site m ()
|
-> m ()
|
||||||
atomLink r title = toWidgetHead [hamlet|
|
atomLink r title = toWidgetHead [hamlet|
|
||||||
<link href=@{r} type=#{S8.unpack typeAtom} rel="alternate" title=#{title}>
|
<link href=@{r} type=#{S8.unpack typeAtom} rel="alternate" title=#{title}>
|
||||||
|]
|
|]
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import Yesod.AtomFeed
|
|||||||
import Yesod.RssFeed
|
import Yesod.RssFeed
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
|
||||||
newsFeed :: HandlerReader m => Feed (Route (HandlerSite m)) -> m TypedContent
|
newsFeed :: MonadHandler m => Feed (Route (HandlerSite m)) -> m TypedContent
|
||||||
newsFeed f = selectRep $ do
|
newsFeed f = selectRep $ do
|
||||||
provideRep $ atomFeed f
|
provideRep $ atomFeed f
|
||||||
provideRep $ rssFeed f
|
provideRep $ rssFeed f
|
||||||
|
|||||||
@ -39,7 +39,7 @@ instance ToTypedContent RepRss where
|
|||||||
toTypedContent = TypedContent typeRss . toContent
|
toTypedContent = TypedContent typeRss . toContent
|
||||||
|
|
||||||
-- | Generate the feed
|
-- | Generate the feed
|
||||||
rssFeed :: HandlerReader m => Feed (Route (HandlerSite m)) -> m RepRss
|
rssFeed :: MonadHandler m => Feed (Route (HandlerSite m)) -> m RepRss
|
||||||
rssFeed feed = do
|
rssFeed feed = do
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
return $ RepRss $ toContent $ renderLBS def $ template feed render
|
return $ RepRss $ toContent $ renderLBS def $ template feed render
|
||||||
@ -71,10 +71,10 @@ entryTemplate FeedEntry {..} render = Element "item" Map.empty $ map NodeElement
|
|||||||
]
|
]
|
||||||
|
|
||||||
-- | Generates a link tag in the head of a widget.
|
-- | Generates a link tag in the head of a widget.
|
||||||
rssLink :: Monad m
|
rssLink :: MonadWidget m
|
||||||
=> Route site
|
=> Route (HandlerSite m)
|
||||||
-> Text -- ^ title
|
-> Text -- ^ title
|
||||||
-> WidgetT site m ()
|
-> m ()
|
||||||
rssLink r title = toWidgetHead [hamlet|
|
rssLink r title = toWidgetHead [hamlet|
|
||||||
<link href=@{r} type=#{S8.unpack typeRss} rel="alternate" title=#{title}>
|
<link href=@{r} type=#{S8.unpack typeRss} rel="alternate" title=#{title}>
|
||||||
|]
|
|]
|
||||||
|
|||||||
@ -75,14 +75,14 @@ template urls render =
|
|||||||
, Element "priority" Map.empty [NodeContent $ pack $ show sitemapPriority]
|
, Element "priority" Map.empty [NodeContent $ pack $ show sitemapPriority]
|
||||||
]
|
]
|
||||||
|
|
||||||
sitemap :: HandlerReader m => [SitemapUrl (Route (HandlerSite m))] -> m RepXml
|
sitemap :: MonadHandler m => [SitemapUrl (Route (HandlerSite m))] -> m RepXml
|
||||||
sitemap urls = do
|
sitemap urls = do
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
let doc = template urls render
|
let doc = template urls render
|
||||||
return $ RepXml $ toContent $ renderLBS def doc
|
return $ RepXml $ toContent $ renderLBS def doc
|
||||||
|
|
||||||
-- | A basic robots file which just lists the "Sitemap: " line.
|
-- | A basic robots file which just lists the "Sitemap: " line.
|
||||||
robots :: HandlerReader m
|
robots :: MonadHandler m
|
||||||
=> Route (HandlerSite m) -- ^ sitemap url
|
=> Route (HandlerSite m) -- ^ sitemap url
|
||||||
-> m RepPlain
|
-> m RepPlain
|
||||||
robots smurl = do
|
robots smurl = do
|
||||||
|
|||||||
@ -6,8 +6,8 @@ module Yesod.Default.Handlers
|
|||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
|
||||||
getFaviconR :: HandlerError m => m ()
|
getFaviconR :: MonadHandler m => m ()
|
||||||
getFaviconR = sendFile "image/x-icon" "config/favicon.ico"
|
getFaviconR = sendFile "image/x-icon" "config/favicon.ico"
|
||||||
|
|
||||||
getRobotsR :: HandlerError m => m ()
|
getRobotsR :: MonadHandler m => m ()
|
||||||
getRobotsR = sendFile "text/plain" "config/robots.txt"
|
getRobotsR = sendFile "text/plain" "config/robots.txt"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user