{-# LANGUAGE OverloadedStrings #-}{-# LANGUAGE TypeFamilies #-}{-# LANGUAGE ExistentialQuantification #-}moduleYesod.Form.Types(-- * HelpersEnctype(..),FormResult(..),FormMessage(..),Env,FileEnv,Ints(..)-- * Form,MForm,AForm(..)-- * Build forms,Field(..),FieldSettings(..),FieldView(..))whereimportControl.Monad.Trans.RWS(RWST)importYesod.Request(FileInfo)importData.Text(Text)importData.Monoid(Monoid(..))importText.Blaze(Html,ToHtml(toHtml))importControl.Applicative((<$>),Applicative(..))importControl.Monad(liftM)importData.String(IsString(..))importYesod.Core(GHandler,GWidget,SomeMessage)importqualifiedData.MapasMap-- | A form can produce three different results: there was no data available,-- the data was invalid, or there was a successful parse.---- The 'Applicative' instance will concatenate the failure messages in two-- 'FormResult's.dataFormResulta=FormMissing|FormFailure[Text]|FormSuccessaderivingShowinstanceFunctorFormResultwherefmap_FormMissing=FormMissingfmap_(FormFailureerrs)=FormFailureerrsfmapf(FormSuccessa)=FormSuccess$fainstanceApplicativeFormResultwherepure=FormSuccess(FormSuccessf)<*>(FormSuccessg)=FormSuccess$fg(FormFailurex)<*>(FormFailurey)=FormFailure$x++y(FormFailurex)<*>_=FormFailurex_<*>(FormFailurey)=FormFailurey_<*>_=FormMissinginstanceMonoidm=>Monoid(FormResultm)wheremempty=purememptymappendxy=mappend<$>x<*>y-- | The encoding type required by a form. The 'ToHtml' instance produces values-- that can be inserted directly into HTML.dataEnctype=UrlEncoded|Multipartderiving(Eq,Enum,Bounded)instanceToHtmlEnctypewheretoHtmlUrlEncoded="application/x-www-form-urlencoded"toHtmlMultipart="multipart/form-data"instanceMonoidEnctypewheremempty=UrlEncodedmappendUrlEncodedUrlEncoded=UrlEncodedmappend__=MultipartdataInts=IntConsIntInts|IntSingleIntinstanceShowIntswhereshow(IntSinglei)=showishow(IntConsiis)=showi++('-':showis)typeEnv=Map.MapText[Text]typeFileEnv=Map.MapTextFileInfotypeLang=TexttypeMFormsubmastera=RWST(Maybe(Env,FileEnv),master,[Lang])EnctypeInts(GHandlersubmaster)anewtypeAFormsubmastera=AForm{unAForm::(master,[Text])->Maybe(Env,FileEnv)->Ints->GHandlersubmaster(FormResulta,[FieldViewsubmaster]->[FieldViewsubmaster],Ints,Enctype)}instanceFunctor(AFormsubmaster)wherefmapf(AForma)=AForm$\xyz->liftMgo$axyzwherego(w,x,y,z)=(fmapfw,x,y,z)instanceApplicative(AFormsubmaster)wherepurex=AForm$const$const$\ints->return(FormSuccessx,mempty,ints,mempty)(AFormf)<*>(AFormg)=AForm$\mrenvints->do(a,b,ints',c)<-fmrenvints(x,y,ints'',z)<-gmrenvints'return(a<*>x,b`mappend`y,ints'',c`mappend`z)instanceMonoida=>Monoid(AFormsubmastera)wheremempty=purememptymappendab=mappend<$>a<*>bdataFieldSettingsmsg=FieldSettings{fsLabel::msg-- FIXME switch to SomeMessage?,fsTooltip::Maybemsg,fsId::MaybeText,fsName::MaybeText,fsClass::[Text]}instance(a~Text)=>IsString(FieldSettingsa)wherefromStrings=FieldSettings(fromStrings)NothingNothingNothing[]dataFieldViewsubmaster=FieldView{fvLabel::Html,fvTooltip::MaybeHtml,fvId::Text,fvInput::GWidgetsubmaster(),fvErrors::MaybeHtml,fvRequired::Bool}dataFieldsubmastera=Field{fieldParse::[Text]->GHandlersubmaster(Either(SomeMessagemaster)(Maybea))-- | ID, name, class, (invalid text OR legimiate result), required?,fieldView::Text->Text->[Text]->EitherTexta->Bool->GWidgetsubmaster()}dataFormMessage=MsgInvalidIntegerText|MsgInvalidNumberText|MsgInvalidEntryText|MsgInvalidUrlText|MsgInvalidEmailText|MsgInvalidTimeFormat|MsgInvalidHourText|MsgInvalidMinuteText|MsgInvalidSecondText|MsgInvalidDay|MsgCsrfWarning|MsgValueRequired|MsgInputNotFoundText|MsgSelectNone|MsgInvalidBoolText|MsgBoolYes|MsgBoolNo|MsgDelete