-- | Module providing a snap backend for the digestive-functors library
--
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, Rank2Types #-}
module Text.Digestive.Forms.Snap
( SnapInput
, SnapForm
, snapEnvironment
, eitherSnapForm
) where
import Control.Applicative ((<$>))
import Control.Monad (liftM)
import Data.ByteString as SB
import Data.ByteString.UTF8 as SB (toString, fromString)
import Snap.Types
import Text.Digestive.Forms (FormInput (..))
import Text.Digestive.Types (Form (..), Environment (..), viewForm, eitherForm)
newtype SnapInput = SnapInput {unSnapInput :: SB.ByteString}
instance FormInput SnapInput () where
getInputString = Just . SB.toString . unSnapInput
getInputFile = const Nothing
-- | Simplification of the `Form` type, instantiated to Snap
--
type SnapForm e v a = (MonadSnap m) => Form m SnapInput e v a
-- | Environment that will fetch input from the parameters parsed by Snap
--
snapEnvironment :: (MonadSnap m) => Environment m SnapInput
snapEnvironment = Environment $ \id' -> do
input' <- getParam (SB.fromString $ show id')
return $ SnapInput <$> input'
-- | Run a snap form
--
-- * When we are responding to a GET request, you will simply receive the form
-- as a view
--
-- * When we are responding to another request method, the form data will be
-- used. When errors occur, you will receive the form as a view, otherwise,
-- you will get the actual result
--
eitherSnapForm :: (MonadSnap m)
=> SnapForm e v a -- ^ Form
-> String -- ^ Form name
-> m (Either v a) -- ^ Result
eitherSnapForm form name = do
method' <- rqMethod <$> getRequest
case method' of GET -> liftM Left $ viewForm form name
_ -> eitherForm form name snapEnvironment