yesod-form 1.4.1.1 → 1.4.2
raw patch · 6 files changed
+104/−16 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Yesod.Form.Fields: timeFieldTypeText :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay
+ Yesod.Form.Fields: timeFieldTypeTime :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay
+ Yesod.Form.I18n.Dutch: dutchFormMessage :: FormMessage -> Text
- Yesod.Form.Functions: runFormPostNoToken :: MonadHandler m => (Markup -> MForm m (FormResult a, xml)) -> m ((FormResult a, xml), Enctype)
+ Yesod.Form.Functions: runFormPostNoToken :: MonadHandler m => (Markup -> MForm m a) -> m (a, Enctype)
Files
- ChangeLog.md +4/−0
- README.md +4/−0
- Yesod/Form/Fields.hs +64/−13
- Yesod/Form/Functions.hs +2/−2
- Yesod/Form/I18n/Dutch.hs +26/−0
- yesod-form.cabal +4/−1
+ ChangeLog.md view
@@ -0,0 +1,4 @@+## 1.4.2++Added `timeFieldTypeTime` and `timeFieldTypeText`, and deprecated `timeField`+itself.
+ README.md view
@@ -0,0 +1,4 @@+## yesod-form++Form handling for Yesod, in the same style as formlets. See [the forms+chapter](http://www.yesodweb.com/book/forms) of the Yesod book.
Yesod/Form/Fields.hs view
@@ -4,6 +4,11 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE CPP #-}+-- | Field functions allow you to easily create and validate forms, cleanly handling the uncertainty of parsing user input.+--+-- When possible, the field functions use a specific input type (e.g. "number"), allowing supporting browsers to validate the input before form submission. Browsers can also improve usability with this information; for example, mobile browsers might present a specialized keyboard for an input of type "email" or "number".+--+-- See the Yesod book <http://www.yesodweb.com/book/forms chapter on forms> for a broader overview of forms in Yesod. module Yesod.Form.Fields ( -- * i18n FormMessage (..)@@ -16,6 +21,8 @@ , intField , dayField , timeField+ , timeFieldTypeTime+ , timeFieldTypeText , htmlField , emailField , multiEmailField@@ -99,7 +106,7 @@ defaultFormMessage :: FormMessage -> Text defaultFormMessage = englishFormMessage -+-- | Creates a input with @type="number"@ and @step=1@. intField :: (Monad m, Integral i, RenderMessage (HandlerSite m) FormMessage) => Field m i intField = Field { fieldParse = parseHelper $ \s ->@@ -117,6 +124,7 @@ showVal = either id (pack . showI) showI x = show (fromIntegral x :: Integer) +-- | Creates a input with @type="number"@ and @step=any@. doubleField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Double doubleField = Field { fieldParse = parseHelper $ \s ->@@ -132,6 +140,9 @@ } where showVal = either id (pack . show) +-- | Creates an input with @type="date"@, validating the input using the 'parseDate' function.+--+-- Add the @time@ package and import the "Data.Time.Calendar" module to use this function. dayField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Day dayField = Field { fieldParse = parseHelper $ parseDate . unpack@@ -143,12 +154,33 @@ } where showVal = either id (pack . show) +-- | An alias for 'timeFieldTypeText'. timeField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay-timeField = Field+timeField = timeFieldTypeText+{-# DEPRECATED timeField "'timeField' currently defaults to an input of type=\"text\". In the next major release, it will default to type=\"time\". To opt in to the new functionality, use 'timeFieldTypeTime'. To keep the existing behavior, use 'timeFieldTypeText'. See 'https://github.com/yesodweb/yesod/pull/874' for details." #-}++-- | Creates an input with @type="time"@. <http://caniuse.com/#search=time%20input%20type Browsers not supporting this type> will fallback to a text field, and Yesod will parse the time as described in 'timeFieldTypeText'.+-- +-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.+--+-- Since 1.4.2+timeFieldTypeTime :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay +timeFieldTypeTime = timeFieldOfType "time"++-- | Creates an input with @type="text"@, parsing the time from an [H]H:MM[:SS] format, with an optional AM or PM (if not given, AM is assumed for compatibility with the 24 hour clock system).+-- +-- Add the @time@ package and import the "Data.Time.LocalTime" module to use this function.+--+-- Since 1.4.2+timeFieldTypeText :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m TimeOfDay+timeFieldTypeText = timeFieldOfType "text"++timeFieldOfType :: Monad m => RenderMessage (HandlerSite m) FormMessage => Text -> Field m TimeOfDay+timeFieldOfType inputType = Field { fieldParse = parseHelper parseTime , fieldView = \theId name attrs val isReq -> toWidget [hamlet| $newline never-<input id="#{theId}" name="#{name}" *{attrs} :isReq:required="" value="#{showVal val}">+<input id="#{theId}" name="#{name}" *{attrs} type="#{inputType}" :isReq:required="" value="#{showVal val}"> |] , fieldEnctype = UrlEncoded }@@ -159,6 +191,7 @@ where fullSec = fromInteger $ floor $ todSec tod +-- | Creates a @\<textarea>@ tag whose input is sanitized to prevent XSS attacks and is validated for having balanced tags. htmlField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Html htmlField = Field { fieldParse = parseHelper $ Right . preEscapedText . sanitizeBalance@@ -170,8 +203,11 @@ } where showVal = either id (pack . renderHtml) --- | A newtype wrapper around a 'Text' that converts newlines to HTML--- br-tags.+-- | A newtype wrapper around a 'Text' whose 'ToMarkup' instance converts newlines to HTML @\<br>@ tags.+-- +-- (When text is entered into a @\<textarea>@, newline characters are used to separate lines.+-- If this text is then placed verbatim into HTML, the lines won't be separated, thus the need for replacing with @\<br>@ tags).+-- If you don't need this functionality, simply use 'unTextarea' to access the raw text. newtype Textarea = Textarea { unTextarea :: Text } deriving (Show, Read, Eq, PersistField, Ord, ToJSON, FromJSON) instance PersistFieldSql Textarea where@@ -190,6 +226,7 @@ writeHtmlEscapedChar '\n' = writeByteString "<br>" writeHtmlEscapedChar c = B.writeHtmlEscapedChar c +-- | Creates a @\<textarea>@ tag whose returned value is wrapped in a 'Textarea'; see 'Textarea' for details. textareaField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Textarea textareaField = Field { fieldParse = parseHelper $ Right . Textarea@@ -200,6 +237,7 @@ , fieldEnctype = UrlEncoded } +-- | Creates an input with @type="hidden"@; you can use this to store information in a form that users shouldn't see (for example, Yesod stores CSRF tokens in a hidden field). hiddenField :: (Monad m, PathPiece p, RenderMessage (HandlerSite m) FormMessage) => Field m p hiddenField = Field@@ -211,6 +249,7 @@ , fieldEnctype = UrlEncoded } +-- | Creates a input with @type="text"@. textField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text textField = Field { fieldParse = parseHelper $ Right@@ -221,7 +260,7 @@ |] , fieldEnctype = UrlEncoded }-+-- | Creates an input with @type="password"@. passwordField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text passwordField = Field { fieldParse = parseHelper $ Right@@ -237,6 +276,7 @@ (x, _):_ -> Just x [] -> Nothing +-- | Parses a 'Day' from a 'String'. parseDate :: String -> Either FormMessage Day parseDate = maybe (Left MsgInvalidDay) Right . readMay . replace '/' '-'@@ -292,7 +332,8 @@ if i < 0 || i >= 60 then fail $ show $ msg $ pack xy else return $ fromIntegral (i :: Int)-+ +-- | Creates an input with @type="email"@. Yesod will validate the email's correctness according to RFC5322 and canonicalize it by removing comments and whitespace (see "Text.Email.Validate"). emailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text emailField = Field { fieldParse = parseHelper $@@ -307,7 +348,7 @@ , fieldEnctype = UrlEncoded } --- |+-- | Creates an input with @type="email"@ with the <http://www.w3.org/html/wg/drafts/html/master/forms.html#the-multiple-attribute multiple> attribute; browsers might implement this as taking a comma separated list of emails. Each email address is validated as described in 'emailField'. -- -- Since 1.3.7 multiEmailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m [Text]@@ -333,6 +374,7 @@ emailToText = decodeUtf8With lenientDecode . Email.toByteString type AutoFocus = Bool+-- | Creates an input with @type="search"@. For <http://caniuse.com/#search=autofocus browsers without autofocus support>, a JS fallback is used if @AutoFocus@ is true. searchField :: Monad m => RenderMessage (HandlerSite m) FormMessage => AutoFocus -> Field m Text searchField autoFocus = Field { fieldParse = parseHelper Right@@ -353,7 +395,7 @@ |] , fieldEnctype = UrlEncoded }-+-- | Creates an input with @type="url"@, validating the URL according to RFC3986. urlField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Text urlField = Field { fieldParse = parseHelper $ \s ->@@ -467,6 +509,13 @@ \#{text} |]) +-- | Creates a group of radio buttons to answer the question given in the message. Radio buttons are used to allow differentiating between an empty response (@Nothing@) and a no response (@Just False@). Consider using the simpler 'checkBoxField' if you don't need to make this distinction.+--+-- If this field is optional, the first radio button is labeled "\<None>", the second \"Yes" and the third \"No".+--+-- If this field is required, the first radio button is labeled \"Yes" and the second \"No". +--+-- (Exact label titles will depend on localization). boolField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool boolField = Field { fieldParse = \e _ -> return $ boolParser e@@ -498,10 +547,11 @@ t -> Left $ SomeMessage $ MsgInvalidBool t showVal = either (\_ -> False) --- | While the default @'boolField'@ implements a radio button so you--- can differentiate between an empty response (Nothing) and a no--- response (Just False), this simpler checkbox field returns an empty--- response as Just False.+-- | Creates an input with @type="checkbox"@. +-- While the default @'boolField'@ implements a radio button so you+-- can differentiate between an empty response (@Nothing@) and a no+-- response (@Just False@), this simpler checkbox field returns an empty+-- response as @Just False@. -- -- Note that this makes the field always optional. --@@ -635,6 +685,7 @@ Nothing -> Left $ SomeMessage $ MsgInvalidEntry x Just y -> Right $ Just y +-- | Creates an input with @type="file"@. fileField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m FileInfo fileField = Field
Yesod/Form/Functions.hs view
@@ -254,8 +254,8 @@ return $ Just (p', Map.unionsWith (++) $ map (\(k, v) -> Map.singleton k [v]) f) runFormPostNoToken :: MonadHandler m- => (Html -> MForm m (FormResult a, xml))- -> m ((FormResult a, xml), Enctype)+ => (Html -> MForm m a)+ -> m (a, Enctype) runFormPostNoToken form = do langs <- languages m <- getYesod
+ Yesod/Form/I18n/Dutch.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE OverloadedStrings #-}+module Yesod.Form.I18n.Dutch where++import Yesod.Form.Types (FormMessage (..))+import Data.Monoid (mappend)+import Data.Text (Text)++dutchFormMessage :: FormMessage -> Text+dutchFormMessage (MsgInvalidInteger t) = "Ongeldig aantal: " `mappend` t+dutchFormMessage (MsgInvalidNumber t) = "Ongeldig getal: " `mappend` t+dutchFormMessage (MsgInvalidEntry t) = "Ongeldige invoer: " `mappend` t+dutchFormMessage MsgInvalidTimeFormat = "Ongeldige tijd, het juiste formaat is (UU:MM[:SS])"+dutchFormMessage MsgInvalidDay = "Ongeldige datum, het juiste formaat is (JJJJ-MM-DD)"+dutchFormMessage (MsgInvalidUrl t) = "Ongeldige URL: " `mappend` t+dutchFormMessage (MsgInvalidEmail t) = "Ongeldig e-mail adres: " `mappend` t+dutchFormMessage (MsgInvalidHour t) = "Ongeldig uur: " `mappend` t+dutchFormMessage (MsgInvalidMinute t) = "Ongeldige minuut: " `mappend` t+dutchFormMessage (MsgInvalidSecond t) = "Ongeldige seconde: " `mappend` t+dutchFormMessage MsgCsrfWarning = "Bevestig het indienen van het formulier, dit als veiligheidsmaatregel tegen \"cross-site request forgery\" aanvallen."+dutchFormMessage MsgValueRequired = "Verplicht veld"+dutchFormMessage (MsgInputNotFound t) = "Geen invoer gevonden: " `mappend` t+dutchFormMessage MsgSelectNone = "<Geen>"+dutchFormMessage (MsgInvalidBool t) = "Ongeldige waarheidswaarde: " `mappend` t+dutchFormMessage MsgBoolYes = "Ja"+dutchFormMessage MsgBoolNo = "Nee"+dutchFormMessage MsgDelete = "Verwijderen?"
yesod-form.cabal view
@@ -1,5 +1,5 @@ name: yesod-form-version: 1.4.1.1+version: 1.4.2 license: MIT license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>@@ -11,6 +11,8 @@ build-type: Simple homepage: http://www.yesodweb.com/ description: Form handling support for Yesod Web Framework+extra-source-files: ChangeLog.md+ README.md flag network-uri description: Get Network.URI from the network-uri package@@ -63,6 +65,7 @@ Yesod.Form.I18n.Japanese Yesod.Form.I18n.Czech Yesod.Form.I18n.Russian+ Yesod.Form.I18n.Dutch -- FIXME Yesod.Helpers.Crud ghc-options: -Wall